-/* dh.c 4.27 81/03/06 */
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ * @(#)dh.c 7.5 (Berkeley) %G%
+ */
#include "dh.h"
#if NDH > 0
-#define DELAY(i) { register int j = i; while (--j > 0); }
/*
* DH-11/DM-11 driver
*/
+#include "../machine/pte.h"
+
#include "bk.h"
-#include "../h/param.h"
-#include "../h/conf.h"
-#include "../h/dir.h"
-#include "../h/user.h"
-#include "../h/tty.h"
-#include "../h/map.h"
-#include "../h/pte.h"
-#include "../h/buf.h"
-#include "../h/vm.h"
-#include "../h/uba.h"
-#include "../h/bk.h"
-#include "../h/clist.h"
-#include "../h/mx.h"
-#include "../h/file.h"
+#include "uba.h"
+#include "param.h"
+#include "conf.h"
+#include "dir.h"
+#include "user.h"
+#include "proc.h"
+#include "ioctl.h"
+#include "tty.h"
+#include "map.h"
+#include "buf.h"
+#include "vm.h"
+#include "kernel.h"
+#include "syslog.h"
+
+#include "ubareg.h"
+#include "ubavar.h"
+#include "dhreg.h"
+#include "dmreg.h"
+
+#include "bkmac.h"
+#include "clist.h"
+#include "file.h"
+#include "uio.h"
/*
* Definition of the driver for the auto-configuration program.
* There is one definition for the dh and one for the dm.
*/
-int dhprobe(), dhattach(), dhrint(), dhxint();
-struct uba_dinfo *dhinfo[NDH];
+int dhprobe(), dhattach(), dhrint(), dhxint(), dhtimer();
+struct uba_device *dhinfo[NDH];
u_short dhstd[] = { 0 };
struct uba_driver dhdriver =
{ dhprobe, 0, dhattach, 0, dhstd, "dh", dhinfo };
int dmprobe(), dmattach(), dmintr();
-struct uba_dinfo *dminfo[NDH];
+struct uba_device *dminfo[NDH];
u_short dmstd[] = { 0 };
struct uba_driver dmdriver =
{ dmprobe, 0, dmattach, 0, dmstd, "dm", dminfo };
-struct dhdevice
-{
- union {
- short dhcsr; /* control-status register */
- char dhcsrl; /* low byte for line select */
- } un;
- short dhrcr; /* receive character register */
- short dhlpr; /* line parameter register */
- u_short dhcar; /* current address register */
- short dhbcr; /* byte count register */
- u_short dhbar; /* buffer active register */
- short dhbreak; /* break control register */
- short dhsilo; /* silo status register */
-};
-
-/* Bits in dhcsr */
-#define DH_TI 0100000 /* transmit interrupt */
-#define DH_SI 0040000 /* storage interrupt */
-#define DH_TIE 0020000 /* transmit interrupt enable */
-#define DH_SIE 0010000 /* storage interrupt enable */
-#define DH_MC 0004000 /* master clear */
-#define DH_NXM 0002000 /* non-existant memory */
-#define DH_MM 0001000 /* maintenance mode */
-#define DH_CNI 0000400 /* clear non-existant memory interrupt */
-#define DH_RI 0000200 /* receiver interrupt */
-#define DH_RIE 0000100 /* receiver interrupt enable */
-
-/* Bits in dhlpr */
-#define BITS6 01
-#define BITS7 02
-#define BITS8 03
-#define TWOSB 04
-#define PENABLE 020
-/* DEC manuals incorrectly say this bit causes generation of even parity. */
-#define OPAR 040
-#define HDUPLX 040000
-
-#define DH_IE (DH_TIE|DH_SIE|DH_RIE)
-
-/* Bits in dhrcr */
-#define DH_PE 0010000 /* parity error */
-#define DH_FE 0020000 /* framing error */
-#define DH_DO 0040000 /* data overrun */
-
-struct dmdevice
-{
- short dmcsr; /* control status register */
- short dmlstat; /* line status register */
- short dmpad1[2];
-};
-
-/* bits in dm csr */
-#define DM_RF 0100000 /* ring flag */
-#define DM_CF 0040000 /* carrier flag */
-#define DM_CTS 0020000 /* clear to send */
-#define DM_SRF 0010000 /* secondary receive flag */
-#define DM_CS 0004000 /* clear scan */
-#define DM_CM 0002000 /* clear multiplexor */
-#define DM_MM 0001000 /* maintenance mode */
-#define DM_STP 0000400 /* step */
-#define DM_DONE 0000200 /* scanner is done */
-#define DM_IE 0000100 /* interrupt enable */
-#define DM_SE 0000040 /* scan enable */
-#define DM_BUSY 0000020 /* scan busy */
-
-/* bits in dm lsr */
-#define DML_RNG 0000200 /* ring */
-#define DML_CAR 0000100 /* carrier detect */
-#define DML_CTS 0000040 /* clear to send */
-#define DML_SR 0000020 /* secondary receive */
-#define DML_ST 0000010 /* secondary transmit */
-#define DML_RTS 0000004 /* request to send */
-#define DML_DTR 0000002 /* data terminal ready */
-#define DML_LE 0000001 /* line enable */
-
-#define DML_ON (DML_DTR|DML_LE)
-#define DML_OFF (DML_LE)
+#ifndef PORTSELECTOR
+#define ISPEED B9600
+#define IFLAGS (EVENP|ODDP|ECHO)
+#else
+#define ISPEED B4800
+#define IFLAGS (EVENP|ODDP)
+#endif
+
+#define FASTTIMER (hz/30) /* scan rate with silos on */
/*
* Local variables for the driver
struct tty dh11[NDH*16];
int ndh11 = NDH*16;
int dhact; /* mask of active dh's */
+int dhsilos; /* mask of dh's with silo in use */
+int dhchars[NDH]; /* recent input count */
+int dhrate[NDH]; /* smoothed input count */
+int dhhighrate = 100; /* silo on if dhchars > dhhighrate */
+int dhlowrate = 75; /* silo off if dhrate < dhlowrate */
+static short timerstarted;
int dhstart(), ttrstrt();
/*
- * The clist space is mapped by the driver onto each UNIBUS.
+ * The clist space is mapped by one terminal driver onto each UNIBUS.
+ * The identity of the board which allocated resources is recorded,
+ * so the process may be repeated after UNIBUS resets.
* The UBACVT macro converts a clist space address for unibus uban
* into an i/o space address for the DMA routine.
*/
-int dh_ubinfo[MAXNUBA]; /* info about allocated unibus map */
-int cbase[MAXNUBA]; /* base address in unibus map */
+int dh_uballoc[NUBA]; /* which dh (if any) allocated unibus map */
+int cbase[NUBA]; /* base address of clists in unibus map */
#define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
/*
#ifdef lint
br = 0; cvec = br; br = cvec;
+ if (ndh11 == 0) ndh11 = 1;
+ dhrint(0); dhxint(0);
#endif
#ifndef notdef
dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI;
- DELAY(5);
+ DELAY(1000);
+ dhaddr->un.dhcsr &= ~DH_RI;
dhaddr->un.dhcsr = 0;
#else
dhaddr->un.dhcsr = DH_TIE;
if (cvec && cvec != 0x200)
cvec -= 4; /* transmit -> receive */
#endif
- return (1);
+ return (sizeof (struct dhdevice));
}
/*
* Routine called to attach a dh.
*/
dhattach(ui)
- struct uba_dinfo *ui;
+ struct uba_device *ui;
{
dhsoftCAR[ui->ui_unit] = ui->ui_flags;
+ cbase[ui->ui_ubanum] = -1;
+ dh_uballoc[ui->ui_unit] = -1;
}
/*
register struct dmdevice *dmaddr = (struct dmdevice *)reg;
#ifdef lint
- br = 0; cvec = br; br = cvec;
+ br = 0; vec = br; br = vec;
+ dmintr(0);
#endif
dmaddr->dmcsr = DM_DONE|DM_IE;
DELAY(20);
/*ARGSUSED*/
dmattach(ui)
- struct uba_dinfo *ui;
+ struct uba_device *ui;
{
/* no local state to set up */
register struct tty *tp;
register int unit, dh;
register struct dhdevice *addr;
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
int s;
unit = minor(dev);
dh = unit >> 4;
- if (unit >= NDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0) {
- u.u_error = ENXIO;
- return;
- }
+ if (unit >= NDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0)
+ return (ENXIO);
tp = &dh11[unit];
- if (tp->t_state&XCLUDE && u.u_uid!=0) {
- u.u_error = EBUSY;
- return;
- }
+ if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
+ return (EBUSY);
addr = (struct dhdevice *)ui->ui_addr;
tp->t_addr = (caddr_t)addr;
tp->t_oproc = dhstart;
- tp->t_iproc = NULL;
- tp->t_state |= WOPEN;
+ tp->t_state |= TS_WOPEN;
/*
* While setting up state for this uba and this dh,
* block uba resets which can clear the state.
*/
s = spl5();
- if (dh_ubinfo[ui->ui_ubanum] == 0) {
- /* 512+ is a kludge to try to get around a hardware problem */
- dh_ubinfo[ui->ui_ubanum] =
- uballoc(ui->ui_ubanum, (caddr_t)cfree,
- 512+nclist*sizeof(struct cblock), 0);
- cbase[ui->ui_ubanum] = dh_ubinfo[ui->ui_ubanum]&0x3ffff;
+ if (cbase[ui->ui_ubanum] == -1) {
+ dh_uballoc[ui->ui_ubanum] = dh;
+ cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
+ (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
+ }
+ if (timerstarted == 0) {
+ timerstarted++;
+ timeout(dhtimer, (caddr_t) 0, hz);
}
if ((dhact&(1<<dh)) == 0) {
addr->un.dhcsr |= DH_IE;
dhact |= (1<<dh);
- addr->dhsilo = 16;
+ addr->dhsilo = 0;
}
splx(s);
/*
- * If this is first open, initialze tty state to default.
+ * If this is first open, initialize tty state to default.
*/
- if ((tp->t_state&ISOPEN) == 0) {
+ if ((tp->t_state&TS_ISOPEN) == 0) {
ttychars(tp);
+#ifndef PORTSELECTOR
if (tp->t_ispeed == 0) {
- tp->t_ispeed = B300;
- tp->t_ospeed = B300;
- tp->t_flags = ODDP|EVENP|ECHO;
+#else
+ tp->t_state |= TS_HUPCLS;
+#endif PORTSELECTOR
+ tp->t_ispeed = ISPEED;
+ tp->t_ospeed = ISPEED;
+ tp->t_flags = IFLAGS;
+#ifndef PORTSELECTOR
}
+#endif PORTSELECTOR
dhparam(unit);
}
/*
* Wait for carrier, then process line discipline specific open.
*/
dmopen(dev);
- (*linesw[tp->t_line].l_open)(dev, tp);
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
}
/*
tp = &dh11[unit];
(*linesw[tp->t_line].l_close)(tp);
((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
- if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0)
+ if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
dmctl(unit, DML_OFF, DMSET);
ttyclose(tp);
}
-dhread(dev)
+dhread(dev, uio)
dev_t dev;
+ struct uio *uio;
{
- register struct tty *tp;
+ register struct tty *tp = &dh11[minor(dev)];
- tp = &dh11[minor(dev)];
- (*linesw[tp->t_line].l_read)(tp);
+ return ((*linesw[tp->t_line].l_read)(tp, uio));
}
-dhwrite(dev)
+dhwrite(dev, uio)
dev_t dev;
+ struct uio *uio;
{
- register struct tty *tp;
+ register struct tty *tp = &dh11[minor(dev)];
- tp = &dh11[minor(dev)];
- (*linesw[tp->t_line].l_write)(tp);
+ return ((*linesw[tp->t_line].l_write)(tp, uio));
}
/*
register c;
register struct dhdevice *addr;
register struct tty *tp0;
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
int overrun = 0;
ui = dhinfo[dh];
*/
while ((c = addr->dhrcr) < 0) {
tp = tp0 + ((c>>8)&0xf);
- if ((tp->t_state&ISOPEN)==0) {
- wakeup((caddr_t)tp);
- continue;
+ dhchars[dh]++;
+ if ((tp->t_state&TS_ISOPEN)==0) {
+ wakeup((caddr_t)&tp->t_rawq);
+#ifdef PORTSELECTOR
+ if ((tp->t_state&TS_WOPEN) == 0)
+#endif
+ continue;
}
if (c & DH_PE)
if ((tp->t_flags&(EVENP|ODDP))==EVENP
|| (tp->t_flags&(EVENP|ODDP))==ODDP )
continue;
if ((c & DH_DO) && overrun == 0) {
- printf("dh%d: silo overflow\n", dh);
+ log(LOG_WARNING, "dh%d: silo overflow\n", dh);
overrun = 1;
}
if (c & DH_FE)
if (tp->t_flags&RAW)
c = 0;
else
- c = tun.t_intrc;
+ c = tp->t_intrc;
#if NBK > 0
if (tp->t_line == NETLDISC) {
c &= 0177;
* Ioctl for DH11.
*/
/*ARGSUSED*/
-dhioctl(dev, cmd, addr, flag)
- caddr_t addr;
+dhioctl(dev, cmd, data, flag)
+ caddr_t data;
{
register struct tty *tp;
- register unit = minor(dev);
+ register int unit = minor(dev);
+ int error;
tp = &dh11[unit];
- cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
- if (cmd == 0)
- return;
- if (ttioctl(tp, cmd, addr, flag)) {
- if (cmd==TIOCSETP || cmd==TIOCSETN)
+ 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) {
+ if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
+ cmd == TIOCLBIC || cmd == TIOCLSET)
dhparam(unit);
- } else switch(cmd) {
+ return (error);
+ }
+ switch (cmd) {
+
case TIOCSBRK:
((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017);
break;
+
case TIOCCBRK:
((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
break;
+
case TIOCSDTR:
dmctl(unit, DML_DTR|DML_RTS, DMBIS);
break;
+
case TIOCCDTR:
dmctl(unit, DML_DTR|DML_RTS, DMBIC);
break;
+
default:
- u.u_error = ENOTTY;
+ return (ENOTTY);
}
+ return (0);
}
/*
s = spl5();
addr->un.dhcsrl = (unit&0xf) | DH_IE;
if ((tp->t_ispeed)==0) {
- tp->t_state |= HUPCLS;
+ tp->t_state |= TS_HUPCLS;
dmctl(unit, DML_OFF, DMSET);
+ splx(s);
return;
}
lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
if ((tp->t_ispeed) == B134)
lpar |= BITS6|PENABLE|HDUPLX;
- else if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT))
+ else if (tp->t_flags & (RAW|LITOUT|PASS8))
lpar |= BITS8;
else
lpar |= BITS7|PENABLE;
register struct tty *tp;
register struct dhdevice *addr;
short ttybit, bar, *sbar;
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
register int unit;
u_short cntr;
*sbar &= ~ttybit;
bar &= ~ttybit;
tp = &dh11[unit];
- tp->t_state &= ~BUSY;
- if (tp->t_state&FLUSH)
- tp->t_state &= ~FLUSH;
+ tp->t_state &= ~TS_BUSY;
+ if (tp->t_state&TS_FLUSH)
+ tp->t_state &= ~TS_FLUSH;
else {
addr->un.dhcsrl = (unit&017)|DH_IE;
/*
*/
cntr = addr->dhcar -
UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
- ndflush(&tp->t_outq, cntr);
+ ndflush(&tp->t_outq, (int)cntr);
}
if (tp->t_line)
(*linesw[tp->t_line].l_start)(tp);
/*
* If it's currently active, or delaying, no need to do anything.
*/
- if (tp->t_state&(TIMEOUT|BUSY|TTSTOP))
+ if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
goto out;
/*
* If there are sleepers, and output has drained below low
* water mark, wake up the sleepers.
*/
- if ((tp->t_state&ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) {
- tp->t_state &= ~ASLEEP;
- if (tp->t_chan)
- mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
- else
+ if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
+ if (tp->t_state&TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
wakeup((caddr_t)&tp->t_outq);
+ }
+ if (tp->t_wsel) {
+ selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
+ tp->t_wsel = 0;
+ tp->t_state &= ~TS_WCOLL;
+ }
}
/*
* Now restart transmission unless the output queue is
*/
if (tp->t_outq.c_cc == 0)
goto out;
- if (tp->t_flags & RAW)
+ if (tp->t_flags & (RAW|LITOUT))
nch = ndqb(&tp->t_outq, 0);
else {
nch = ndqb(&tp->t_outq, 0200);
if (nch == 0) {
nch = getc(&tp->t_outq);
timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
- tp->t_state |= TIMEOUT;
+ tp->t_state |= TS_TIMEOUT;
goto out;
}
}
if (nch) {
car = UBACVT(tp->t_outq.c_cf, dhinfo[dh]->ui_ubanum);
addr->un.dhcsrl = unit|((car>>12)&0x30)|DH_IE;
- unit = 1 << unit;
- dhsar[dh] |= unit;
+ /*
+ * The following nonsense with short word
+ * is to make sure the dhbar |= word below
+ * is done with an interlocking bisw2 instruction.
+ */
+ { short word = 1 << unit;
+ dhsar[dh] |= word;
addr->dhcar = car;
addr->dhbcr = -nch;
- addr->dhbar |= unit;
- tp->t_state |= BUSY;
+ addr->dhbar |= word;
+ }
+ tp->t_state |= TS_BUSY;
}
out:
splx(s);
* Block input/output interrupts while messing with state.
*/
s = spl5();
- if (tp->t_state & BUSY) {
+ if (tp->t_state & TS_BUSY) {
/*
* Device is transmitting; stop output
* by selecting the line and setting the byte
*/
unit = minor(tp->t_dev);
addr->un.dhcsrl = (unit&017) | DH_IE;
- if ((tp->t_state&TTSTOP)==0)
- tp->t_state |= FLUSH;
+ if ((tp->t_state&TS_TTSTOP)==0)
+ tp->t_state |= TS_FLUSH;
addr->dhbcr = -1;
}
splx(s);
{
register int dh, unit;
register struct tty *tp;
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
int i;
- if (dh_ubinfo[uban] == 0)
- return;
- ubarelse(uban, &dh_ubinfo[uban]);
- dh_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
- 512+nclist*sizeof (struct cblock), 0);
- cbase[uban] = dh_ubinfo[uban]&0x3ffff;
dh = 0;
for (dh = 0; dh < NDH; dh++) {
ui = dhinfo[dh];
if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
continue;
printf(" dh%d", dh);
+ if (dh_uballoc[uban] == dh) {
+ int info;
+
+ info = uballoc(uban, (caddr_t)cfree,
+ nclist * sizeof(struct cblock), UBA_CANTWAIT);
+ if (info)
+ cbase[uban] = UBAI_ADDR(info);
+ else {
+ printf(" [can't get uba map]");
+ cbase[uban] = -1;
+ }
+ }
((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE;
- ((struct dhdevice *)ui->ui_addr)->dhsilo = 16;
+ ((struct dhdevice *)ui->ui_addr)->dhsilo = 0;
unit = dh * 16;
for (i = 0; i < 16; i++) {
tp = &dh11[unit];
- if (tp->t_state & (ISOPEN|WOPEN)) {
+ if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
dhparam(unit);
dmctl(unit, DML_ON, DMSET);
- tp->t_state &= ~BUSY;
+ tp->t_state &= ~TS_BUSY;
dhstart(tp);
}
unit++;
}
}
- dhtimer();
+ dhsilos = 0;
}
+int dhtransitions, dhslowtimers, dhfasttimers; /*DEBUG*/
/*
- * At software clock interrupt time or after a UNIBUS reset
- * empty all the dh silos.
+ * At software clock interrupt time, check status.
+ * Empty all the dh silos that are in use, and decide whether
+ * to turn any silos off or on.
*/
dhtimer()
{
- register int dh;
-
- for (dh = 0; dh < NDH; dh++)
- dhrint(dh);
+ register int dh, s;
+ static int timercalls;
+
+ if (dhsilos) {
+ dhfasttimers++; /*DEBUG*/
+ timercalls++;
+ s = spl5();
+ for (dh = 0; dh < NDH; dh++)
+ if (dhsilos & (1 << dh))
+ dhrint(dh);
+ splx(s);
+ }
+ if ((dhsilos == 0) || ((timercalls += FASTTIMER) >= hz)) {
+ dhslowtimers++; /*DEBUG*/
+ timercalls = 0;
+ for (dh = 0; dh < NDH; dh++) {
+ ave(dhrate[dh], dhchars[dh], 8);
+ if ((dhchars[dh] > dhhighrate) &&
+ ((dhsilos & (1 << dh)) == 0)) {
+ ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo =
+ (dhchars[dh] > 500? 32 : 16);
+ dhsilos |= (1 << dh);
+ dhtransitions++; /*DEBUG*/
+ } else if ((dhsilos & (1 << dh)) &&
+ (dhrate[dh] < dhlowrate)) {
+ ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo = 0;
+ dhsilos &= ~(1 << dh);
+ }
+ dhchars[dh] = 0;
+ }
+ }
+ timeout(dhtimer, (caddr_t) 0, dhsilos? FASTTIMER: hz);
}
/*
{
register struct tty *tp;
register struct dmdevice *addr;
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
register int unit;
register int dm;
+ int s;
unit = minor(dev);
dm = unit >> 4;
tp = &dh11[unit];
unit &= 0xf;
- if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0 ||
- (dhsoftCAR[dm]&(1<<unit))) {
- tp->t_state |= CARR_ON;
+ if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0) {
+ tp->t_state |= TS_CARR_ON;
return;
}
addr = (struct dmdevice *)ui->ui_addr;
- spl5();
- addr->dmcsr &= ~DM_SE;
- while (addr->dmcsr & DM_BUSY)
- ;
- addr->dmcsr = unit;
- addr->dmlstat = DML_ON;
- if (addr->dmlstat&DML_CAR)
- tp->t_state |= CARR_ON;
- addr->dmcsr = DH_IE|DM_SE;
- while ((tp->t_state&CARR_ON)==0)
+ s = spl5();
+ for (;;) {
+ addr->dmcsr &= ~DM_SE;
+ while (addr->dmcsr & DM_BUSY)
+ ;
+ addr->dmcsr = unit;
+ addr->dmlstat = DML_ON;
+ if ((addr->dmlstat & DML_CAR) || (dhsoftCAR[dm] & (1 << unit)))
+ tp->t_state |= TS_CARR_ON;
+ addr->dmcsr = DM_IE|DM_SE;
+ if (tp->t_state & TS_CARR_ON)
+ break;
sleep((caddr_t)&tp->t_rawq, TTIPRI);
- spl0();
+ }
+ splx(s);
}
/*
dev_t dev;
int bits, how;
{
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
register struct dmdevice *addr;
register int unit, s;
int dm;
addr->dmlstat &= ~bits;
break;
}
- addr->dmcsr = DH_IE|DM_SE;
+ addr->dmcsr = DM_IE|DM_SE;
splx(s);
}
dmintr(dm)
register int dm;
{
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
register struct tty *tp;
register struct dmdevice *addr;
+ int unit;
ui = dminfo[dm];
if (ui == 0)
return;
addr = (struct dmdevice *)ui->ui_addr;
- if (addr->dmcsr&DM_DONE && addr->dmcsr&DM_CF) {
- tp = &dh11[(dm<<4)+(addr->dmcsr&0xf)];
- wakeup((caddr_t)&tp->t_rawq);
- if ((tp->t_state&WOPEN)==0 &&
- (tp->t_local&LMDMBUF)) {
- if (addr->dmlstat & DML_CAR) {
- tp->t_state &= ~TTSTOP;
- ttstart(tp);
- } else if ((tp->t_state&TTSTOP) == 0) {
- tp->t_state |= TTSTOP;
- dhstop(tp, 0);
- }
- } else if ((addr->dmlstat&DML_CAR)==0) {
- if ((tp->t_state&WOPEN)==0 &&
- (tp->t_local&LNOHANG)==0) {
- gsignal(tp->t_pgrp, SIGHUP);
- gsignal(tp->t_pgrp, SIGCONT);
+ if (addr->dmcsr&DM_DONE) {
+ if (addr->dmcsr&DM_CF) {
+ unit = addr->dmcsr & 0xf;
+ tp = &dh11[(dm << 4) + unit];
+ if (addr->dmlstat & DML_CAR)
+ (void)(*linesw[tp->t_line].l_modem)(tp, 1);
+ else if ((dhsoftCAR[dm] & (1<<unit)) == 0 &&
+ (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
addr->dmlstat = 0;
- flushtty(tp, FREAD|FWRITE);
- }
- tp->t_state &= ~CARR_ON;
- } else
- tp->t_state |= CARR_ON;
- addr->dmcsr = DH_IE|DM_SE;
+ }
+ addr->dmcsr = DM_IE|DM_SE;
}
}
#endif