diff options
Diffstat (limited to 'sys/isa/sio.c')
-rw-r--r-- | sys/isa/sio.c | 326 |
1 files changed, 187 insertions, 139 deletions
diff --git a/sys/isa/sio.c b/sys/isa/sio.c index 8081ae5..9b2ddfe 100644 --- a/sys/isa/sio.c +++ b/sys/isa/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.20 1993/12/16 04:38:27 ache Exp $ + * $Id: sio.c,v 1.21 1994/01/02 10:17:29 ache Exp $ */ #include "sio.h" @@ -84,8 +84,20 @@ #define COM_MPMASTER(dev) (((dev)->id_flags >> 8) & 0x0ff) #endif /* COM_MULTIPORT */ +#ifndef FIFO_TRIGGER +/* + * This driver is fast enough to work with any value and for high values + * to be only slightly more efficient. Low values may be better because + * they give lower latency. + * TODO: always use low values for low speeds. Mouse movements are jerky + * if more than one packet arrives at once. The low speeds used for + * serial mice help avoid this, but not if (large) fifos are enabled. + */ +#define FIFO_TRIGGER FIFO_TRIGGER_14 +#endif + #define com_scr 7 /* scratch register for 16450-16550 (R/W) */ -#define schedsoftcom() (ipending |= 1 << 4) /* XXX */ +#define schedsoftcom() (ipending |= 1 << (16 + 4)) /* XXX */ /* * Input buffer watermarks. @@ -215,13 +227,6 @@ void siocnprobe __P((struct consdev *cp)); void siocnputc __P((Dev_t dev, int c)); int sioopen __P((Dev_t dev, int oflags, int devtype, struct proc *p)); -/* - * Also, most of the device switch functions are still declared old-style - * so they take a Dev_t arg and shorten it to a dev_t. It would be simpler - * and faster if dev_t's were always promoted (to ints or whatever) as - * early as possible. - */ - int sioread __P((Dev_t dev, struct uio *uio, int ioflag)); int sioselect __P((Dev_t dev, int rw, struct proc *p)); void siostop __P((struct tty *tp, int rw)); @@ -233,14 +238,14 @@ static void comflush __P((struct com_s *com)); static void comhardclose __P((struct com_s *com)); static void cominit __P((int unit, int rate)); #ifdef COM_MULTIPORT -static bool_t comintr1 __P((struct com_s *com)); +static bool_t comintr1 __P((struct com_s *com)); #endif /* COM_MULTIPORT */ -static int commctl __P((struct com_s *com, int bits, int how)); +static void commctl __P((struct com_s *com, int bits, int how)); static int comparam __P((struct tty *tp, struct termios *t)); static int sioprobe __P((struct isa_device *dev)); static void compoll __P((void)); -static void comstart __P((struct tty *tp)); -static void comwakeup __P((caddr_t chan, int ticks)); +static void comstart __P((struct tty *tp)); +static void comwakeup __P((caddr_t chan, int ticks)); static int tiocm_xxx2mcr __P((int tiocm_xxx)); /* table and macro for fast conversion from a unit number to its com struct */ @@ -305,7 +310,7 @@ static int sioprobe(dev) struct isa_device *dev; { - static bool_t already_init; + static bool_t already_init; Port_t *com_ptr; Port_t iobase; int result; @@ -324,7 +329,7 @@ sioprobe(dev) already_init = TRUE; } iobase = dev->id_iobase; - result = 1; + result = IO_COMSIZE; /* * We don't want to get actual interrupts, just masked ones. @@ -335,6 +340,11 @@ sioprobe(dev) disable_intr(); /* + * Initialize the speed so that any junk in the THR or output fifo will + * be transmitted in a known time. (There may be lots of junk after a + * soft reboot, and output interrupts don't work right after a master + * reset, at least for 16550s. (The speed is undefined after MR, but + * MR empties the THR and the TSR so it's not clear why this matters)). * Enable output interrupts (only) and check the following: * o the CFCR, IER and MCR in UART hold the values written to them * (the values happen to be all distinct - this is good for @@ -342,14 +352,14 @@ sioprobe(dev) * o an output interrupt is generated and its vector is correct. * o the interrupt goes away when the IIR in the UART is read. */ - outb(iobase + com_cfcr, CFCR_DLAB); /* DLAB = 1 */ - outb(iobase + com_dlbl, COMBRD(9600) & 0xff); /* 9600bps */ - outb(iobase + com_dlbh, ((u_int) COMBRD(9600) >> 8) & 0xff); + outb(iobase + com_cfcr, CFCR_DLAB); + outb(iobase + com_dlbl, COMBRD(9600) & 0xff); + outb(iobase + com_dlbh, (u_int) COMBRD(9600) >> 8); outb(iobase + com_cfcr, CFCR_8BITS); /* ensure IER is addressed */ outb(iobase + com_mcr, MCR_IENABLE); /* open gate early */ - outb(iobase + com_ier, 0); /* ensure edge on next intr */ + outb(iobase + com_ier, 0); /* ensure edge on next intr */ outb(iobase + com_ier, IER_ETXRDY); /* generate interrupt */ - DELAY(17000); /* wait for fifo drain on 9600 */ + DELAY((16 + 1) * 9600 / 10); /* enough to drain 16 bytes */ if ( inb(iobase + com_cfcr) != CFCR_8BITS || inb(iobase + com_ier) != IER_ETXRDY || inb(iobase + com_mcr) != MCR_IENABLE @@ -448,25 +458,25 @@ sioattach(isdp) scr2 = inb(iobase + com_scr); outb(iobase + com_scr, scr); if (scr1 != 0xa5 || scr2 != 0x5a) { - printf(" <8250>"); + printf(" 8250"); goto determined_type; } } outb(iobase + com_fifo, FIFO_ENABLE | FIFO_TRIGGER_14); DELAY(100); - switch (inb(iobase + com_iir) & IIR_FIFO_MASK) { + switch (inb(com->int_id_port) & IIR_FIFO_MASK) { case FIFO_TRIGGER_1: - printf(" <16450>"); + printf(" 16450"); break; case FIFO_TRIGGER_4: - printf(" <16450?>"); + printf(" 16450?"); break; case FIFO_TRIGGER_8: - printf(" <16550?>"); + printf(" 16550?"); break; case FIFO_TRIGGER_14: com->hasfifo = TRUE; - printf(" <16550A>"); + printf(" 16550A"); break; } outb(iobase + com_fifo, 0); @@ -483,11 +493,11 @@ determined_type: ; * as appropriate. YYY See your manual */ /* enable only common interrupt for port */ - outb(iobase + com_mcr, 0); + outb(com->modem_ctl_port, com->mcr_image = 0); masterdev = find_isadev(isa_devtab_tty, &siodriver, COM_MPMASTER(isdp)); - outb(masterdev->id_iobase+com_scr, 0x80); + outb(masterdev->id_iobase + com_scr, 0x80); } else com->multiport = FALSE; @@ -516,20 +526,16 @@ determined_type: ; /* * Need to reset baud rate, etc. of next print so reset comconsinit. - * Also make sure console is always "hardwired" */ if (unit == comconsole) comconsinit = FALSE; com_addr(unit) = com; - splx(s); - if (!comwakeup_started) { comwakeup((caddr_t) NULL, 0); comwakeup_started = TRUE; } - return (1); } @@ -541,19 +547,22 @@ sioopen(dev, flag, mode, p) int mode; struct proc *p; { +#ifdef COM_BIDIR + bool_t callout; +#endif /* COM_BIDIR */ struct com_s *com; int error = 0; Port_t iobase; int s; struct tty *tp; - int unit = UNIT(dev); -#ifdef COM_BIDIR - bool_t callout = CALLOUT(dev); -#endif /* COM_BIDIR */ + int unit; + + unit = UNIT(dev); if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) return (ENXIO); #ifdef COM_BIDIR /* if it's a callout device, and bidir not possible on that dev, die */ + callout = CALLOUT(dev); if (callout && !(com->bidir)) return (ENXIO); #endif /* COM_BIDIR */ @@ -607,22 +616,21 @@ bidir_open_top: com->active_in = TRUE; } else { /* put DTR & RTS up */ - /* NOTE: cgd'sdriver used the ier register - * to enable/disable interrupts. This one - * uses both ier and IENABLE in the mcr. - */ /* XXX - bring up RTS earlier? */ - (void) commctl(com, MCR_DTR | MCR_RTS, DMSET); + commctl(com, MCR_DTR | MCR_RTS, DMSET); outb(com->iobase + com_ier, IER_EMSC); + /* wait for it... */ error = tsleep((caddr_t)&com->active_in, TTIPRI|PCATCH, "siodcd", 0); - /* if not active, turn DTR off */ - if (!com->active) - (void) commctl(com, MCR_DTR, DMBIC); + /* if not active, turn intrs and DTR off */ + if (!com->active) { + outb(com->iobase + com_ier, 0); + commctl(com, MCR_DTR, DMBIC); + } /* if there was an error, take off. */ if (error != 0) { @@ -651,15 +659,7 @@ bidir_open_top: * since those are only relevant for logins. It's * important to have echo off initially so that the * line doesn't start blathering before the echo flag - * can be turned off. It's useful to have clocal on - * initially so that "stty changed-defaults </dev/sioX" - * doesn't hang waiting for carrier. - * - * XXX: CLOCAL is dangerous with incoming ports: - * it cause getty hangs after first login+logout. - * use "stty com_speed -clocal < /dev/comxx" - * before do anything with incoming port... - * Ache. + * can be turned off. */ tp->t_iflag = 0; #ifdef COMCONSOLE @@ -667,30 +667,53 @@ bidir_open_top: #else tp->t_oflag = 0; #endif - tp->t_cflag = CREAD | CS8 | CLOCAL; + tp->t_cflag = CREAD | CS8 | HUPCL; tp->t_lflag = 0; tp->t_ispeed = tp->t_ospeed = comdefaultrate; } + + /* + * XXX the full state after a first open() needs to be + * programmable and separate for callin and callout. + */ #ifdef COM_BIDIR if (com->bidir) { if (callout) tp->t_cflag |= CLOCAL; else tp->t_cflag &= ~CLOCAL; - tp->t_cflag |= HUPCL; } #endif - (void) commctl(com, MCR_DTR | MCR_RTS, DMSET); + + commctl(com, MCR_DTR | MCR_RTS, DMSET); error = comparam(tp, &tp->t_termios); if (error != 0) goto out; ttsetwater(tp); + + /* + * XXX temporary fix for deadlock in ttywait(). + * + * If two processes wait for output to drain from the same + * tty, and the amount of output to drain is > 0 and + * <= tp->t_lowat, then the processes will take turns + * uselessly waking each other up until the output drains, + * with cpl higher than spltty() throughout. + * + * The sleep address and TS_ASLEEP flag ought to be different + * for the different events (output done) and (output almost + * done). + */ + tp->t_lowat = 0; + iobase = com->iobase; - disable_intr(); - if (com->hasfifo) + if (com->hasfifo) { /* (re)enable and drain FIFO */ - outb(iobase + com_fifo, FIFO_ENABLE | FIFO_TRIGGER_14 + outb(iobase + com_fifo, FIFO_ENABLE | FIFO_TRIGGER | FIFO_RCV_RST | FIFO_XMT_RST); + DELAY(100); + } + disable_intr(); (void) inb(com->line_status_port); (void) inb(com->data_port); com->last_modem_status = @@ -711,9 +734,9 @@ bidir_open_top: * but it's certain we have a carrier now, so * don't spend any time on it now. */ - && !(com->bidir) + && !(com->bidir) #endif /* COM_BIDIR */ - && !(tp->t_state & TS_CARR_ON)) { + && !(tp->t_state & TS_CARR_ON)) { tp->t_state |= TS_WOPEN; error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH, ttopen, 0); @@ -776,18 +799,25 @@ comhardclose(com) iobase = com->iobase; outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); #ifdef KGDB - /* do not disable interrupts if debugging */ + /* do not disable interrupts or hang up if debugging */ if (kgdb_dev != makedev(commajor, com - &com_structs[0])) #endif + { outb(iobase + com_ier, 0); - tp = com->tp; - if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN - || !(tp->t_state & TS_ISOPEN)) { - (void) commctl(com, MCR_RTS, DMSET); - if (com->dtr_wait != 0) - /* uninterruptible since we want to wait a fixed time */ - tsleep((caddr_t)&com->dtr_wait, TTIPRI, "sioclose", - com->dtr_wait); + tp = com->tp; + if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN + || !(tp->t_state & TS_ISOPEN)) { + commctl(com, MCR_RTS, DMSET); + if (com->dtr_wait != 0) + /* + * Uninterruptible sleep since we want to + * wait a fixed time. + * XXX - delay in open() (if necessary), + * not here (always). + */ + tsleep((caddr_t)&com->dtr_wait, TTIPRI, + "sioclose", com->dtr_wait); + } } #ifdef COM_BIDIR @@ -844,16 +874,14 @@ siointr(unit) com = com_addr(unit); #else /* COM_MULTIPORT */ - int i; - bool_t donesomething; + bool_t possibly_more_intrs; /* * Loop until there is no activity on any port. This is necessary * to get an interrupt edge more than to avoid another interrupt. * If the IRQ signal is just an OR of the IRQ signals from several * devices, then the edge from one may be lost because another is - * on, or it may cause a stray interrupt because another was on a - * short time before. + * on. * * XXX getting the status from comintr1() is not best and may be * incorrect. It would be better to test the int_id's in a tight @@ -861,18 +889,19 @@ siointr(unit) * have been off at the start. */ do { - donesomething = FALSE; - for(i=0;i<NSIO;i++) { - com=com_addr(i); - if(com != NULL) { - /* XXX call comintr1() instead of here from - * com_wakeup(). The interrupt edge problem + possibly_more_intrs = FALSE; + for (unit = 0; unit < NSIO; ++unit) { + com = com_addr(unit); + if (com != NULL) { + /* + * XXX call comintr1() instead of here from + * comwakeup(). The interrupt edge problem * only exists for real interrupts. */ - donesomething |= comintr1(com); + possibly_more_intrs |= comintr1(com); } } - } while (donesomething); + } while (possibly_more_intrs); return; } @@ -917,6 +946,10 @@ comintr1(com) CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); else { ++com_events; +#if 0 +if (com->iptr - com->ibuf == 8) + schedsoftcom(); +#endif ioptr[0] = recv_data; ioptr[CE_INPUT_OFFSET] = line_status; com->iptr = ++ioptr; @@ -1025,25 +1058,24 @@ sioioctl(dev, cmd, data, flag, p) com = com_addr(UNIT(dev)); tp = com->tp; + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); - if (error >= 0) - return (error); - - iobase = com->iobase; - s = spltty(); - #ifdef COM_BIDIR /* XXX: plug security hole while stucky bits not yet implemented */ - if (com->bidir && com->active_in && p->p_ucred->cr_uid != 0) { - tp->t_cflag |= HUPCL; + if (com->bidir && com->active_in && p->p_ucred->cr_uid != 0) tp->t_cflag &= ~CLOCAL; - } #endif + if (error >= 0) { + tp->t_lowat = 0; /* XXX part of ttywait() deadlock fix */ + return (error); + } + iobase = com->iobase; + s = spltty(); switch (cmd) { case TIOCSBRK: outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); @@ -1052,19 +1084,19 @@ sioioctl(dev, cmd, data, flag, p) outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); break; case TIOCSDTR: - (void) commctl(com, MCR_DTR, DMBIS); + commctl(com, MCR_DTR, DMBIS); break; case TIOCCDTR: - (void) commctl(com, MCR_DTR, DMBIC); + commctl(com, MCR_DTR, DMBIC); break; case TIOCMSET: - (void) commctl(com, tiocm_xxx2mcr(*(int *)data), DMSET); + commctl(com, tiocm_xxx2mcr(*(int *)data), DMSET); break; case TIOCMBIS: - (void) commctl(com, tiocm_xxx2mcr(*(int *)data), DMBIS); + commctl(com, tiocm_xxx2mcr(*(int *)data), DMBIS); break; case TIOCMBIC: - (void) commctl(com, tiocm_xxx2mcr(*(int *)data), DMBIC); + commctl(com, tiocm_xxx2mcr(*(int *)data), DMBIC); break; case TIOCMGET: tiocm_xxx = TIOCM_LE; /* XXX - always enabled while open */ @@ -1080,7 +1112,11 @@ sioioctl(dev, cmd, data, flag, p) tiocm_xxx |= TIOCM_CD; if (msr & MSR_DSR) tiocm_xxx |= TIOCM_DSR; - /* XXX - MSR_TERI is too volatile. */ + /* + * XXX - MSR_RI is naturally volatile, and we make MSR_TERI + * more volatile by reading the modem status a lot. Perhaps + * we should latch both bits until the status is read here. + */ if (msr & (MSR_RI | MSR_TERI)) tiocm_xxx |= TIOCM_RI; *(int *)data = tiocm_xxx; @@ -1088,20 +1124,28 @@ sioioctl(dev, cmd, data, flag, p) #ifdef COM_BIDIR case TIOCMSBIDIR: /* must be root to set bidir. capability */ - if (p->p_ucred->cr_uid != 0) + error = suser(p->p_ucred, &p->p_acflag); + if (error != 0) { + splx(s); return(EPERM); + } - /* if it's the console, can't do it */ - if (UNIT(dev) == comconsole) + /* if it's the console, can't do it (XXX why?) */ + if (UNIT(dev) == comconsole) { + splx(s); return(ENOTTY); + } - /* can't do the next, for obvious reasons... +#if 0 + /* XXX - can't do the next, for obvious reasons... * but there are problems to be looked at... */ - /* if the port is active, don't do it */ - /* if (com->active) - return(EBUSY); */ + if (com->active) { + splx(s); + return(EBUSY); + } +#endif com->bidir = *(int *)data; break; @@ -1110,13 +1154,18 @@ sioioctl(dev, cmd, data, flag, p) break; #endif /* COM_BIDIR */ case TIOCMSDTRWAIT: - /* must be root (XXX why?) */ - if (p->p_ucred->cr_uid != 0) + /* must be root since the wait applies to following logins */ + error = suser(p->p_ucred, &p->p_acflag); + if (error != 0) { + splx(s); return(EPERM); + } /* if it's the console, can't do it (XXX why?) */ - if (UNIT(dev) == comconsole) + if (UNIT(dev) == comconsole) { + splx(s); return(ENOTTY); + } com->dtr_wait = *(int *)data; break; @@ -1170,7 +1219,7 @@ compoll() s = spltty(); repeat: for (unit = 0; unit < NSIO; ++unit) { - u_char *buf = 0; + u_char *buf; u_char *ibuf; int incc; struct tty *tp; @@ -1180,6 +1229,7 @@ repeat: continue; tp = com->tp; + buf = NULL; /* avoid compiler warning */ /* switch the role of the low-level input buffers */ if (com->iptr == (ibuf = com->ibuf)) incc = 0; @@ -1351,7 +1401,9 @@ comparam(tp, t) /* check requested parameters */ divisor = ttspeedtab(t->c_ospeed, comspeedtab); - if (divisor < 0 || t->c_ispeed != 0 && t->c_ispeed != t->c_ospeed) + if (t->c_ispeed == 0) + t->c_ispeed = t->c_ospeed; + if (divisor < 0 || t->c_ispeed != t->c_ospeed) return (EINVAL); /* parameters are OK, convert them to the com struct and the device */ @@ -1359,11 +1411,10 @@ comparam(tp, t) com = com_addr(unit); iobase = com->iobase; s = spltty(); - if (divisor == 0) { - (void) commctl(com, MCR_RTS, DMSET); /* hang up line */ - splx(s); - return (0); - } + if (divisor == 0) + commctl(com, MCR_DTR, DMBIC); /* hang up line */ + else + commctl(com, MCR_DTR, DMBIS); cflag = t->c_cflag; switch (cflag & CSIZE) { case CS5: @@ -1426,9 +1477,11 @@ retry: != (LSR_TSRE | LSR_TXRDY)) goto retry; - outb(iobase + com_cfcr, cfcr | CFCR_DLAB); - outb(iobase + com_dlbl, divisor & 0xFF); - outb(iobase + com_dlbh, (u_int) divisor >> 8); + if (divisor != 0) { + outb(iobase + com_cfcr, cfcr | CFCR_DLAB); + outb(iobase + com_dlbl, divisor & 0xFF); + outb(iobase + com_dlbh, (u_int) divisor >> 8); + } outb(iobase + com_cfcr, com->cfcr_image = cfcr); if (!(tp->t_state & TS_TTSTOP)) com->state |= CS_TTGO; @@ -1535,22 +1588,17 @@ siostop(tp, rw) enable_intr(); } -static int +static void commctl(com, bits, how) struct com_s *com; int bits; int how; { -#ifdef COM_MULTIPORT - if (how != DMBIC && !com->multiport) -#else - if (how != DMBIC) -#endif - bits |= MCR_IENABLE; disable_intr(); switch (how) { case DMSET: - outb(com->modem_ctl_port, com->mcr_image = bits); + outb(com->modem_ctl_port, + com->mcr_image = bits | (com->mcr_image & MCR_IENABLE)); break; case DMBIS: outb(com->modem_ctl_port, com->mcr_image |= bits); @@ -1560,7 +1608,6 @@ commctl(com, bits, how) break; } enable_intr(); - return (bits); } static void @@ -1571,7 +1618,7 @@ comwakeup(chan, ticks) struct com_s *com; int unit; - timeout(comwakeup, (caddr_t) NULL, 1); + timeout(comwakeup, (caddr_t) NULL, hz / 100); if (com_events != 0) /* schedule compoll() to run when the cpl allows */ schedsoftcom(); @@ -1595,8 +1642,9 @@ softsio1() } /* - * Following are all routines needed for COM to act as console + * Following are all routines needed for SIO to act as console * XXX - not tested in this version + * XXX - i386/cons.c only knows about the com driver (NCOM and not NSIO) * XXX - check that the corresponding serial interrupts are never enabled */ #include "i386/i386/cons.h" @@ -1613,7 +1661,7 @@ siocnprobe(cp) break; /* XXX: ick */ - unit = CONUNIT; + unit = UNIT(CONUNIT); com_addr(unit) = &com_structs[unit]; com_addr(unit)->iobase = CONADDR; @@ -1653,17 +1701,21 @@ cominit(unit, rate) s = splhigh(); outb(iobase + com_cfcr, CFCR_DLAB); rate = ttspeedtab(comdefaultrate, comspeedtab); - outb(iobase + com_data, rate & 0xFF); - outb(iobase + com_ier, rate >> 8); + outb(iobase + com_dlbl, rate & 0xFF); + outb(iobase + com_dlbh, rate >> 8); outb(iobase + com_cfcr, CFCR_8BITS); + outb(iobase + com_fifo, + FIFO_ENABLE | FIFO_TRIGGER | FIFO_RCV_RST | FIFO_XMT_RST); + DELAY(100); + (void) inb(iobase + com_lsr); + (void) inb(iobase + com_data); + (void) inb(iobase + com_msr); /* * XXX - fishy to enable interrupts and then poll. * It shouldn't be necessary to ready the iir. */ outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC); - outb(iobase + com_fifo, - FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14); (void) inb(iobase + com_iir); splx(s); } @@ -1701,7 +1753,7 @@ siocnputc(dev, c) if (dev != kgdb_dev) #endif if (!comconsinit) { - (void) cominit(UNIT(dev), comdefaultrate); + cominit(UNIT(dev), comdefaultrate); comconsinit = TRUE; } /* wait for any pending transmission to finish */ @@ -1719,14 +1771,10 @@ siocnputc(dev, c) } /* - * 10 Feb 93 Jordan K. Hubbard Added select code - * 27 May 93 Rodney W. Grimes Stole the select code from com.c.pl5 - * - * XXX - the standard com.c never needed this, but we need it because + * XXX - sioselect() is almost a copy of ttselect(). It is required because * ttselect() can't determine the tty struct because stuff is encoded in the * high bit of the minor number. */ - int sioselect(dev, rw, p) dev_t dev; |