Subject: 2.11BSD gets RTS/CTS flow control - continued (#374) Index: pdpuba/dhu,dhv,dh.c,pdpuba/dhureg.h,pdp/conf.c,man/dhv,dh,dvu.4 2.11BSD Description: The DH-11 and DHU-11 drivers do not implement RTS/CTS flowcontrol. Also, the dhureg.h file makes the same mistake as dhvreg.h did by misdeclaring the value of the CTS bit in the device status register. There was no manpage for the DHV device. The manpages for the DH and DHU devices were way out of date. Repeat-By: It's fairly obvious - by observation of course ;) Fix: NOTE: I do not have a DHU-11 to test with. The DHU is very very close to the DHV-11 and the changes were essentially merged in from the DHV-11 driver. It is possible (I hesitate to say "likely", but...) there are bugs present. If you have a DHU-11 and experience problems let me know and I'll work with you to fix them. NOTE: While I do have a DH-11 lookalike (an Able "Supermax") there has only been minimal testing of the driver because no phoneline is within reach of the 11/44. The testing done was to make sure that channels on the DH could be opened and that the output of "stty -a -f /dev/ttyi8" looked reasonable (i.e. DTR, RTS, CTS, etc looked right) and no system crash occurs. If I can get a modem line installed on the 44 more testing will be done. I really don't like sending out poorly tested or untested changes. But the hope is that someone will help out with the testing. The changes to the DH and DHU should be considered "alpha test" in nature. There is a good chance the modifications will work but if not the problems will be fixed and an update posted. In the patch kit below the following files are updated: /usr/src/sys/pdpuba/dhureg.h /usr/src/sys/pdpuba/dhu.c /usr/src/sys/pdpuba/dhv.c /usr/src/sys/pdpuba/dh.c /usr/src/sys/pdp/conf.c /usr/src/man/man4/dhu.4 /usr/src/man/man4/dh.4 /usr/src/man/man4/dhv.4 /usr/src/man/man4/Makefile /VERSION dhu.c and dh.c were almost complete rewrites. The changes to dhv.c are small and consist of shortening a couple message strings and a return(0) added where only "return" was used before. While the DHV is similar to the DHU the differences are sufficient to justify a new manpage: dhv(4). The dh(4) and dhu(4) manpages were updated to reflect the new minor device number layout (bit 6 is used to enable/disable RTS/CTS flow control, usw). In conf.c the DH and DHU entries in the cdevsw[] table were changed to call the driver specific select() function. This is necessary for ALL serial drivers which do RTS/CTS because the minor device number must be modified before being passed to the tty subsystem. To install this update first cut where indicated and save to a file (/tmp/374). Then: cd /tmp sh 374 patch -p0 < 374.patch sh 374.shar cd /usr/src/man/man4 make dh.0 dhu.0 dhv.0 install -m 444 -o bin -g bin *.0 /usr/man/cat4 If you can't wait for the 'makewhatis' database to be rebuilt (usually done by 'catman' from the /usr/adm/weekly cron run): /usr/sbin/makewhatis Unless you have DH, DHU or DHV devices present in the system there is no compelling reason to rebuild your kernel at this time. If you have the time it doesn't hurt anything to do a kernel recompile. As always this and previous updates to 2.11BSD are available via anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the directory /pub/2.11BSD. ----------------------------cut here-------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # 374.patch # 374.shar # This archive created: Thu Jun 12 22:44:31 1997 export PATH; PATH=/bin:/usr/bin:$PATH if test -f '374.patch' then echo shar: "will not over-write existing file '374.patch'" else sed 's/^Z//' << \SHAR_EOF > '374.patch' Z*** /usr/src/sys/pdpuba/dhureg.h.old Mon Jan 12 14:56:11 1987 Z--- /usr/src/sys/pdpuba/dhureg.h Fri May 9 20:30:43 1997 Z*************** Z*** 3,9 **** Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)dhureg.h 1.1 (2.10BSD Berkeley) 12/1/86 Z */ Z Z /* Z--- 3,9 ---- Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)dhureg.h 1.2 (2.11BSD) 1997/5/9 Z */ Z Z /* Z*************** Z*** 92,98 **** Z #define DHU_ST_DSR 0x80 /* data set ready */ Z #define DHU_ST_RI 0x20 /* ring indicator */ Z #define DHU_ST_DCD 0x10 /* carrier detect */ Z! #define DHU_ST_CTS 0x04 /* clear to send */ Z #define DHU_ST_DHU 0x01 /* always one on a dhu, zero on dhv */ Z Z /* Bits in dhulcr */ Z--- 92,98 ---- Z #define DHU_ST_DSR 0x80 /* data set ready */ Z #define DHU_ST_RI 0x20 /* ring indicator */ Z #define DHU_ST_DCD 0x10 /* carrier detect */ Z! #define DHU_ST_CTS 0x08 /* clear to send */ Z #define DHU_ST_DHU 0x01 /* always one on a dhu, zero on dhv */ Z Z /* Bits in dhulcr */ Z*************** Z*** 128,141 **** Z #define DHU_DTR DHU_LC_DTR Z #define DHU_BRK DHU_LC_BREAK Z #define DHU_LE DHU_LC_MODEM Z- Z- /* bits in dm lsr, copied from dmreg.h */ Z- #define DML_DSR 0000400 /* data set ready, not a real DM bit */ Z- #define DML_RNG 0000200 /* ring */ Z- #define DML_CAR 0000100 /* carrier detect */ Z- #define DML_CTS 0000040 /* clear to send */ Z- #define DML_SR 0000020 /* secondary receive */ Z- #define DML_ST 0000010 /* secondary transmit */ Z- #define DML_RTS 0000004 /* request to send */ Z- #define DML_DTR 0000002 /* data terminal ready */ Z- #define DML_LE 0000001 /* line enable */ Z--- 128,130 ---- Z*** /usr/src/sys/pdpuba/dhu.c.old Fri Feb 14 21:02:10 1997 Z--- /usr/src/sys/pdpuba/dhu.c Sat May 31 16:13:24 1997 Z*************** Z*** 3,12 **** Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)dhu.c 2.2 (2.11BSD GTE) 1997/2/14 Z */ Z Z /* Z * based on dh.c 6.3 84/03/15 Z * and on dmf.c 6.2 84/02/16 Z * Z--- 3,14 ---- Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)dhu.c 2.3 (2.11BSD GTE) 1997/5/9 Z */ Z Z /* Z+ * Rewritten for hardware flow control - sms 1997/5/9 Z+ * Z * based on dh.c 6.3 84/03/15 Z * and on dmf.c 6.2 84/02/16 Z * Z*************** Z*** 32,37 **** Z--- 34,40 ---- Z #include "uba.h" Z #include "ubavar.h" Z #include "systm.h" Z+ #include "syslog.h" Z #include Z Z struct uba_device dhuinfo[NDHU]; Z*************** Z*** 38,52 **** Z Z #define NDHULINE (NDHU*16) Z Z! #define UNIT(x) (minor(x) & 0177) Z Z- #ifndef PORTSELECTOR Z #define ISPEED B9600 Z #define IFLAGS (EVENP|ODDP|ECHO) Z- #else Z- #define ISPEED B4800 Z- #define IFLAGS (EVENP|ODDP) Z- #endif Z Z /* Z * default receive silo timeout value -- valid values are 2..255 Z--- 41,52 ---- Z Z #define NDHULINE (NDHU*16) Z Z! #define UNIT(x) (minor(x) & 077) Z! #define SOFTCAR 0x80 Z! #define HWFLOW 0x40 Z Z #define ISPEED B9600 Z #define IFLAGS (EVENP|ODDP|ECHO) Z Z /* Z * default receive silo timeout value -- valid values are 2..255 Z*************** Z*** 54,75 **** Z * Z * A value of 20 gives same response as ABLE dh/dm with silo alarm = 0 Z */ Z! #define DHU_DEF_TIMO 20 Z Z /* Z- * Other values for silo timeout register defined here but not used: Z- * receive interrupt only on modem control or silo alarm (3/4 full) Z- */ Z- #define DHU_POLL_TIMO 0 Z- /* Z- * receive interrupt immediately on receive character Z- */ Z- #define DHU_NO_TIMO 1 Z- Z- /* Z- * Local variables for the driver Z- */ Z- /* Z * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B". Z * EXTA => 19200 baud Z * EXTB => 2000 baud Z--- 54,62 ---- Z * Z * A value of 20 gives same response as ABLE dh/dm with silo alarm = 0 Z */ Z! int dhu_def_timo = 20; Z Z /* Z * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B". Z * EXTA => 19200 baud Z * EXTB => 2000 baud Z*************** Z*** 77,89 **** Z char dhu_speeds[] = Z { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 10, 11, 13, 14, 9 }; Z Z- short dhusoftCAR[NDHU]; Z- Z struct tty dhu_tty[NDHULINE]; Z int ndhu = NDHULINE; Z int dhuact; /* mask of active dhu's */ Z! int dhustart(), ttrstrt(); Z long dhumctl(),dmtodhu(); Z Z #if defined(UCB_CLIST) Z extern ubadr_t clstaddr; Z--- 64,76 ---- Z char dhu_speeds[] = Z { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 10, 11, 13, 14, 9 }; Z Z struct tty dhu_tty[NDHULINE]; Z int ndhu = NDHULINE; Z int dhuact; /* mask of active dhu's */ Z! int dhu_overrun[NDHULINE]; Z! int dhustart(); Z long dhumctl(),dmtodhu(); Z+ extern int wakeup(); Z Z #if defined(UCB_CLIST) Z extern ubadr_t clstaddr; Z*************** Z*** 99,116 **** Z duattach(addr,unit) Z register caddr_t addr; Z register u_int unit; Z! { Z register struct uba_device *ui; Z Z! if (addr && unit < NDHU && !dhuinfo[unit].ui_addr) { Z ui = &dhuinfo[unit]; Z ui->ui_unit = unit; Z ui->ui_addr = addr; Z ui->ui_alive = 1; Z! return (1); Z } Z- return (0); Z- } Z Z /* Z * Open a DHU11 line, mapping the clist onto the uba if this Z--- 86,104 ---- Z duattach(addr,unit) Z register caddr_t addr; Z register u_int unit; Z! { Z register struct uba_device *ui; Z Z! if (addr && unit < NDHU && !dhuinfo[unit].ui_addr) Z! { Z ui = &dhuinfo[unit]; Z ui->ui_unit = unit; Z ui->ui_addr = addr; Z ui->ui_alive = 1; Z! return(1); Z! } Z! return(0); Z } Z Z /* Z * Open a DHU11 line, mapping the clist onto the uba if this Z*************** Z*** 120,240 **** Z /*ARGSUSED*/ Z dhuopen(dev, flag) Z dev_t dev; Z! { Z register struct tty *tp; Z! register int unit, dhu; Z register struct dhudevice *addr; Z register struct uba_device *ui; Z! int s; Z Z unit = UNIT(dev); Z dhu = unit >> 4; Z! if (dev & 0200) Z! dhusoftCAR[dhu] |= (1<<(unit&0xf)); Z! else Z! dhusoftCAR[dhu] &= ~(1<<(unit&0xf)); Z! if (unit >= NDHULINE || (ui = &dhuinfo[dhu])->ui_alive == 0) Z return (ENXIO); Z tp = &dhu_tty[unit]; Z- if (tp->t_state & TS_XCLUDE && u.u_uid != 0) Z- return (EBUSY); Z addr = (struct dhudevice *)ui->ui_addr; Z tp->t_addr = (caddr_t)addr; Z tp->t_oproc = dhustart; Z! /* Z! * While setting up state for this uba and this dhu, Z! * block uba resets which can clear the state. Z! */ Z! s = spl5(); Z! if ((dhuact&(1<dhucsr = DHU_SELECT(0) | DHU_IE; Z! addr->dhutimo = DHU_DEF_TIMO; Z dhuact |= (1<t_state&TS_ISOPEN) == 0) { Z! ttychars(tp); Z! #ifndef PORTSELECTOR Z! if (tp->t_ispeed == 0) { Z! #else Z tp->t_state |= TS_HUPCLS; Z- #endif PORTSELECTOR Z tp->t_ispeed = ISPEED; Z tp->t_ospeed = ISPEED; Z tp->t_flags = IFLAGS; Z! #ifndef PORTSELECTOR Z! } Z! #endif PORTSELECTOR Z tp->t_dev = dev; Z dhuparam(unit); Z! } Z! /* Z! * Wait for carrier, then process line discipline specific open. Z! */ Z! s = spl5(); Z! if ((dhumctl(dev, (long)DHU_ON, DMSET) & DHU_CAR) || Z! (dhusoftCAR[dhu] & (1<<(unit&0xf)))) Z tp->t_state |= TS_CARR_ON; Z! while ((tp->t_state & TS_CARR_ON) == 0) { Z tp->t_state |= TS_WOPEN; Z sleep((caddr_t)&tp->t_rawq, TTIPRI); Z } Z- (void) splx(s); Z- return ((*linesw[tp->t_line].l_open)(dev, tp)); Z- } Z Z /* Z! * Close a DHU11 line, turning off the modem control. Z */ Z /*ARGSUSED*/ Z dhuclose(dev, flag) Z dev_t dev; Z int flag; Z! { Z register struct tty *tp; Z! register unit; Z Z unit = UNIT(dev); Z tp = &dhu_tty[unit]; Z (*linesw[tp->t_line].l_close)(tp, flag); Z (void) dhumctl(unit, (long)DHU_BRK, DMBIC); Z! if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN)==0) Z! #ifdef PORTSELECTOR Z { Z- extern int wakeup(); Z Z! (void) dhumctl(unit, (long)DHU_OFF, DMSET); Z! /* Hold DTR low for 0.5 seconds */ Z! timeout(wakeup, (caddr_t) &tp->t_dev, hz/2); Z! sleep((caddr_t) &tp->t_dev, PZERO); Z } Z- #else Z- (void) dhumctl(unit, DHU_OFF, DMSET); Z- #endif PORTSELECTOR Z- ttyclose(tp); Z- } Z Z dhuread(dev, uio, flag) Z dev_t dev; Z struct uio *uio; Z! { Z register struct tty *tp = &dhu_tty[UNIT(dev)]; Z Z return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); Z! } Z Z dhuwrite(dev, uio, flag) Z dev_t dev; Z struct uio *uio; Z! { Z register struct tty *tp = &dhu_tty[UNIT(dev)]; Z Z return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); Z! } Z Z /* Z * DHU11 receiver interrupt. Z--- 108,241 ---- Z /*ARGSUSED*/ Z dhuopen(dev, flag) Z dev_t dev; Z! int flag; Z! { Z register struct tty *tp; Z! int unit, dhu; Z register struct dhudevice *addr; Z register struct uba_device *ui; Z! int s, error; Z Z unit = UNIT(dev); Z dhu = unit >> 4; Z! if (unit >= NDHULINE || (ui = &dhuinfo[dhu])->ui_alive == 0) Z return (ENXIO); Z tp = &dhu_tty[unit]; Z addr = (struct dhudevice *)ui->ui_addr; Z tp->t_addr = (caddr_t)addr; Z tp->t_oproc = dhustart; Z! Z! if ((dhuact&(1<dhucsr = DHU_SELECT(0) | DHU_IE; Z! addr->dhutimo = dhu_def_timo; Z dhuact |= (1<t_state&TS_ISOPEN) == 0) Z! { Z! tp->t_state |= TS_WOPEN; Z! if (tp->t_ispeed == 0) Z! { Z tp->t_state |= TS_HUPCLS; Z tp->t_ispeed = ISPEED; Z tp->t_ospeed = ISPEED; Z tp->t_flags = IFLAGS; Z! } Z! ttychars(tp); Z tp->t_dev = dev; Z+ if (dev & HWFLOW) Z+ tp->t_flags |= RTSCTS; Z+ else Z+ tp->t_flags &= ~RTSCTS; Z dhuparam(unit); Z! } Z! else if (tp->t_state & TS_XCLUDE && u.u_uid) Z! { Z! error = EBUSY; Z! goto out; Z! } Z! /* Z! * Turn the device on. Wait for carrier (the wait is short if this is a Z! * softcarrier/hardwired line ;-)). Then do the line discipline specific open. Z! */ Z! dhumctl(dev, (long)DHU_ON, DMSET); Z! addr->dhucsr = DHU_SELECT(unit) | DHU_IE; Z! if ((addr->dhustat & DHU_ST_DCD) || (dev & SOFTCAR)) Z tp->t_state |= TS_CARR_ON; Z! while ((tp->t_state & TS_CARR_ON) == 0 && Z! (flag & O_NONBLOCK) == 0) Z! { Z tp->t_state |= TS_WOPEN; Z sleep((caddr_t)&tp->t_rawq, TTIPRI); Z+ } Z+ error = (*linesw[tp->t_line].l_open)(dev, tp); Z+ out: Z+ splx(s); Z+ return(error); Z } Z Z /* Z! * Close a DHU11 line. Clear the 'break' state in case it's asserted and Z! * then drop DTR+RTS. Z */ Z /*ARGSUSED*/ Z dhuclose(dev, flag) Z dev_t dev; Z int flag; Z! { Z register struct tty *tp; Z! register int unit; Z Z unit = UNIT(dev); Z tp = &dhu_tty[unit]; Z+ /* Z+ * Do we need to do this? Perhaps this should be ifdef'd. I can't see how Z+ * this can happen... Z+ */ Z+ if (!(tp->t_state & TS_ISOPEN)) Z+ return(EBADF); Z (*linesw[tp->t_line].l_close)(tp, flag); Z (void) dhumctl(unit, (long)DHU_BRK, DMBIC); Z! (void) dhumctl(unit, DHU_OFF, DMSET); Z! ttyclose(tp); Z! if (dhu_overrun[unit]) Z! { Z! log(LOG_NOTICE, "dhu%d %d overruns\n", unit, dhu_overrun[unit]); Z! dhu_overrun[unit] = 0; Z! } Z! return(0); Z! } Z! Z! dhuselect(dev, rw) Z! dev_t dev; Z! int rw; Z { Z Z! return(ttyselect(&dhu_tty[UNIT(dev)], rw)); Z } Z Z dhuread(dev, uio, flag) Z dev_t dev; Z struct uio *uio; Z! { Z register struct tty *tp = &dhu_tty[UNIT(dev)]; Z Z return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); Z! } Z Z dhuwrite(dev, uio, flag) Z dev_t dev; Z struct uio *uio; Z! { Z register struct tty *tp = &dhu_tty[UNIT(dev)]; Z Z return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); Z! } Z Z /* Z * DHU11 receiver interrupt. Z*************** Z*** 241,298 **** Z */ Z dhurint(dhu) Z int dhu; Z! { Z register struct tty *tp; Z! register c; Z register struct dhudevice *addr; Z! register struct tty *tp0; Z! register struct uba_device *ui; Z! register line; Z! int overrun = 0; Z Z ui = &dhuinfo[dhu]; Z- if (ui == 0 || ui->ui_alive == 0) Z- return; Z addr = (struct dhudevice *)ui->ui_addr; Z tp0 = &dhu_tty[dhu<<4]; Z /* Z * Loop fetching characters from the silo for this Z * dhu until there are no more in the silo. Z */ Z! while ((c = addr->dhurbuf) < 0) { /* (c & DHU_RB_VALID) == on */ Z line = DHU_RX_LINE(c); Z tp = tp0 + line; Z! if ((c & DHU_RB_STAT) == DHU_RB_STAT) { Z /* Z * modem changed or diag info Z */ Z! if (c & DHU_RB_DIAG) { Z! /* decode diagnostic messages */ Z continue; Z! } Z! if (c & DHU_ST_DCD) Z! (void)(*linesw[tp->t_line].l_modem)(tp, 1); Z! else if ((dhusoftCAR[dhu] & (1<t_line].l_modem)(tp, 0) == 0) Z! (void) dhumctl((dhu<<4)|line, DHU_OFF, DMSET); Z continue; Z! } Z! if ((tp->t_state&TS_ISOPEN) == 0) { Z wakeup((caddr_t)&tp->t_rawq); Z! #ifdef PORTSELECTOR Z! if ((tp->t_state&TS_WOPEN) == 0) Z! #endif Z continue; Z! } Z! if (c & DHU_RB_PE) Z! if ((tp->t_flags&(EVENP|ODDP)) == EVENP || Z! (tp->t_flags&(EVENP|ODDP)) == ODDP) Z! continue; Z! if ((c & DHU_RB_DO) && overrun == 0) { Z! printf("dhu%d: silo overflow\n", dhu); Z! overrun = 1; Z! } Z! if (c & DHU_RB_FE) Z /* Z * At framing error (break) generate Z * a null (in raw mode, for getty), or a Z--- 242,318 ---- Z */ Z dhurint(dhu) Z int dhu; Z! { Z register struct tty *tp; Z! register int c; Z register struct dhudevice *addr; Z! struct tty *tp0; Z! struct uba_device *ui; Z! int line; Z Z ui = &dhuinfo[dhu]; Z addr = (struct dhudevice *)ui->ui_addr; Z+ if (!addr) Z+ return; Z tp0 = &dhu_tty[dhu<<4]; Z /* Z * Loop fetching characters from the silo for this Z * dhu until there are no more in the silo. Z */ Z! while ((c = addr->dhurbuf) < 0) Z! { /* (c & DHU_RB_VALID) == on */ Z line = DHU_RX_LINE(c); Z tp = tp0 + line; Z! if ((c & DHU_RB_STAT) == DHU_RB_STAT) Z! { Z /* Z * modem changed or diag info Z */ Z! if (c & DHU_RB_DIAG) Z! { Z! if ((c & 0xff) > 0201) Z! log(LOG_NOTICE,"dhu%d diag %o\n", Z! dhu, c); Z continue; Z! } Z! if (!(tp->t_dev & SOFTCAR) || Z! (tp->t_flags & MDMBUF)) Z! (*linesw[tp->t_line].l_modem)(tp, Z! (c & DHU_ST_DCD) != 0); Z! if (tp->t_flags & RTSCTS) Z! { Z! if (c & DHU_ST_CTS) Z! { Z! tp->t_state &= ~TS_TTSTOP; Z! ttstart(tp); Z! } Z! else Z! { Z! tp->t_state |= TS_TTSTOP; Z! dhustop(tp, 0); Z! } Z! } Z continue; Z! } Z! if ((tp->t_state&TS_ISOPEN) == 0) Z! { Z wakeup((caddr_t)&tp->t_rawq); Z! continue; Z! } Z! if (c & DHU_RB_PE) Z! if ((tp->t_flags&(EVENP|ODDP)) == EVENP || Z! (tp->t_flags&(EVENP|ODDP)) == ODDP) Z continue; Z! if (c & DHU_RB_DO) Z! { Z! dhu_overrun[(dhu << 4) + line]++; Z! /* bit bucket the silo to free the cpu */ Z! while (addr->dhurbuf & DHU_RB_VALID) Z! ; Z! break; Z! } Z! if (c & DHU_RB_FE) Z! { Z /* Z * At framing error (break) generate Z * a null (in raw mode, for getty), or a Z*************** Z*** 306,320 **** Z #else Z c = tp->t_brkc; Z #endif Z #if NBK > 0 Z! if (tp->t_line == NETLDISC) { Z c &= 0x7f; Z BKINPUT(c, tp); Z! } else Z #endif Z (*linesw[tp->t_line].l_rint)(c, tp); Z } Z- } Z Z /* Z * Ioctl for DHU11. Z--- 326,343 ---- Z #else Z c = tp->t_brkc; Z #endif Z+ } Z #if NBK > 0 Z! if (tp->t_line == NETLDISC) Z! { Z c &= 0x7f; Z BKINPUT(c, tp); Z! } Z! else Z #endif Z (*linesw[tp->t_line].l_rint)(c, tp); Z+ } Z } Z Z /* Z * Ioctl for DHU11. Z*************** Z*** 323,329 **** Z dhuioctl(dev, cmd, data, flag) Z u_int cmd; Z caddr_t data; Z! { Z register struct tty *tp; Z register int unit = UNIT(dev); Z int error; Z--- 346,352 ---- Z dhuioctl(dev, cmd, data, flag) Z u_int cmd; Z caddr_t data; Z! { Z register struct tty *tp; Z register int unit = UNIT(dev); Z int error; Z*************** Z*** 330,410 **** Z Z tp = &dhu_tty[unit]; Z error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); Z! if (error >= 0) Z! return (error); Z error = ttioctl(tp, cmd, data, flag); Z! if (error >= 0) { Z! if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLSET || Z! cmd == TIOCLBIC || cmd == TIOCLBIS) Z dhuparam(unit); Z! return (error); Z! } Z Z! switch (cmd) { Z! case TIOCSBRK: Z! (void) dhumctl(unit, (long)DHU_BRK, DMBIS); Z! break; Z! Z! case TIOCCBRK: Z! (void) dhumctl(unit, (long)DHU_BRK, DMBIC); Z! break; Z! Z! case TIOCSDTR: Z! (void) dhumctl(unit, (long)DHU_DTR|DHU_RTS, DMBIS); Z! break; Z! Z! case TIOCCDTR: Z! (void) dhumctl(unit, (long)DHU_DTR|DHU_RTS, DMBIC); Z! break; Z! Z! case TIOCMSET: Z! (void) dhumctl(dev, dmtodhu(*(int *)data), DMSET); Z! break; Z! Z! case TIOCMBIS: Z! (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIS); Z! break; Z! Z! case TIOCMBIC: Z! (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIC); Z! break; Z! Z! case TIOCMGET: Z! *(int *)data = dhutodm(dhumctl(dev, 0L, DMGET)); Z! break; Z! default: Z! return (ENOTTY); Z } Z- return (0); Z- } Z Z static long Z dmtodhu(bits) Z register int bits; Z! { Z long b = 0; Z Z! if (bits & DML_RTS) b |= DHU_RTS; Z! if (bits & DML_DTR) b |= DHU_DTR; Z! if (bits & DML_LE) b |= DHU_LE; Z return(b); Z! } Z Z static Z dhutodm(bits) Z long bits; Z! { Z register int b = 0; Z Z! if (bits & DHU_DSR) b |= DML_DSR; Z! if (bits & DHU_RNG) b |= DML_RNG; Z! if (bits & DHU_CAR) b |= DML_CAR; Z! if (bits & DHU_CTS) b |= DML_CTS; Z! if (bits & DHU_RTS) b |= DML_RTS; Z! if (bits & DHU_DTR) b |= DML_DTR; Z! if (bits & DHU_LE) b |= DML_LE; Z return(b); Z! } Z Z /* Z * Set parameters from open or stty into the DHU hardware Z--- 353,428 ---- Z Z tp = &dhu_tty[unit]; Z error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); Z! if (error >= 0) Z! return(error); Z error = ttioctl(tp, cmd, data, flag); Z! if (error >= 0) Z! { Z! if (cmd == TIOCSETP || cmd == TIOCSETN || Z! cmd == TIOCLSET || cmd == TIOCLBIC || cmd == TIOCLBIS) Z dhuparam(unit); Z! return(error); Z! } Z Z! switch (cmd) Z! { Z! case TIOCSBRK: Z! (void) dhumctl(unit, (long)DHU_BRK, DMBIS); Z! break; Z! case TIOCCBRK: Z! (void) dhumctl(unit, (long)DHU_BRK, DMBIC); Z! break; Z! case TIOCSDTR: Z! (void) dhumctl(unit, (long)DHU_DTR|DHU_RTS, DMBIS); Z! break; Z! case TIOCCDTR: Z! (void) dhumctl(unit, (long)DHU_DTR|DHU_RTS, DMBIC); Z! break; Z! case TIOCMSET: Z! (void) dhumctl(dev, dmtodhu(*(int *)data), DMSET); Z! break; Z! case TIOCMBIS: Z! (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIS); Z! break; Z! case TIOCMBIC: Z! (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIC); Z! break; Z! case TIOCMGET: Z! *(int *)data = dhutodm(dhumctl(dev, 0L, DMGET)); Z! break; Z! default: Z! return(ENOTTY); Z! } Z! return(0); Z } Z Z static long Z dmtodhu(bits) Z register int bits; Z! { Z long b = 0; Z Z! if (bits & TIOCM_RTS) b |= DHU_RTS; Z! if (bits & TIOCM_DTR) b |= DHU_DTR; Z! if (bits & TIOCM_LE) b |= DHU_LE; Z return(b); Z! } Z Z static Z dhutodm(bits) Z long bits; Z! { Z register int b = 0; Z Z! if (bits & DHU_DSR) b |= TIOCM_DSR; Z! if (bits & DHU_RNG) b |= TIOCM_RNG; Z! if (bits & DHU_CAR) b |= TIOCM_CAR; Z! if (bits & DHU_CTS) b |= TIOCM_CTS; Z! if (bits & DHU_RTS) b |= TIOCM_RTS; Z! if (bits & DHU_DTR) b |= TIOCM_DTR; Z! if (bits & DHU_LE) b |= TIOCM_LE; Z return(b); Z! } Z Z /* Z * Set parameters from open or stty into the DHU hardware Z*************** Z*** 413,419 **** Z static Z dhuparam(unit) Z register int unit; Z! { Z register struct tty *tp; Z register struct dhudevice *addr; Z register int lpar; Z--- 431,437 ---- Z static Z dhuparam(unit) Z register int unit; Z! { Z register struct tty *tp; Z register struct dhudevice *addr; Z register int lpar; Z*************** Z*** 425,452 **** Z * Block interrupts so parameters will be set Z * before the line interrupts. Z */ Z! s = spl5(); Z! if ((tp->t_ispeed) == 0) { Z tp->t_state |= TS_HUPCLS; Z (void)dhumctl(unit, (long)DHU_OFF, DMSET); Z! splx(s); Z! return; Z! } Z lpar = (dhu_speeds[tp->t_ospeed]<<12) | (dhu_speeds[tp->t_ispeed]<<8); Z! if ((tp->t_ispeed) == B134) Z lpar |= DHU_LP_BITS6|DHU_LP_PENABLE; Z else if (tp->t_flags & (RAW|LITOUT|PASS8)) Z lpar |= DHU_LP_BITS8; Z else Z lpar |= DHU_LP_BITS7|DHU_LP_PENABLE; Z! if (tp->t_flags&EVENP) Z lpar |= DHU_LP_EPAR; Z! if ((tp->t_ospeed) == B110) Z lpar |= DHU_LP_TWOSB; Z addr->dhucsr = DHU_SELECT(unit) | DHU_IE; Z addr->dhulpr = lpar; Z splx(s); Z! } Z Z /* Z * DHU11 transmitter interrupt. Z--- 443,472 ---- Z * Block interrupts so parameters will be set Z * before the line interrupts. Z */ Z! s = spltty(); Z! if (tp->t_ispeed == 0) Z! { Z tp->t_state |= TS_HUPCLS; Z (void)dhumctl(unit, (long)DHU_OFF, DMSET); Z! goto out; Z! } Z lpar = (dhu_speeds[tp->t_ospeed]<<12) | (dhu_speeds[tp->t_ispeed]<<8); Z! if ((tp->t_ispeed) == B134) Z lpar |= DHU_LP_BITS6|DHU_LP_PENABLE; Z else if (tp->t_flags & (RAW|LITOUT|PASS8)) Z lpar |= DHU_LP_BITS8; Z else Z lpar |= DHU_LP_BITS7|DHU_LP_PENABLE; Z! if (tp->t_flags&EVENP) Z lpar |= DHU_LP_EPAR; Z! if ((tp->t_ospeed) == B110) Z lpar |= DHU_LP_TWOSB; Z addr->dhucsr = DHU_SELECT(unit) | DHU_IE; Z addr->dhulpr = lpar; Z+ out: Z splx(s); Z! return; Z! } Z Z /* Z * DHU11 transmitter interrupt. Z*************** Z*** 455,465 **** Z */ Z dhuxint(dhu) Z int dhu; Z! { Z register struct tty *tp; Z register struct dhudevice *addr; Z! register struct tty *tp0; Z! register struct uba_device *ui; Z register int line, t; Z u_short cntr; Z ubadr_t base; Z--- 475,485 ---- Z */ Z dhuxint(dhu) Z int dhu; Z! { Z register struct tty *tp; Z register struct dhudevice *addr; Z! struct tty *tp0; Z! struct uba_device *ui; Z register int line, t; Z u_short cntr; Z ubadr_t base; Z*************** Z*** 467,483 **** Z ui = &dhuinfo[dhu]; Z tp0 = &dhu_tty[dhu<<4]; Z addr = (struct dhudevice *)ui->ui_addr; Z! while ((t = addr->dhucsrh) & DHU_CSH_TI) { Z line = DHU_TX_LINE(t); Z tp = tp0 + line; Z tp->t_state &= ~TS_BUSY; Z! if (t & DHU_CSH_NXM) { Z! printf("dhu(%d,%d): NXM fault\n", dhu, line); Z /* SHOULD RESTART OR SOMETHING... */ Z! } Z! if (tp->t_state&TS_FLUSH) Z tp->t_state &= ~TS_FLUSH; Z! else { Z addr->dhucsrl = DHU_SELECT(line) | DHU_IE; Z base = (ubadr_t) addr->dhubar1; Z /* Z--- 487,506 ---- Z ui = &dhuinfo[dhu]; Z tp0 = &dhu_tty[dhu<<4]; Z addr = (struct dhudevice *)ui->ui_addr; Z! while ((t = addr->dhucsrh) & DHU_CSH_TI) Z! { Z line = DHU_TX_LINE(t); Z tp = tp0 + line; Z tp->t_state &= ~TS_BUSY; Z! if (t & DHU_CSH_NXM) Z! { Z! log(LOG_NOTICE, "dhu%d,%d NXM\n", dhu, line); Z /* SHOULD RESTART OR SOMETHING... */ Z! } Z! if (tp->t_state&TS_FLUSH) Z tp->t_state &= ~TS_FLUSH; Z! else Z! { Z addr->dhucsrl = DHU_SELECT(line) | DHU_IE; Z base = (ubadr_t) addr->dhubar1; Z /* Z*************** Z*** 489,505 **** Z * Z * In either case, the extension bits are 0. Z */ Z! if (!ubmap) Z base |= (ubadr_t)((addr->dhubar2 & 037) << 16); Z cntr = base - cpaddr(tp->t_outq.c_cf); Z! ndflush(&tp->t_outq,cntr); Z! } Z! if (tp->t_line) Z (*linesw[tp->t_line].l_start)(tp); Z else Z dhustart(tp); Z } Z- } Z Z /* Z * Start (restart) transmission on the given DHU11 line. Z--- 512,528 ---- Z * Z * In either case, the extension bits are 0. Z */ Z! if (!ubmap) Z base |= (ubadr_t)((addr->dhubar2 & 037) << 16); Z cntr = base - cpaddr(tp->t_outq.c_cf); Z! ndflush(&tp->t_outq, cntr); Z! } Z! if (tp->t_line) Z (*linesw[tp->t_line].l_start)(tp); Z else Z dhustart(tp); Z+ } Z } Z Z /* Z * Start (restart) transmission on the given DHU11 line. Z*************** Z*** 506,584 **** Z */ Z dhustart(tp) Z register struct tty *tp; Z! { Z register struct dhudevice *addr; Z register int unit, nch; Z ubadr_t car; Z int s; Z Z! unit = minor(tp->t_dev); Z! unit &= 0xf; Z addr = (struct dhudevice *)tp->t_addr; Z Z /* Z- * Must hold interrupts in following code to prevent Z- * state of the tp from changing. Z- */ Z- s = spl5(); Z- /* Z * If it's currently active, or delaying, no need to do anything. Z */ Z! if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) Z goto out; Z /* Z * If there are sleepers, and output has drained below low Z * water mark, wake up the sleepers.. Z */ Z! if (tp->t_outq.c_cc<=TTLOWAT(tp)) { Z! if (tp->t_state&TS_ASLEEP) { Z! tp->t_state &= ~TS_ASLEEP; Z! wakeup((caddr_t)&tp->t_outq); Z! } Z! if (tp->t_wsel) { Z! selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); Z! tp->t_wsel = 0; Z! tp->t_state &= ~TS_WCOLL; Z! } Z! } Z /* Z * Now restart transmission unless the output queue is Z * empty. Z */ Z! if (tp->t_outq.c_cc == 0) Z goto out; Z! if (tp->t_flags & (RAW|LITOUT)) Z! nch = ndqb(&tp->t_outq, 0); Z! else { Z! nch = ndqb(&tp->t_outq, 0200); Z! /* Z! * If first thing on queue is a delay process it. Z! */ Z! if (nch == 0) { Z! nch = getc(&tp->t_outq); Z! timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); Z! tp->t_state |= TS_TIMEOUT; Z! goto out; Z } Z! } Z /* Z * If characters to transmit, restart transmission. Z */ Z! if (nch) { Z car = cpaddr(tp->t_outq.c_cf); Z addr->dhucsrl = DHU_SELECT(unit) | DHU_IE; Z addr->dhulcr &= ~DHU_LC_TXABORT; Z addr->dhubcr = nch; Z addr->dhubar1 = loint(car); Z! if (ubmap) Z addr->dhubar2 = (hiint(car) & DHU_BA2_XBA) | DHU_BA2_DMAGO; Z else Z addr->dhubar2 = (hiint(car) & 037) | DHU_BA2_DMAGO; Z tp->t_state |= TS_BUSY; Z! } Z out: Z splx(s); Z! } Z Z /* Z * Stop output on a line, e.g. for ^S/^Q or output flush. Z--- 529,597 ---- Z */ Z dhustart(tp) Z register struct tty *tp; Z! { Z register struct dhudevice *addr; Z register int unit, nch; Z ubadr_t car; Z int s; Z Z! unit = UNIT(tp->t_dev); Z addr = (struct dhudevice *)tp->t_addr; Z Z+ s = spltty(); Z /* Z * If it's currently active, or delaying, no need to do anything. Z */ Z! if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) Z goto out; Z /* Z * If there are sleepers, and output has drained below low Z * water mark, wake up the sleepers.. Z */ Z! ttyowake(tp); Z! Z /* Z * Now restart transmission unless the output queue is Z * empty. Z */ Z! if (tp->t_outq.c_cc == 0) Z goto out; Z! addr->dhucsrl = DHU_SELECT(unit) | DHU_IE; Z! /* Z! * If CTS is off and we're doing hardware flow control then mark the output Z! * as stopped and do not transmit anything. Z! */ Z! if ((addr->dhustat & DHU_ST_CTS) == 0 && (tp->t_flags & RTSCTS)) Z! { Z! tp->t_state |= TS_TTSTOP; Z! goto out; Z } Z! /* Z! * This is where any per character delay handling for special characters Z! * would go if ever implemented again. The call to ndqb would be replaced Z! * with a scan for special characters and then the appropriate sleep/wakeup Z! * done. Z! */ Z! nch = ndqb(&tp->t_outq, 0); Z /* Z * If characters to transmit, restart transmission. Z */ Z! if (nch) Z! { Z car = cpaddr(tp->t_outq.c_cf); Z addr->dhucsrl = DHU_SELECT(unit) | DHU_IE; Z addr->dhulcr &= ~DHU_LC_TXABORT; Z addr->dhubcr = nch; Z addr->dhubar1 = loint(car); Z! if (ubmap) Z addr->dhubar2 = (hiint(car) & DHU_BA2_XBA) | DHU_BA2_DMAGO; Z else Z addr->dhubar2 = (hiint(car) & 037) | DHU_BA2_DMAGO; Z tp->t_state |= TS_BUSY; Z! } Z out: Z splx(s); Z! } Z Z /* Z * Stop output on a line, e.g. for ^S/^Q or output flush. Z*************** Z*** 586,592 **** Z /*ARGSUSED*/ Z dhustop(tp, flag) Z register struct tty *tp; Z! { Z register struct dhudevice *addr; Z register int unit, s; Z Z--- 599,605 ---- Z /*ARGSUSED*/ Z dhustop(tp, flag) Z register struct tty *tp; Z! { Z register struct dhudevice *addr; Z register int unit, s; Z Z*************** Z*** 594,601 **** Z /* Z * Block input/output interrupts while messing with state. Z */ Z! s = spl5(); Z! if (tp->t_state & TS_BUSY) { Z /* Z * Device is transmitting; stop output Z * by selecting the line and setting the Z--- 607,615 ---- Z /* Z * Block input/output interrupts while messing with state. Z */ Z! s = spltty(); Z! if (tp->t_state & TS_BUSY) Z! { Z /* Z * Device is transmitting; stop output Z * by selecting the line and setting the Z*************** Z*** 605,618 **** Z * TS_FLUSH is set, the outq will be flushed. Z * In either case, dhustart will clear the TXABORT bit. Z */ Z! unit = minor(tp->t_dev); Z addr->dhucsrl = DHU_SELECT(unit) | DHU_IE; Z addr->dhulcr |= DHU_LC_TXABORT; Z! if ((tp->t_state&TS_TTSTOP)==0) Z tp->t_state |= TS_FLUSH; Z! } Z (void) splx(s); Z! } Z Z /* Z * DHU11 modem control Z--- 619,632 ---- Z * TS_FLUSH is set, the outq will be flushed. Z * In either case, dhustart will clear the TXABORT bit. Z */ Z! unit = UNIT(tp->t_dev); Z addr->dhucsrl = DHU_SELECT(unit) | DHU_IE; Z addr->dhulcr |= DHU_LC_TXABORT; Z! if ((tp->t_state&TS_TTSTOP)==0) Z tp->t_state |= TS_FLUSH; Z! } Z (void) splx(s); Z! } Z Z /* Z * DHU11 modem control Z*************** Z*** 622,663 **** Z dev_t dev; Z long bits; Z int how; Z! { Z register struct dhudevice *dhuaddr; Z! register int unit; Z long mbits; Z int s; Z Z unit = UNIT(dev); Z dhuaddr = (struct dhudevice *)(dhu_tty[unit].t_addr); Z! unit &= 0xf; Z! s = spl5(); Z! dhuaddr->dhucsr = DHU_SELECT(unit) | DHU_IE; Z /* Z * combine byte from stat register (read only, bits 16..23) Z * with lcr register (read write, bits 0..15). Z */ Z mbits = (u_short)dhuaddr->dhulcr | ((long)dhuaddr->dhustat << 16); Z! switch (how) { Z! Z! case DMSET: Z! mbits = (mbits & 0xff0000L) | bits; Z! break; Z! Z! case DMBIS: Z! mbits |= bits; Z! break; Z! Z! case DMBIC: Z! mbits &= ~bits; Z! break; Z! Z! case DMGET: Z! (void) splx(s); Z! return(mbits); Z! } Z! dhuaddr->dhulcr = (mbits & 0xffff) | DHU_LC_RXEN; Z dhuaddr->dhulcr2 = DHU_LC2_TXEN; Z (void) splx(s); Z return(mbits); Z } Z--- 636,674 ---- Z dev_t dev; Z long bits; Z int how; Z! { Z register struct dhudevice *dhuaddr; Z! register int unit, line; Z long mbits; Z int s; Z Z unit = UNIT(dev); Z dhuaddr = (struct dhudevice *)(dhu_tty[unit].t_addr); Z! line = unit & 0xf; Z! s = spltty(); Z! dhuaddr->dhucsr = DHU_SELECT(line) | DHU_IE; Z /* Z * combine byte from stat register (read only, bits 16..23) Z * with lcr register (read write, bits 0..15). Z */ Z mbits = (u_short)dhuaddr->dhulcr | ((long)dhuaddr->dhustat << 16); Z! switch (how) Z! { Z! case DMSET: Z! mbits = (mbits & 0xff0000L) | bits; Z! break; Z! case DMBIS: Z! mbits |= bits; Z! break; Z! case DMBIC: Z! mbits &= ~bits; Z! break; Z! case DMGET: Z! goto out; Z! } Z! dhuaddr->dhulcr = (mbits & 0xffffL) | DHU_LC_RXEN; Z dhuaddr->dhulcr2 = DHU_LC2_TXEN; Z+ out: Z (void) splx(s); Z return(mbits); Z } Z*** /usr/src/sys/pdpuba/dhv.c.old Fri May 2 20:03:42 1997 Z--- /usr/src/sys/pdpuba/dhv.c Sat May 31 16:15:26 1997 Z*************** Z*** 3,9 **** Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)dhv.c 2.3 (2.11BSD 2.11BSD) 1997/5/1 Z */ Z Z /* Z--- 3,9 ---- Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)dhv.c 2.4 (2.11BSD 2.11BSD) 1997/5/31 Z */ Z Z /* Z*************** Z*** 202,209 **** Z Z unit = UNIT(dev); Z tp = &dhv_tty[unit]; Z! if (!(tp->t_state & TS_ISOPEN)) Z! return; Z (*linesw[tp->t_line].l_close)(tp, flag); Z (void) dhvmctl(unit, (long)DHV_BRK, DMBIC); Z (void) dhvmctl(unit, (long)DHV_OFF, DMSET); Z--- 202,209 ---- Z Z unit = UNIT(dev); Z tp = &dhv_tty[unit]; Z! if (!(tp->t_state & (TS_WOPEN|TS_ISOPEN))) Z! return(0); Z (*linesw[tp->t_line].l_close)(tp, flag); Z (void) dhvmctl(unit, (long)DHV_BRK, DMBIC); Z (void) dhvmctl(unit, (long)DHV_OFF, DMSET); Z*************** Z*** 281,287 **** Z if (c & DHV_RB_DIAG) Z { Z if ((c & 0xff) > 0201) Z! printf ("dhv%d: diag %o\n",dhv, c&0xff); Z continue; Z } Z if (!(tp->t_dev & SOFTCAR) || Z--- 281,287 ---- Z if (c & DHV_RB_DIAG) Z { Z if ((c & 0xff) > 0201) Z! log(LOG_NOTICE,"dhv%d diag %o\n",dhv, c&0xff); Z continue; Z } Z if (!(tp->t_dev & SOFTCAR) || Z*************** Z*** 533,539 **** Z tp->t_state &= ~TS_BUSY; Z if (t & DHV_CSH_NXM) Z { Z! printf("dhv(%d,%d) NXM\n", dhv, line); Z /* SHOULD RESTART OR SOMETHING... */ Z } Z if (tp->t_state&TS_FLUSH) Z--- 533,539 ---- Z tp->t_state &= ~TS_BUSY; Z if (t & DHV_CSH_NXM) Z { Z! log(LOG_NOTICE, "dhv%d,%d NXM\n", dhv, line); Z /* SHOULD RESTART OR SOMETHING... */ Z } Z if (tp->t_state&TS_FLUSH) Z*** /usr/src/sys/pdpuba/dh.c.old Sun Feb 16 18:48:24 1997 Z--- /usr/src/sys/pdpuba/dh.c Thu Jun 12 21:37:55 1997 Z*************** Z*** 3,9 **** Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)dh.c 1.4 (2.11BSD GTE) 1997/2/14 Z */ Z Z /* Z--- 3,9 ---- Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)dh.c 1.5 (2.11BSD GTE) 1997/6/12 Z */ Z Z /* Z*************** Z*** 37,49 **** Z struct uba_device dhinfo[NDH]; Z struct uba_device dminfo[NDH]; Z Z- #ifndef PORTSELECTOR Z- #define ISPEED B9600 Z #define IFLAGS (EVENP|ODDP|ECHO) Z- #else Z- #define ISPEED B4800 Z- #define IFLAGS (EVENP|ODDP) Z- #endif Z Z /* Z * Use 2 ticks rather than doing a divide of 'hz' by 30. The old method Z--- 37,43 ---- Z*************** Z*** 56,64 **** Z * Local variables for the driver Z */ Z short dhsar[NDH]; /* software copy of last bar */ Z- short dhsoftCAR[NDH]; Z Z struct tty dh11[NDH*16]; Z int ndh11 = NDH*16; Z int dhact; /* mask of active dh's */ Z int dhsilos; /* mask of dh's with silo in use */ Z--- 50,60 ---- Z * Local variables for the driver Z */ Z short dhsar[NDH]; /* software copy of last bar */ Z Z struct tty dh11[NDH*16]; Z+ u_int dh_overrun[NDH*16]; /* count of silo overruns, cleared on Z+ * close. Z+ */ Z int ndh11 = NDH*16; Z int dhact; /* mask of active dh's */ Z int dhsilos; /* mask of dh's with silo in use */ Z*************** Z*** 67,73 **** Z int dhhighrate = 100; /* silo on if dhchars > dhhighrate */ Z int dhlowrate = 75; /* silo off if dhrate < dhlowrate */ Z static short timerstarted; Z! int dhstart(), ttrstrt(); Z Z #if defined(UCB_CLIST) Z extern ubadr_t clstaddr; Z--- 63,70 ---- Z int dhhighrate = 100; /* silo on if dhchars > dhhighrate */ Z int dhlowrate = 75; /* silo off if dhrate < dhlowrate */ Z static short timerstarted; Z! int dhstart(); Z! static int dmtodh(), dhtodm(); Z Z #if defined(UCB_CLIST) Z extern ubadr_t clstaddr; Z*************** Z*** 76,82 **** Z #define cpaddr(x) (x) Z #endif Z Z! #define UNIT(x) (minor(x) & 0177) Z Z /* Z * Routine called to attach a dh. Z--- 73,81 ---- Z #define cpaddr(x) (x) Z #endif Z Z! #define UNIT(x) (x & 0x3f) Z! #define SOFTCAR 0x80 Z! #define HWFLOW 0x40 Z Z /* Z * Routine called to attach a dh. Z*************** Z*** 116,220 **** Z Z /* Z * Open a DH11 line. Turn on this dh if this is Z! * the first use of it. Also do a dmopen to wait for carrier. Z */ Z /*ARGSUSED*/ Z dhopen(dev, flag) Z dev_t dev; Z! { Z register struct tty *tp; Z- register int unit, dh; Z register struct dhdevice *addr; Z! register struct uba_device *ui; Z! int s; Z Z unit = UNIT(dev); Z dh = unit >> 4; Z! if (unit >= NDH*16 || (ui = &dhinfo[dh])->ui_alive == 0) Z! return (ENXIO); Z tp = &dh11[unit]; Z- if (tp->t_state&TS_XCLUDE && u.u_uid!=0) Z- return (EBUSY); Z addr = (struct dhdevice *)ui->ui_addr; Z tp->t_addr = (caddr_t)addr; Z tp->t_oproc = dhstart; Z- tp->t_state |= TS_WOPEN; Z Z! /* Z! * While setting up state for this uba and this dh, Z! * block uba resets which can clear the state. Z! */ Z! s = spl5(); Z! if (timerstarted == 0) { Z timerstarted++; Z timeout(dhtimer, (caddr_t) 0, hz); Z! } Z! if ((dhact&(1<un.dhcsr |= DH_IE; Z dhact |= (1<dhsilo = 0; Z! } Z! splx(s); Z! /* Z! * If this is first open, initialize tty state to default. Z! */ Z! if ((tp->t_state&TS_ISOPEN) == 0) { Z! ttychars(tp); Z! #ifndef PORTSELECTOR Z! if (tp->t_ispeed == 0) { Z! #else Z tp->t_state |= TS_HUPCLS; Z! #endif PORTSELECTOR Z! tp->t_ispeed = ISPEED; Z! tp->t_ospeed = ISPEED; Z tp->t_flags = IFLAGS; Z! #ifndef PORTSELECTOR Z! } Z! #endif Z dhparam(unit); Z! } Z dmopen(dev); Z! return ((*linesw[tp->t_line].l_open)(dev, tp)); Z! } Z Z /* Z * Close a DH line, turning off the DM11. Z */ Z- /*ARGSUSED*/ Z dhclose(dev, flag) Z! dev_t dev; Z! int flag; Z! { Z register struct tty *tp; Z! register unit; Z Z unit = UNIT(dev); Z tp = &dh11[unit]; Z (*linesw[tp->t_line].l_close)(tp, flag); Z ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); Z! if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) Z! dmctl(unit, DML_OFF, DMSET); Z ttyclose(tp); Z! } Z Z dhread(dev, uio, flag) Z dev_t dev; Z struct uio *uio; Z int flag; Z! { Z register struct tty *tp = &dh11[UNIT(dev)]; Z Z return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); Z! } Z Z dhwrite(dev, uio, flag) Z dev_t dev; Z struct uio *uio; Z! { Z register struct tty *tp = &dh11[UNIT(dev)]; Z Z return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); Z! } Z Z /* Z * DH11 receiver interrupt. Z--- 115,241 ---- Z Z /* Z * Open a DH11 line. Turn on this dh if this is Z! * the first use of it. Z */ Z /*ARGSUSED*/ Z dhopen(dev, flag) Z dev_t dev; Z! { Z register struct tty *tp; Z register struct dhdevice *addr; Z! register int unit; Z! struct uba_device *ui; Z! int dh, s, error; Z Z unit = UNIT(dev); Z dh = unit >> 4; Z! if (unit >= NDH*16 || (ui = &dhinfo[dh])->ui_alive == 0) Z! return(ENXIO); Z tp = &dh11[unit]; Z addr = (struct dhdevice *)ui->ui_addr; Z tp->t_addr = (caddr_t)addr; Z tp->t_oproc = dhstart; Z Z! if (timerstarted == 0) Z! { Z timerstarted++; Z timeout(dhtimer, (caddr_t) 0, hz); Z! } Z! if ((dhact&(1<un.dhcsr |= DH_IE; Z dhact |= (1<dhsilo = 0; Z! } Z! s = spltty(); Z! if ((tp->t_state & TS_ISOPEN) == 0) Z! { Z! tp->t_state |= TS_WOPEN; Z! if (tp->t_ispeed == 0) Z! { Z tp->t_state |= TS_HUPCLS; Z! tp->t_ispeed = B9600; Z! tp->t_ospeed = B9600; Z tp->t_flags = IFLAGS; Z! } Z! ttychars(tp); Z! tp->t_dev = dev; Z! if (dev & HWFLOW) Z! tp->t_flags |= RTSCTS; Z! else Z! tp->t_flags &= ~RTSCTS; Z dhparam(unit); Z! } Z! else if ((tp->t_state & TS_XCLUDE) && u.u_uid) Z! { Z! error = EBUSY; Z! goto out; Z! } Z dmopen(dev); Z! if ((dmctl(unit, 0, DMGET) & DML_CAR) || (dev & SOFTCAR)) Z! tp->t_state |= TS_CARR_ON; Z! while ((tp->t_state & TS_CARR_ON) == 0 && !(flag & O_NONBLOCK)) Z! { Z! tp->t_state |= TS_WOPEN; Z! sleep((caddr_t)&tp->t_rawq, TTIPRI); Z! } Z! error = (*linesw[tp->t_line].l_open)(dev, tp); Z! out: Z! splx(s); Z! return(error); Z! } Z Z /* Z * Close a DH line, turning off the DM11. Z */ Z dhclose(dev, flag) Z! dev_t dev; Z! int flag; Z! { Z register struct tty *tp; Z! register int unit; Z Z unit = UNIT(dev); Z tp = &dh11[unit]; Z+ if ((tp->t_state & (TS_WOPEN | TS_ISOPEN)) == 0) Z+ return(EBADF); /* XXX */ Z (*linesw[tp->t_line].l_close)(tp, flag); Z ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); Z! dmctl(unit, DML_OFF, DMSET); Z ttyclose(tp); Z! if (dh_overrun[unit]) Z! { Z! log(LOG_NOTICE, "dh%d %d overruns\n", dh_overrun[unit]); Z! dh_overrun[unit] = 0; Z! } Z! return(0); Z! } Z Z+ dhselect(dev, rw) Z+ dev_t dev; Z+ int rw; Z+ { Z+ return(ttyselect(&dh11[UNIT(dev)], rw)); Z+ } Z+ Z dhread(dev, uio, flag) Z dev_t dev; Z struct uio *uio; Z int flag; Z! { Z register struct tty *tp = &dh11[UNIT(dev)]; Z Z return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); Z! } Z Z dhwrite(dev, uio, flag) Z dev_t dev; Z struct uio *uio; Z! { Z register struct tty *tp = &dh11[UNIT(dev)]; Z Z return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); Z! } Z Z /* Z * DH11 receiver interrupt. Z*************** Z*** 226,238 **** Z register int c; Z register struct dhdevice *addr; Z struct tty *tp0; Z! struct uba_device *ui; Z! int overrun = 0; Z Z! ui = &dhinfo[dh]; Z! if (ui == 0 || ui->ui_alive == 0) Z return; Z- addr = (struct dhdevice *)ui->ui_addr; Z tp0 = &dh11[dh<<4]; Z /* Z * Loop fetching characters from the silo for this Z--- 247,257 ---- Z register int c; Z register struct dhdevice *addr; Z struct tty *tp0; Z! int line, p; Z Z! addr = (struct dhdevice *)dhinfo[dh].ui_addr; Z! if (addr == 0) /* Can't happen? */ Z return; Z tp0 = &dh11[dh<<4]; Z /* Z * Loop fetching characters from the silo for this Z*************** Z*** 239,261 **** Z * dh until there are no more in the silo. Z */ Z while ((c = addr->dhrcr) < 0) { Z! tp = tp0 + ((c>>8)&0xf); Z dhchars[dh]++; Z if ((tp->t_state&TS_ISOPEN)==0) { Z wakeup((caddr_t)&tp->t_rawq); Z- #ifdef PORTSELECTOR Z- if ((tp->t_state&TS_WOPEN) == 0) Z- #endif Z continue; Z } Z! if (c & DH_PE) Z! if ((tp->t_flags & (EVENP|ODDP)) == EVENP Z! || (tp->t_flags & (EVENP|ODDP)) == ODDP) Z continue; Z! if ((c & DH_DO) && overrun == 0) { Z! log(LOG_WARNING, "dh%d: silo overflow\n", dh); Z! overrun = 1; Z! } Z if (c & DH_FE) Z /* Z * At framing error (break) generate Z--- 258,281 ---- Z * dh until there are no more in the silo. Z */ Z while ((c = addr->dhrcr) < 0) { Z! line = (c >> 8) & 0xf; Z! tp = tp0 + line; Z dhchars[dh]++; Z if ((tp->t_state&TS_ISOPEN)==0) { Z wakeup((caddr_t)&tp->t_rawq); Z continue; Z } Z! if (c & DH_PE) Z! { Z! p = tp->t_flags & (EVENP|ODDP); Z! if (p == EVENP || p == ODDP) Z continue; Z! } Z! if (c & DH_DO) Z! { Z! dh_overrun[(dh << 4) + line]++; Z! continue; Z! } Z if (c & DH_FE) Z /* Z * At framing error (break) generate Z*************** Z*** 285,331 **** Z */ Z /*ARGSUSED*/ Z dhioctl(dev, cmd, data, flag) Z u_int cmd; Z caddr_t data; Z! { Z register struct tty *tp; Z register unit = UNIT(dev); Z! int error; Z Z tp = &dh11[unit]; Z error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); Z! if (error >= 0) Z! return (error); Z error = ttioctl(tp, cmd, data, flag); Z! if (error >= 0) { Z! if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS || Z! cmd == TIOCLBIC || cmd == TIOCLSET) Z dhparam(unit); Z! return (error); Z } Z- switch (cmd) { Z Z! case TIOCSBRK: Z! ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017); Z! break; Z Z! case TIOCCBRK: Z! ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); Z! break; Z Z! case TIOCSDTR: Z! dmctl (unit, DML_DTR|DML_RTS, DMBIS); Z! break; Z Z! case TIOCCDTR: Z! dmctl (unit, DML_DTR|DML_RTS, DMBIC); Z! break; Z! Z! default: Z! return (ENOTTY); Z } Z- return (0); Z- } Z Z /* Z * Set parameters from open or stty into the DH hardware Z--- 305,390 ---- Z */ Z /*ARGSUSED*/ Z dhioctl(dev, cmd, data, flag) Z+ dev_t dev; Z u_int cmd; Z caddr_t data; Z! int flag; Z! { Z register struct tty *tp; Z register unit = UNIT(dev); Z! int error, brkline; Z Z tp = &dh11[unit]; Z error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); Z! if (error >= 0) Z! return(error); Z error = ttioctl(tp, cmd, data, flag); Z! if (error >= 0) Z! { Z! if (cmd == TIOCSETP || cmd == TIOCSETN || Z! cmd == TIOCLBIS || cmd == TIOCLBIC || cmd == TIOCLSET) Z dhparam(unit); Z! return(error); Z! } Z! brkline = 1 << (unit & 0xf); Z! switch (cmd) Z! { Z! case TIOCSBRK: Z! ((struct dhdevice *)(tp->t_addr))->dhbreak |= brkline; Z! break; Z! case TIOCCBRK: Z! ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~brkline; Z! break; Z! case TIOCSDTR: Z! (void)dmctl(unit, DML_DTR|DML_RTS, DMBIS); Z! break; Z! case TIOCCDTR: Z! (void)dmctl(unit, DML_DTR|DML_RTS, DMBIC); Z! break; Z! case TIOCMSET: Z! (void)dmctl(unit, dmtodh(*(int *)data, DMSET)); Z! break; Z! case TIOCMBIS: Z! (void)dmctl(unit, dmtodh(*(int *)data, DMBIS)); Z! break; Z! case TIOCMBIC: Z! (void)dmctl(unit, dmtodh(*(int *)data, DMBIC)); Z! break; Z! case TIOCMGET: Z! *(int *)data = dhtodm(dmctl(unit, 0, DMGET)); Z! break; Z! default: Z! return(ENOTTY); Z! } Z! return(0); Z } Z Z! static int Z! dmtodh(bits) Z! register int bits; Z! { Z! register int b = 0; Z Z! if (bits & TIOCM_RTS) b |= DML_RTS; Z! if (bits & TIOCM_DTR) b |= DML_DTR; Z! if (bits & TIOCM_LE) b |= DML_LE; Z! return(b); Z! } Z Z! static int Z! dhtodm(bits) Z! register int bits; Z! { Z! register int b = 0; Z Z! if (bits & DML_RNG) b |= TIOCM_RNG; Z! if (bits & DML_CAR) b |= TIOCM_CAR; Z! if (bits & DML_CTS) b |= TIOCM_CTS; Z! if (bits & DML_RTS) b |= TIOCM_RTS; Z! if (bits & DML_DTR) b |= TIOCM_DTR; Z! if (bits & DML_LE) b |= TIOCM_LE; Z! return(b); Z } Z Z /* Z * Set parameters from open or stty into the DH hardware Z*************** Z*** 333,339 **** Z */ Z dhparam(unit) Z register int unit; Z! { Z register struct tty *tp; Z register struct dhdevice *addr; Z register int lpar; Z--- 392,398 ---- Z */ Z dhparam(unit) Z register int unit; Z! { Z register struct tty *tp; Z register struct dhdevice *addr; Z register int lpar; Z*************** Z*** 345,358 **** Z * Block interrupts so parameters will be set Z * before the line interrupts. Z */ Z! s = spl5(); Z addr->un.dhcsrl = (unit&0xf)|DH_IE; Z! if ((tp->t_ispeed)==0) { Z tp->t_state |= TS_HUPCLS; Z dmctl(unit, DML_OFF, DMSET); Z! splx(s); Z! return; Z! } Z lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6); Z if ((tp->t_ispeed) == B134) Z lpar |= BITS6|PENABLE|HDUPLX; Z--- 404,417 ---- Z * Block interrupts so parameters will be set Z * before the line interrupts. Z */ Z! s = spltty(); Z addr->un.dhcsrl = (unit&0xf)|DH_IE; Z! if ((tp->t_ispeed)==0) Z! { Z tp->t_state |= TS_HUPCLS; Z dmctl(unit, DML_OFF, DMSET); Z! goto out; Z! } Z lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6); Z if ((tp->t_ispeed) == B134) Z lpar |= BITS6|PENABLE|HDUPLX; Z*************** Z*** 365,372 **** Z if ((tp->t_ospeed) == B110) Z lpar |= TWOSB; Z addr->dhlpr = lpar; Z splx(s); Z! } Z Z /* Z * DH transmitter interrupt. Z--- 424,433 ---- Z if ((tp->t_ospeed) == B110) Z lpar |= TWOSB; Z addr->dhlpr = lpar; Z+ out: Z splx(s); Z! return(0); Z! } Z Z /* Z * DH transmitter interrupt. Z*************** Z*** 379,395 **** Z register struct tty *tp; Z register struct dhdevice *addr; Z short ttybit, bar, *sbar; Z- struct uba_device *ui; Z register int unit; Z u_short cntr; Z ubadr_t car; Z struct dmdevice *dmaddr; Z Z! ui = &dhinfo[dh]; Z! addr = (struct dhdevice *)ui->ui_addr; Z if (addr->un.dhcsr & DH_NXM) { Z addr->un.dhcsr |= DH_CNI; Z! printf("dh%d: NXM\n", dh); Z } Z sbar = &dhsar[dh]; Z bar = *sbar & ~addr->dhbar; Z--- 440,454 ---- Z register struct tty *tp; Z register struct dhdevice *addr; Z short ttybit, bar, *sbar; Z register int unit; Z u_short cntr; Z ubadr_t car; Z struct dmdevice *dmaddr; Z Z! addr = (struct dhdevice *)dhinfo[dh].ui_addr; Z if (addr->un.dhcsr & DH_NXM) { Z addr->un.dhcsr |= DH_CNI; Z! log(LOG_NOTICE, "dh%d NXM\n", dh); Z } Z sbar = &dhsar[dh]; Z bar = *sbar & ~addr->dhbar; Z*************** Z*** 414,420 **** Z * Z * In either case, the extension bits are 0. Z */ Z! car = (caddr_t)addr->dhcar; Z if (!ubmap) { Z #if defined(CS02) Z dmaddr = (struct dmdevice *)dminfo[dh].ui_addr; Z--- 473,479 ---- Z * Z * In either case, the extension bits are 0. Z */ Z! car = (ubadr_t)addr->dhcar; Z if (!ubmap) { Z #if defined(CS02) Z dmaddr = (struct dmdevice *)dminfo[dh].ui_addr; Z*************** Z*** 456,502 **** Z * Must hold interrupts in following code to prevent Z * state of the tp from changing. Z */ Z! s = spl5(); Z /* Z * If it's currently active, or delaying, no need to do anything. Z */ Z if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) Z goto out; Z /* Z- * If there are sleepers, and the output has drained below low Z- * water mark, wake up the sleepers. Z- */ Z- if (tp->t_outq.c_cc<=TTLOWAT(tp)) { Z- if (tp->t_state&TS_ASLEEP) { Z- tp->t_state &= ~TS_ASLEEP; Z- wakeup((caddr_t)&tp->t_outq); Z- } Z- if (tp->t_wsel) { Z- selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); Z- tp->t_wsel = 0; Z- tp->t_state &= ~TS_WCOLL; Z- } Z- } Z- /* Z * Now restart transmission unless the output queue is Z * empty. Z */ Z if (tp->t_outq.c_cc == 0) Z goto out; Z! if (tp->t_flags & (RAW|LITOUT)) Z! nch = ndqb(&tp->t_outq, 0); Z! else { Z! nch = ndqb(&tp->t_outq, 0200); Z! /* Z! * If first thing on queue is a delay, process it. Z! */ Z! if (nch == 0) { Z! nch = getc(&tp->t_outq); Z! timeout(ttrstrt, (caddr_t) tp, (nch&0x7f)+6); Z! tp->t_state |= TS_TIMEOUT; Z! goto out; Z! } Z! } Z /* Z * If characters to transmit, restart transmission. Z */ Z--- 515,538 ---- Z * Must hold interrupts in following code to prevent Z * state of the tp from changing. Z */ Z! s = spltty(); Z /* Z * If it's currently active, or delaying, no need to do anything. Z */ Z if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) Z goto out; Z+ ttyowake(tp); /* Wake up any sleepers */ Z /* Z * Now restart transmission unless the output queue is Z * empty. Z */ Z if (tp->t_outq.c_cc == 0) Z goto out; Z! /* Z! * This is where any per character delay handling would be done if ever Z! * implemented again. See the comments in dhv.c and dhu.c Z! */ Z! nch = ndqb(&tp->t_outq, 0); Z /* Z * If characters to transmit, restart transmission. Z */ Z*************** Z*** 542,548 **** Z /* Z * Block input/output interrupts while messing with state. Z */ Z! s = spl5(); Z if (tp->t_state & TS_BUSY) { Z /* Z * Device is transmitting; stop output Z--- 578,584 ---- Z /* Z * Block input/output interrupts while messing with state. Z */ Z! s = spltty(); Z if (tp->t_state & TS_BUSY) { Z /* Z * Device is transmitting; stop output Z*************** Z*** 574,580 **** Z if (dhsilos) { Z dhfasttimers++; /*DEBUG*/ Z timercalls++; Z! s = spl5(); Z for (dh = 0; dh < NDH; dh++) Z if (dhsilos & (1 << dh)) Z dhrint(dh); Z--- 610,616 ---- Z if (dhsilos) { Z dhfasttimers++; /*DEBUG*/ Z timercalls++; Z! s = spltty(); Z for (dh = 0; dh < NDH; dh++) Z if (dhsilos & (1 << dh)) Z dhrint(dh); Z*************** Z*** 607,646 **** Z */ Z dmopen(dev) Z dev_t dev; Z! { Z register struct tty *tp; Z register struct dmdevice *addr; Z- register struct uba_device *ui; Z register int unit; Z! register int dm; Z! int s; Z Z unit = UNIT(dev); Z dm = unit >> 4; Z tp = &dh11[unit]; Z! unit &= 0xf; Z! if (dev & 0200) Z! dhsoftCAR[dm] |= (1<<(unit&0xf)); Z! else Z! dhsoftCAR[dm] &= ~(1<<(unit&0xf)); Z! if (dm >= NDH || (ui = &dminfo[dm])->ui_alive == 0) { Z tp->t_state |= TS_CARR_ON; Z return; Z } Z- addr = (struct dmdevice *)ui->ui_addr; Z- s = spl5(); Z- addr->dmcsr &= ~DM_SE; Z- while (addr->dmcsr & DM_BUSY) Z- ; Z- addr->dmcsr = unit & 017; Z- addr->dmlstat = DML_ON; Z- if ((addr->dmlstat&DML_CAR) || (dhsoftCAR[dm]&(1<t_state |= TS_CARR_ON; Z- addr->dmcsr = DM_IE|DM_SE; Z- while ((tp->t_state & TS_CARR_ON)==0) Z- sleep((caddr_t) &tp->t_rawq, TTIPRI); Z- splx(s); Z- } Z Z /* Z * Dump control bits into the DM registers. Z--- 643,664 ---- Z */ Z dmopen(dev) Z dev_t dev; Z! { Z register struct tty *tp; Z register struct dmdevice *addr; Z register int unit; Z! int dm; Z Z unit = UNIT(dev); Z dm = unit >> 4; Z tp = &dh11[unit]; Z! if (dm >= NDH || dminfo[dm].ui_alive == 0) Z! { Z tp->t_state |= TS_CARR_ON; Z return; Z+ } Z+ (void)dmctl(unit, DML_ON, DMSET); Z } Z Z /* Z * Dump control bits into the DM registers. Z*************** Z*** 648,689 **** Z dmctl(unit, bits, how) Z int unit; Z int bits, how; Z! { Z! register struct uba_device *ui; Z register struct dmdevice *addr; Z! register s; Z! int dm; Z Z dm = unit >> 4; Z! if ((ui = &dminfo[dm])->ui_alive == 0) Z! return; Z! addr = (struct dmdevice *)ui->ui_addr; Z! s = spl5(); Z addr->dmcsr &= ~DM_SE; Z! while (addr->dmcsr & DM_BUSY) Z ; Z addr->dmcsr = unit & 0xf; Z! switch (how) { Z! case DMSET: Z! addr->dmlstat = bits; Z! break; Z! case DMBIS: Z! addr->dmlstat |= bits; Z! break; Z! case DMBIC: Z! addr->dmlstat &= ~bits; Z! break; Z! } Z addr->dmcsr = DM_IE|DM_SE; Z splx(s); Z! } Z Z /* Z * DM interrupt; deal with carrier transitions. Z */ Z dmintr(dm) Z! register int dm; Z! { Z register struct uba_device *ui; Z register struct tty *tp; Z register struct dmdevice *addr; Z--- 666,713 ---- Z dmctl(unit, bits, how) Z int unit; Z int bits, how; Z! { Z register struct dmdevice *addr; Z! register int s, mbits; Z! int dm; Z Z dm = unit >> 4; Z! addr = (struct dmdevice *)dminfo[dm].ui_addr; Z! if (!addr) Z! return(0); Z! s = spltty(); Z addr->dmcsr &= ~DM_SE; Z! while (addr->dmcsr & DM_BUSY) Z ; Z addr->dmcsr = unit & 0xf; Z! mbits = addr->dmlstat; Z! Z! switch (how) Z! { Z! case DMGET: Z! break; /* go re-enable scan */ Z! case DMSET: Z! mbits = bits; Z! break; Z! case DMBIS: Z! mbits |= bits; Z! break; Z! case DMBIC: Z! mbits &= ~bits; Z! break; Z! } Z! addr->dmlstat = mbits; Z addr->dmcsr = DM_IE|DM_SE; Z splx(s); Z! return(mbits); Z! } Z Z /* Z * DM interrupt; deal with carrier transitions. Z */ Z dmintr(dm) Z! int dm; Z! { Z register struct uba_device *ui; Z register struct tty *tp; Z register struct dmdevice *addr; Z*************** Z*** 690,709 **** Z int unit; Z Z ui = &dminfo[dm]; Z- if (ui == 0) Z- return; Z addr = (struct dmdevice *)ui->ui_addr; Z! if (addr->dmcsr&DM_DONE) { Z! if (addr->dmcsr&DM_CF) { Z! unit = addr->dmcsr & 0xf; Z! tp = &dh11[(dm << 4) + unit]; Z! if (addr->dmlstat & DML_CAR) Z! (void)(*linesw[tp->t_line].l_modem)(tp, 1); Z! else if ((dhsoftCAR[dm] & (1<t_line].l_modem)(tp, 0) == 0) Z! addr->dmlstat = 0; Z } Z! addr->dmcsr = DM_IE|DM_SE; Z } Z- } Z #endif Z--- 714,748 ---- Z int unit; Z Z ui = &dminfo[dm]; Z addr = (struct dmdevice *)ui->ui_addr; Z! if (addr->dmcsr&DM_DONE == 0) Z! return; Z! unit = addr->dmcsr & 0xf; Z! tp = &dh11[(dm << 4) + unit]; Z! if (addr->dmcsr & DM_CF) Z! { Z! if (addr->dmlstat & DML_CAR) Z! (void)(*linesw[tp->t_line].l_modem)(tp, 1); Z! else if (!(tp->t_dev & SOFTCAR) && Z! (*linesw[tp->t_line].l_modem)(tp, 0) == 0) Z! addr->dmlstat = 0; Z } Z! if (addr->dmcsr & DM_CTS) Z! { Z! if (tp->t_flags & RTSCTS) Z! { Z! if (addr->dmlstat & DML_CTS) Z! { Z! tp->t_state &= ~TS_TTSTOP; Z! ttstart(tp); Z! } Z! else Z! { Z! tp->t_state |= TS_TTSTOP; Z! dhstop(tp, 0); Z! } Z! } Z! } Z! addr->dmcsr = DM_IE|DM_SE; Z } Z #endif Z*** /usr/src/sys/pdp/conf.c.old Fri Jan 31 20:49:43 1997 Z--- /usr/src/sys/pdp/conf.c Sat May 31 14:38:53 1997 Z*************** Z*** 3,9 **** Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)conf.c 3.0 (2.11BSD GTE) 1997/1/30 Z */ Z Z #include "param.h" Z--- 3,9 ---- Z * All rights reserved. The Berkeley software License Agreement Z * specifies the terms and conditions for redistribution. Z * Z! * @(#)conf.c 3.1 (2.11BSD GTE) 1997/5/31 Z */ Z Z #include "param.h" Z*************** Z*** 230,235 **** Z--- 230,236 ---- Z #include "dh.h" Z #if NDH > 0 Z int dhopen(), dhclose(), dhread(), dhwrite(), dhioctl(), dhstop(); Z+ int dhselect(); Z extern struct tty dh11[]; Z #else Z #define dhopen nodev Z*************** Z*** 238,243 **** Z--- 239,245 ---- Z #define dhwrite nodev Z #define dhioctl nodev Z #define dhstop nodev Z+ #define dhselect nodev Z #define dh11 ((struct tty *) NULL) Z #endif Z Z*************** Z*** 290,295 **** Z--- 292,298 ---- Z #include "dhu.h" Z #if NDHU > 0 Z int dhuopen(), dhuclose(), dhuread(), dhuwrite(), dhuioctl(), dhustop(); Z+ int dhuselect(); Z extern struct tty dhu_tty[]; Z #else Z #define dhuopen nodev Z*************** Z*** 298,303 **** Z--- 301,307 ---- Z #define dhuwrite nodev Z #define dhuioctl nodev Z #define dhustop nodev Z+ #define dhuselect nodev Z #define dhu_tty ((struct tty *) NULL) Z #endif Z Z*************** Z*** 368,378 **** Z nulldev, Z /* dh = 3 */ Z dhopen, dhclose, dhread, dhwrite, Z! dhioctl, dhstop, dh11, ttselect, Z nulldev, Z /* dhu = 4 */ Z dhuopen, dhuclose, dhuread, dhuwrite, Z! dhuioctl, dhustop, dhu_tty, ttselect, Z nulldev, Z /* lp = 5 */ Z lpopen, lpclose, nodev, lpwrite, Z--- 372,382 ---- Z nulldev, Z /* dh = 3 */ Z dhopen, dhclose, dhread, dhwrite, Z! dhioctl, dhstop, dh11, dhselect, Z nulldev, Z /* dhu = 4 */ Z dhuopen, dhuclose, dhuread, dhuwrite, Z! dhuioctl, dhustop, dhu_tty, dhuselect, Z nulldev, Z /* lp = 5 */ Z lpopen, lpclose, nodev, lpwrite, Z*** /usr/src/man/man4/dhu.4.old Sat Aug 1 11:31:31 1987 Z--- /usr/src/man/man4/dhu.4 Sat May 31 16:18:25 1997 Z*************** Z*** 2,10 **** Z .\" All rights reserved. The Berkeley software License Agreement Z .\" specifies the terms and conditions for redistribution. Z .\" Z! .\" @(#)dhu.4 6.2 (Berkeley) 8/1/87 Z .\" Z! .TH DHU 4 "August 1, 1987" Z .UC 2 Z .SH NAME Z dhu \- DHU-11 communications multiplexer Z--- 2,10 ---- Z .\" All rights reserved. The Berkeley software License Agreement Z .\" specifies the terms and conditions for redistribution. Z .\" Z! .\" @(#)dhu.4 6.2.1 (2.11BSD) 1997/5/31 Z .\" Z! .TH DHU 4 "May 31, 1997" Z .UC 2 Z .SH NAME Z dhu \- DHU-11 communications multiplexer Z*************** Z*** 12,23 **** Z .ft B Z .nf Z /sys/conf/SYSTEM: Z! NDHU \fIdhu_units\fP # DHU11, DHV11 Z Z /etc/dtab: Z .ta .5i +\w'#Name 'u +\w'Unit# 'u +\w'177777 'u +\w'Vector 'u +\w'Br 'u +\w'xxxxxxx 'u +\w'xxxxxxx 'u Z #Name Unit# Addr Vector Br Handler(s) # Comments Z! du ? 160020 310 5 dhurint dhuxint # dhv/dhu11 terminal mux Z .DT Z Z major device number(s): Z--- 12,23 ---- Z .ft B Z .nf Z /sys/conf/SYSTEM: Z! NDHU \fIdhu_units\fP # DHU11 Z Z /etc/dtab: Z .ta .5i +\w'#Name 'u +\w'Unit# 'u +\w'177777 'u +\w'Vector 'u +\w'Br 'u +\w'xxxxxxx 'u +\w'xxxxxxx 'u Z #Name Unit# Addr Vector Br Handler(s) # Comments Z! du ? 160020 310 5 dhurint dhuxint # dhu11 terminal mux Z .DT Z Z major device number(s): Z*************** Z*** 24,30 **** Z raw: 4 Z minor device encoding: Z bits 0017 specify line on DHU unit Z! bits 0160 specify DHU unit Z bit 0200 specifies non-blocking open (``CD always on'') Z .fi Z .ft R Z--- 24,31 ---- Z raw: 4 Z minor device encoding: Z bits 0017 specify line on DHU unit Z! bits 0060 specify DHU unit Z! bit 0100 specify RTS/CTS flow control Z bit 0200 specifies non-blocking open (``CD always on'') Z .fi Z .ft R Z*************** Z*** 47,53 **** Z connected, and that the line should be treated as hard-wired with carrier Z always present. Thus creating the special character device node "4, 130" via Z .I "mknod /dev/ttyS2 c 4 130" Z! would cause line ttyS2 to be treated in this way. Z .PP Z The DHU-11 driver normally uses input silos Z and delays receiver interrupts by 20 milliseconds Z--- 48,57 ---- Z connected, and that the line should be treated as hard-wired with carrier Z always present. Thus creating the special character device node "4, 130" via Z .I "mknod /dev/ttyS2 c 4 130" Z! would cause line ttyS2 to be treated in this way. Turning on bit 6 (adding Z! 64) to the minor device number via Z! .I "mknod /dev/ttyS2 c 4 194" Z! enables RTS/CTS flow control. Z .PP Z The DHU-11 driver normally uses input silos Z and delays receiver interrupts by 20 milliseconds Z*************** Z*** 57,72 **** Z .SH "SEE ALSO" Z tty(4) Z .SH DIAGNOSTICS Z! \fBdhu(%d,%d): NXM fault\fR. No response from UNIBUS on a DMA transfer Z! within a timeout period. This is often followed by a UNIBUS adapter Z! error. This occurs most frequently when the UNIBUS is heavily loaded Z! and when devices which hog the bus (such as RK07s) are present. Z It is not serious. Z .PP Z! \fBdhu%d: silo overflow\fR. The character input silo overflowed Z! before it could be serviced. This can happen if a hard error occurs Z! when the CPU is running with elevated priority, as the system may Z! then print a message on the console with interrupts disabled. Z .SH NOTES Z The driver currently does not make full use of the hardware Z capabilities of the DHU-11, for dealing with XON/XOFF flow-control or hard-wired Z--- 61,75 ---- Z .SH "SEE ALSO" Z tty(4) Z .SH DIAGNOSTICS Z! \fBdhu(%d,%d) NXM\fR. No response from UNIBUS on a DMA transfer Z! within a timeout period. This has never been observed on a PDP-11 and is Z! believed to be a carryover from the VAX driver when it was ported. Z It is not serious. Z .PP Z! \fBdhu%d %d overruns\fR. The character input silo overflowed Z! before it could be serviced. This message is printed only at line close time Z! rather than on each overrun error. Kernel printf's are not interrupt driven Z! and caused more overruns by blocking interrupts for lengthy periods of time. Z .SH NOTES Z The driver currently does not make full use of the hardware Z capabilities of the DHU-11, for dealing with XON/XOFF flow-control or hard-wired Z*** /usr/src/man/man4/dh.4.old Thu Jul 23 20:29:11 1992 Z--- /usr/src/man/man4/dh.4 Sat May 31 16:25:08 1997 Z*************** Z*** 2,10 **** Z .\" All rights reserved. The Berkeley software License Agreement Z .\" specifies the terms and conditions for redistribution. Z .\" Z! .\" @(#)dh.4 6.3 (Berkeley) 7/23/92 Z .\" Z! .TH DH 4 "January 28, 1988" Z .UC 2 Z .SH NAME Z dh \- DH-11/DM-11 communications multiplexer Z--- 2,10 ---- Z .\" All rights reserved. The Berkeley software License Agreement Z .\" specifies the terms and conditions for redistribution. Z .\" Z! .\" @(#)dh.4 6.4 (2.11BSD) 1997/5/31 Z .\" Z! .TH DH 4 "May 31, 1997" Z .UC 2 Z .SH NAME Z dh \- DH-11/DM-11 communications multiplexer Z*************** Z*** 27,33 **** Z minor device encoding: Z bits 0017 specify line on DH unit Z bits 0060 specify DH unit Z! bit 0100 unused Z bit 0200 specifies non-blocking open (``CD always on'') Z .fi Z .ft R Z--- 27,33 ---- Z minor device encoding: Z bits 0017 specify line on DH unit Z bits 0060 specify DH unit Z! bit 0100 specify RTS/CTS (``hardware'') flowcontrol Z bit 0200 specifies non-blocking open (``CD always on'') Z .fi Z .ft R Z*************** Z*** 53,59 **** Z connected, and that the line should be treated as hard-wired with carrier Z always present. Thus creating the special character device node "3, 130" via Z .I "mknod /dev/ttyh2 c 3 130" Z! would cause line ttyh2 to be treated in this way. Z .PP Z The Z .I dh Z--- 53,63 ---- Z connected, and that the line should be treated as hard-wired with carrier Z always present. Thus creating the special character device node "3, 130" via Z .I "mknod /dev/ttyh2 c 3 130" Z! would cause line ttyh2 to be treated in this way. Bit Z! .I 0100 Z! of the minor device number enables RTS/CTS (also called ``hardware'') flow Z! control. It is enabled by adding 64 to the minor device number: Z! .I "mknod /dev/ttyh2 c 3 194" Z .PP Z The Z .I dh Z*************** Z*** 77,90 **** Z dtab(5), Z autoconfig(8) Z .SH DIAGNOSTICS Z! \fBdh%d: NXM\fR. No response from UNIBUS on a dma transfer Z! within a timeout period. This is often followed by a UNIBUS adapter Z! error. This occurs most frequently when the UNIBUS is heavily loaded Z! and when devices which hog the bus (such as rk07's) are present. Z It is not serious. Z .PP Z! \fBdh%d: silo overflow\fR. The character input silo overflowed Z! before it could be serviced. This can happen if a hard error occurs Z! when the CPU is running with elevated priority, as the system will Z! then print a message on the console with interrupts disabled. Z! It is not serious. Z--- 81,92 ---- Z dtab(5), Z autoconfig(8) Z .SH DIAGNOSTICS Z! \fBdh%d NXM\fR. No response from UNIBUS on a dma transfer Z! within a timeout period. This has never been observed on a PDP-11 and is Z! a carryover from the VAX driver when it was ported. Z It is not serious. Z .PP Z! \fBdh%d %d overruns\fR. The character input silo overflowed Z! before it could be serviced. This message is only printed at line close time. Z! It is not serious but does indicate that the system was not able to keep up Z! with the data flow. Z*** /usr/src/man/man4/Makefile.old Tue Feb 4 21:03:04 1997 Z--- /usr/src/man/man4/Makefile Sat May 31 16:11:07 1997 Z*************** Z*** 14,29 **** Z # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED Z # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Z # Z! # @(#)Makefile 5.4.2 (2.11BSD) 1997/2/4 Z # Z DESTDIR= Z MDIR= ${DESTDIR}/usr/man/cat4 Z! SRCS= acc.4 arp.4 bk.4 br.4 cons.4 css.4 de.4 dh.4 dhu.4 dmc.4 dr.4 dz.4 \ Z ec.4 en.4 fd.4 hk.4 ht.4 hy.4 icmp.4 idp.4 il.4 imp.4 impconf.4 inet.4 \ Z intro.4 ip.4 lo.4 lp.4 mem.4 mtio.4 networking.4 ns.4 nsip.4 \ Z null.4 pty.4 qe.4 ra.4 ram.4 rk.4 rl.4 rx.4 si.4 spp.4 sri.4 \ Z swap.4 tb.4 tcp.4 tm.4 tmscp.4 ts.4 tty.4 udp.4 vv.4 xp.4 Z! OBJS= acc.0 arp.0 bk.0 br.0 cons.0 css.0 de.0 dh.0 dhu.0 dmc.0 dr.0 \ Z dz.0 ec.0 en.0 fd.0 hk.0 ht.0 hy.0 icmp.0 idp.0 il.0 imp.0 impconf.0 \ Z inet.0 intro.0 ip.0 lo.0 lp.0 mem.0 mtio.0 networking.0 ns.0 \ Z nsip.0 null.0 pty.0 qe.0 ra.0 ram.0 rk.0 rl.0 rx.0 si.0 spp.0 \ Z--- 14,31 ---- Z # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED Z # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. Z # Z! # @(#)Makefile 5.4.3 (2.11BSD) 1997/5/31 Z # Z DESTDIR= Z MDIR= ${DESTDIR}/usr/man/cat4 Z! SRCS= acc.4 arp.4 bk.4 br.4 cons.4 css.4 de.4 dh.4 dhu.4 dhv.4 \ Z! dmc.4 dr.4 dz.4 \ Z ec.4 en.4 fd.4 hk.4 ht.4 hy.4 icmp.4 idp.4 il.4 imp.4 impconf.4 inet.4 \ Z intro.4 ip.4 lo.4 lp.4 mem.4 mtio.4 networking.4 ns.4 nsip.4 \ Z null.4 pty.4 qe.4 ra.4 ram.4 rk.4 rl.4 rx.4 si.4 spp.4 sri.4 \ Z swap.4 tb.4 tcp.4 tm.4 tmscp.4 ts.4 tty.4 udp.4 vv.4 xp.4 Z! OBJS= acc.0 arp.0 bk.0 br.0 cons.0 css.0 de.0 dh.0 dhu.0 dhv.0 \ Z! dmc.0 dr.0 \ Z dz.0 ec.0 en.0 fd.0 hk.0 ht.0 hy.0 icmp.0 idp.0 il.0 imp.0 impconf.0 \ Z inet.0 intro.0 ip.0 lo.0 lp.0 mem.0 mtio.0 networking.0 ns.0 \ Z nsip.0 null.0 pty.0 qe.0 ra.0 ram.0 rk.0 rl.0 rx.0 si.0 spp.0 \ Z*** /VERSION.old Fri May 9 21:57:12 1997 Z--- /VERSION Sat May 31 16:40:01 1997 Z*************** Z*** 1,5 **** Z! Current Patch Level: 373 Z! Date: May 9, 1997 Z Z 2.11 BSD Z ============ Z--- 1,5 ---- Z! Current Patch Level: 374 Z! Date: May 31, 1997 Z Z 2.11 BSD Z ============ SHAR_EOF fi if test -f '374.shar' then echo shar: "will not over-write existing file '374.shar'" else sed 's/^Z//' << \SHAR_EOF > '374.shar' Z#! /bin/sh Z# This is a shell archive, meaning: Z# 1. Remove everything above the #! /bin/sh line. Z# 2. Save the resulting text in a file. Z# 3. Execute the file with /bin/sh (not csh) to create: Z# /usr/src/man/man4/dhv.4 Z# This archive created: Thu Jun 12 22:25:54 1997 Zexport PATH; PATH=/bin:/usr/bin:$PATH Zif test -f '/usr/src/man/man4/dhv.4' Zthen Z echo shar: "will not over-write existing file '/usr/src/man/man4/dhv.4'" Zelse Zsed 's/^J//' << \SHAR_EOF > '/usr/src/man/man4/dhv.4' ZJ.\" ZJ.\" @(#)dhv.4 1.0 (2.11BSD) 1997/5/31 ZJ.\" ZJ.TH DHV 4 "May 31, 1997" ZJ.UC 2 ZJ.SH NAME ZJdhv \- DHV-11 communications multiplexer ZJ.SH SYNOPSIS ZJ.ft B ZJ.nf ZJ/sys/conf/SYSTEM: ZJ NDHV \fIdhv_units\fP # DHV11 ZJ ZJ/etc/dtab: ZJ.ta .5i +\w'#Name 'u +\w'Unit# 'u +\w'177777 'u +\w'Vector 'u +\w'Br 'u +\w'xxxxxxx 'u +\w'xxxxxxx 'u ZJ #Name Unit# Addr Vector Br Handler(s) # Comments ZJ dhv ? 160440 310 5 dhvrint dhvxint # dhv terminal mux ZJ.DT ZJ ZJmajor device number(s): ZJ raw: 24 ZJminor device encoding: ZJ bits 0007 specify line on DHV unit ZJ bits 0070 specify DHV unit ZJ bit 0100 specifies RTS/CTS (``hardware'') flowcontrol ZJ bit 0200 specifies non-blocking open (``CD always on'') ZJ.fi ZJ.ft R ZJ.SH DESCRIPTION ZJA DHV-11 provides 8 communication lines. ZJ.PP ZJEach line attached to the DHV-11 communications multiplexer ZJbehaves as described in ZJ.IR tty (4). ZJInput and output for each line may independently ZJbe set to run at any of 13 speeds (50 and 200 baud are not available). While ZJ38400 is available the underlying hardware is not fast enough to handle it and ZJthere will be pauses/gaps between characters. ZJ.PP ZJBit ZJ.I 0200 ZJof the minor device number for DHV lines ZJmay be set to say that a line is not properly ZJconnected, and that the line should be treated as hard-wired with carrier ZJalways present. Thus creating the special character device node "4, 130" via ZJ.I "mknod /dev/ttyS2 c 4 130" ZJwould cause line ttyS2 to be treated in this way. Turning on bit 6 in the ZJminor device number via ZJ.I "mknod /dev/ttyS2 c 4 194" ZJwould enable RTS/CTS flow control. ZJ.PP ZJThe DHV-11 has an input silo but does \fBnot\fP have the programmable ZJreceiver delay that the DHU (and DHQ) have. Thus system services more ZJinterrupts (i.e. gets fewer characters per interrupt on average) with a ZJDHV-11 than with a DHQ (in DHU mode). ZJ.SH FILES ZJ/dev/tty[S-Z][0-9a-f] ZJ.SH "SEE ALSO" ZJtty(4) ZJ.SH DIAGNOSTICS ZJ\fBdhv%d,%d NXM\fR. No response from QBUS on a DMA transfer ZJwithin a timeout period. This error has never been observed on a PDP-11 and ZJis a carryover from the VAX driver when that was ported to 2BSD. ZJ.PP ZJ\fBdhv%d diag %o\fR. Diagnostic information from the DHV11. This has never ZJbeen observed. The DHV-11 hardware manual will be required to decode the ZJvalue printed out. ZJ.PP ZJ\fBdhv%d: %d overruns\fR. The character input silo overflowed ZJbefore it could be serviced. This message is printed only when the line is ZJclosed. By only printing this when the line is closed further silo overruns ZJare avoided (kernel printf statements are not interrupt driven). ZJ.SH NOTES ZJThe DHV lacks the receiver delay that the DHU (and DHQ) have. Thus it is ZJextremely easy (indeed it's almost certain at higher data rates) for a ZJDHV-11 to enter an interrupt per character mode and use 70-80% of the cpu. ZSHAR_EOF Zchmod 444 '/usr/src/man/man4/dhv.4' Zfi Zexit 0 Z# End of shell archive SHAR_EOF fi exit 0 # End of shell archive