+ * 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, 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);
+}
+
+/*
+ * Turn on the line associated with dh dev.
+ */
+dmopen(dev)
+ dev_t dev;
+{
+ register struct tty *tp;
+ register struct dmdevice *addr;
+ 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) {
+ tp->t_state |= TS_CARR_ON;
+ return;
+ }
+ addr = (struct dmdevice *)ui->ui_addr;
+ 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);
+ }
+ splx(s);
+}
+
+/*
+ * Dump control bits into the DM registers.
+ */
+dmctl(dev, bits, how)
+ dev_t dev;
+ int bits, how;
+{
+ register struct uba_device *ui;
+ register struct dmdevice *addr;
+ register int unit, s;
+ int dm;
+
+ unit = minor(dev);
+ dm = unit >> 4;
+ if ((ui = dminfo[dm]) == 0 || ui->ui_alive == 0)
+ return;
+ addr = (struct dmdevice *)ui->ui_addr;
+ s = spl5();
+ addr->dmcsr &= ~DM_SE;
+ while (addr->dmcsr & DM_BUSY)
+ ;
+ addr->dmcsr = unit & 0xf;
+ switch(how) {
+ case DMSET:
+ addr->dmlstat = bits;
+ break;
+ case DMBIS:
+ addr->dmlstat |= bits;
+ break;
+ case DMBIC:
+ addr->dmlstat &= ~bits;
+ break;
+ }
+ addr->dmcsr = DM_IE|DM_SE;
+ splx(s);
+}
+
+/*
+ * DM11 interrupt; deal with carrier transitions.