diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/hppa/dev/pdc.c | 199 |
1 files changed, 124 insertions, 75 deletions
diff --git a/sys/arch/hppa/dev/pdc.c b/sys/arch/hppa/dev/pdc.c index 7f4053c469e..e266930356a 100644 --- a/sys/arch/hppa/dev/pdc.c +++ b/sys/arch/hppa/dev/pdc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pdc.c,v 1.9 1999/09/07 03:25:13 mickey Exp $ */ +/* $OpenBSD: pdc.c,v 1.10 1999/11/26 16:48:28 mickey Exp $ */ /* * Copyright (c) 1998,1999 Michael Shalayeff @@ -23,8 +23,8 @@ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF MIND, + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @@ -58,6 +58,7 @@ char pdc_consbuf[IODC_MINIOSIZ] PDC_ALIGNMENT; iodcio_t pdc_cniodc, pdc_kbdiodc; pz_device_t *pz_kbd, *pz_cons; struct tty *pdc_tty[1]; +int CONADDR; int pdcmatch __P((struct device *, void *, void*)); void pdcattach __P((struct device *, struct device *, void *)); @@ -70,6 +71,11 @@ struct cfdriver pdc_cd = { NULL, "pdc", DV_DULL }; +void pdcstart __P((struct tty *tp)); +void pdctimeout __P((void *v)); +int pdcparam __P((struct tty *tp, struct termios *)); +int pdccnlookc __P((dev_t dev, char *cp)); + void pdc_init() { @@ -99,6 +105,7 @@ pdc_init() /* XXX make pdc current console */ cn_tab = &constab[0]; + /* TODO: detect that we are on cereal, and set CONADDR */ } int @@ -135,7 +142,48 @@ pdcopen(dev, flag, mode, p) int flag, mode; struct proc *p; { - return ENXIO; + int unit = minor(dev); + struct tty *tp; + int s; + int error = 0, setuptimeout; + + if (unit >= 1) + return ENXIO; + + s = spltty(); + + if (!pdc_tty[unit]) { + tp = pdc_tty[unit] = ttymalloc(); + tty_attach(tp); + } else + tp = pdc_tty[unit]; + + tp->t_oproc = pdcstart; + tp->t_param = pdcparam; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_WOPEN|TS_CARR_ON; + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG|CLOCAL; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = 9600; + ttsetwater(tp); + + setuptimeout = 1; + } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) { + splx(s); + return EBUSY; + } + + splx(s); + + error = (*linesw[tp->t_line].l_open)(dev, tp); + if (error == 0 && setuptimeout) + timeout(pdctimeout, tp, 1); + + return error; } int @@ -144,7 +192,13 @@ pdcclose(dev, flag, mode, p) int flag, mode; struct proc *p; { - return ENXIO; + int unit = minor(dev); + struct tty *tp = pdc_tty[unit]; + + untimeout(pdctimeout, tp); + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + return 0; } int @@ -204,16 +258,25 @@ void pdcstart(tp) struct tty *tp; { -} - -struct tty * -pdctty(dev) - dev_t dev; -{ - if (minor(dev) != 0) - panic("pdctty: bogus"); + int s; - return pdc_tty[0]; + s = spltty(); + if (tp->t_state & (TS_TTSTOP | TS_BUSY)) { + splx(s); + return; + } + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t)&tp->t_outq); + } + selwakeup(&tp->t_wsel); + } + tp->t_state |= TS_BUSY; + while (tp->t_outq.c_cc != 0) + pdccnputc(tp->t_dev, getc(&tp->t_outq)); + tp->t_state &= ~TS_BUSY; + splx(s); } int @@ -232,10 +295,34 @@ pdcstop(tp, flag) } void +pdctimeout(v) + void *v; +{ + struct tty *tp = v; + u_char c; + + while (pdccnlookc(tp->t_dev, &c)) { + if (tp->t_state & TS_ISOPEN) + (*linesw[tp->t_line].l_rint)(c, tp); + } + timeout(pdctimeout, tp, 1); +} + +struct tty * +pdctty(dev) + dev_t dev; +{ + if (minor(dev) != 0) + panic("pdctty: bogus"); + + return pdc_tty[0]; +} + +void pdccnprobe(cn) struct consdev *cn; { - cn->cn_dev = makedev(28,0); + cn->cn_dev = makedev(22,0); cn->cn_pri = CN_NORMAL; } @@ -249,43 +336,37 @@ pdccninit(cn) } int -pdccngetc(dev) +pdccnlookc(dev, cp) dev_t dev; + char *cp; { - static int stash = 0; - register int err, c, l; + int err, l; - if (!pdc) - return 0; + err = pdc_call(pdc_kbdiodc, 0, pz_kbd->pz_hpa, IODC_IO_CONSIN, + pz_kbd->pz_spa, pz_kbd->pz_layers, pdcret, 0, + pdc_consbuf, 1, 0); - if (stash) { - c = stash; - if (!(dev & 0x80)) - stash = 0; - return c; - } - - do { - err = pdc_call(pdc_kbdiodc, 0, pz_kbd->pz_hpa, - IODC_IO_CONSIN, pz_kbd->pz_spa, - pz_kbd->pz_layers, pdcret, - 0, pdc_consbuf, 1, 0); - - l = pdcret[0]; - c = pdc_consbuf[0]; + l = pdcret[0]; + *cp = pdc_consbuf[0]; #ifdef DEBUG - if (err < 0) - printf("pdccngetc: input error: %d\n", err); + if (err < 0) + printf("pdccnlookc: input error: %d\n", err); #endif - /* if we are doing ischar() report immidiatelly */ - if (dev & 0x80 && l == 0) - return (0); + return l; +} - } while(!l); +int +pdccngetc(dev) + dev_t dev; +{ + char c; - if (dev & 0x80) - stash = c; + if (!pdc) + return 0; + + while(!pdccnlookc(dev, &c)) + ; return (c); } @@ -315,35 +396,3 @@ pdccnpollc(dev, on) { } - -int -pdc_call(func, pdc_flag) - iodcio_t func; - int pdc_flag; -{ - register register_t ret, opsw; - va_list va; - int args[10], i, s; - - va_start(va, pdc_flag); - for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) - args[i] = va_arg(va, int); - va_end(va); - - if (kernelmapped) { - s = splhigh(); - opsw = set_psw(PSW_Q | - ((!pdc_flag && args[0] == PDC_PIM)? PSW_M:0)); - } - - ret = (func)((void *)args[0], args[1], args[2], args[3], args[4], - args[5], args[6], args[7], args[8], args[9]); - - if (kernelmapped) { - set_psw(opsw); - splx(s); - } - - return ret; -} - |