rewritten, includes fixes from mike obrien, not tested
[unix-history] / usr / src / sys / vax / uba / uu.c
index ebe2bf5..61139ad 100644 (file)
@@ -1,9 +1,10 @@
-/*     uu.c    4.2     83/04/10        */
+/*     uu.c    4.3     83/05/08        */
 
 
-#include "uu->h"
+#include "uu.h"
 #if NDL > 0
 /*
  * TU58 DECtape II/DL11 device driver
 #if NDL > 0
 /*
  * TU58 DECtape II/DL11 device driver
+ * (based on a driver written by Mike Obrien @ RAND)
  *
  * The TU58 * is treated as a block device (only).  Error detection and
  * recovery is almost non-existant.  It is assumed that the
  *
  * The TU58 * is treated as a block device (only).  Error detection and
  * recovery is almost non-existant.  It is assumed that the
  * errors are checked for.  
  */
 
  * errors are checked for.  
  */
 
-/* 
- * TODO:
- * -   Split the uu structure into a per controller 
- *     part and a per drive part.
- */
+#include "../machine/pte.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/buf.h"
 #include "../h/conf.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/buf.h"
 #include "../h/conf.h"
-#include "../h/dir.h"
+#include "../h/time.h"
 #include "../h/kernel.h"
 #include "../h/errno.h"
 #include "../h/uio.h"
 #include "../h/kernel.h"
 #include "../h/errno.h"
 #include "../h/uio.h"
-#include "../h/user.h"
 #include "../h/file.h"
 
 #include "../vax/cpu.h"
 #include "../h/file.h"
 
 #include "../vax/cpu.h"
-#include "../vax/mtpr.h"
+#include "../vax/nexus.h"
+
 #include "../vaxuba/ubavar.h"
 #include "../vaxuba/ubareg.h"
 #include "../vaxuba/uureg.h"
 
 #include "../vaxuba/ubavar.h"
 #include "../vaxuba/ubareg.h"
 #include "../vaxuba/uureg.h"
 
-#define        printd  if(uudebug) printf
+#define        printd  if (uudebug) printf
 #ifdef printd
 #ifdef printd
-int    uudebug;        /* printd */
+int    uudebug;                /* printd */
 #endif printd
 
 #endif printd
 
-#if    !defined(MRSP) || lint
-#define        MRSP    (cpu != VAX_750)
-#endif
 #define        NTUBLK  512             /* number of blocks on a TU58 cassette */
 #define        WRV     02              /* bit in minor dev => write w. read verify */
 #define        NTUBLK  512             /* number of blocks on a TU58 cassette */
 #define        WRV     02              /* bit in minor dev => write w. read verify */
-#define        NDPC    02              /* # drives per controller */
+#define        NDPC    02              /* drives per controller */
+#define        NUU     NDPC * NDL      /* number of drives */
+#define        DNUM    01              /* mask for drive number */
+#define        NTUQ    02              /* # of block which can be queued up */
 
 /*
  * Structure of a command packet
 
 /*
  * Structure of a command packet
@@ -105,6 +102,8 @@ char *uustates[UUS_NSTATES] = {
        "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
        "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT"
 };
        "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
        "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT"
 };
+
+#define        UNIT(dev)       (minor(dev)&DNUM)
 #define        printstate(state) \
        if ((state) < UUS_NSTATES) \
                printf("%s", uustates[(state)]); \
 #define        printstate(state) \
        if ((state) < UUS_NSTATES) \
                printf("%s", uustates[(state)]); \
@@ -139,7 +138,6 @@ char *uustates[UUS_NSTATES] = {
 /*
  * Switches
  */
 /*
  * Switches
  */
-#define        TUSW_MRSP       010             /* use Modified RSP */
 
 u_char uunull[2] = { 0, 0 };   /* nulls to send for initialization */
 u_char uuinit[2] = { TUF_INITF, TUF_INITF };   /* inits to send */
 
 u_char uunull[2] = { 0, 0 };   /* nulls to send for initialization */
 u_char uuinit[2] = { TUF_INITF, TUF_INITF };   /* inits to send */
@@ -147,12 +145,13 @@ u_char    uuinit[2] = { TUF_INITF, TUF_INITF };   /* inits to send */
 struct uba_device      *uudinfo[NUU];
 struct uba_ctlr        *uuminfo[NDL];
 
 struct uba_device      *uudinfo[NUU];
 struct uba_ctlr        *uuminfo[NDL];
 
-int uuprobe(), uuslave(), uuattach(), uurintr(), uuxintr(), uuwatch();
+int uuprobe(), uuslave(), uuattach(), uudgo(), uurintr(), uuxintr(), uuwatch();
 u_short uustd[] = { 0176500, 0 };
 struct uba_driver dldriver =
 u_short uustd[] = { 0176500, 0 };
 struct uba_driver dldriver =
-    { uuprobe, uuslave, uuattach, uudgo, uustd, "uu", uudinfo, "dl", uuminfo };
+    { uuprobe, uuslave, uuattach, uudgo, uustd, "uu", uudinfo, "uu", uuminfo };
 
 int    uuwstart;
 
 int    uuwstart;
+static char pcnt[2];                   /* pee/vee counters */
 
 /*ARGSUSED*/
 uuprobe(reg)
 
 /*ARGSUSED*/
 uuprobe(reg)
@@ -174,7 +173,7 @@ uuprobe(reg)
        return(sizeof (*uuaddr));
 }
 
        return(sizeof (*uuaddr));
 }
 
-uuslave(ui, reg);
+uuslave(ui, reg)
        struct uba_device *ui;
        caddr_t reg;
 {
        struct uba_device *ui;
        caddr_t reg;
 {
@@ -185,7 +184,7 @@ uuslave(ui, reg);
 uuattach(ui)
        struct uba_device *ui;
 {
 uuattach(ui)
        struct uba_device *ui;
 {
-
+       /* no local state to set up */
 }
 
 /*ARGSUSED1*/
 }
 
 /*ARGSUSED1*/
@@ -197,26 +196,26 @@ uuopen(dev, flag)
        register struct uu_ctlr *uuc;
        register struct uudevice *uuaddr;
        register struct uba_ctlr *um;
        register struct uu_ctlr *uuc;
        register struct uudevice *uuaddr;
        register struct uba_ctlr *um;
-       int ctlr, unit = minor(dev), s;
+       int ctlr, unit = UNIT(dev), s;
 
        if (unit >= NUU || (ui = uudinfo[unit]) == 0 || ui->ui_alive == 0)
                return (ENXIO);
        um = ui->ui_mi;
        ctlr = um->um_ctlr;
        uuc = &uu_ctlr[ctlr];
 
        if (unit >= NUU || (ui = uudinfo[unit]) == 0 || ui->ui_alive == 0)
                return (ENXIO);
        um = ui->ui_mi;
        ctlr = um->um_ctlr;
        uuc = &uu_ctlr[ctlr];
-       if (uuc->uu_dopen[unit%NDPC])
+       if (uuc->uu_dopen[unit&DNUM])
                return (EBUSY);
        if (uuwstart++ == 0)
                timeout(uuwatch, (caddr_t)0, hz);
 
                return (EBUSY);
        if (uuwstart++ == 0)
                timeout(uuwatch, (caddr_t)0, hz);
 
-       uuc->uu_dopen[unit%NDPC]++;
-       uuaddr = (struct uudevice *)ui->ui_mi->um_addr;
+       uuc->uu_dopen[unit&DNUM]++;
+       uuaddr = (struct uudevice *)um->um_addr;
        s = spl5();
        /*
         * If the unit already initialized,
         * just enable interrupts and return.
         */
        s = spl5();
        /*
         * If the unit already initialized,
         * just enable interrupts and return.
         */
-       if (uu->uu_state == TUS_IDLE) {
+       if (uuc->uu_state == UUS_IDLE) {
                uuaddr->rcs = UUCS_INTR;
                splx(s);
                return (0);
                uuaddr->rcs = UUCS_INTR;
                splx(s);
                return (0);
@@ -229,10 +228,10 @@ uuopen(dev, flag)
        uureset(ctlr);
        sleep((caddr_t)uuc, PZERO+1);
        um->um_tab.b_active = NULL;
        uureset(ctlr);
        sleep((caddr_t)uuc, PZERO+1);
        um->um_tab.b_active = NULL;
-       if (uu->uu_state != TUS_IDLE) {
-               uu->uu_state = TUS_INIT1;
-               uu->uu_dopen[unit%NDPC] = 0;
-               uu->uu_rcnt = uu->uu_wcnt = 0;
+       if (uuc->uu_state != UUS_IDLE) {
+               uuc->uu_state = UUS_INIT1;
+               uuc->uu_dopen[unit&DNUM] = 0;
+               uuc->uu_rcnt = uuc->uu_wcnt = 0;
                uuaddr->rcs = 0;
                uuaddr->tcs = 0;
                splx(s);
                uuaddr->rcs = 0;
                uuaddr->tcs = 0;
                splx(s);
@@ -246,15 +245,10 @@ uuclose(dev, flag)
        dev_t dev;
        int flag;
 {
        dev_t dev;
        int flag;
 {
-       register struct uba_ctlr *um = uudinfo[minor(dev)]->ui_mi;
-       register struct uudevice *uuaddr;
+       register struct uba_ctlr *um = uudinfo[UNIT(dev)]->ui_mi;
        register struct uu_ctlr *uuc;
 
        register struct uu_ctlr *uuc;
 
-       if (um->um_tab.b_active == 0) {
-               uuaddr = (struct uudevice *)um->um_addr;
-               uuaddr->rcs = 0;
-               uuwstart--;
-       }
+       uuwstart--;
        uuc = &uu_ctlr[um->um_ctlr];
        if (uuc->uu_serrs + uuc->uu_cerrs + uuc->uu_herrs != 0) {
                /*
        uuc = &uu_ctlr[um->um_ctlr];
        if (uuc->uu_serrs + uuc->uu_cerrs + uuc->uu_herrs != 0) {
                /*
@@ -263,45 +257,47 @@ uuclose(dev, flag)
                 */
                uprintf(
                   "uu%d: %d soft errors, %d chksum errors, %d hard errors\n",
                 */
                uprintf(
                   "uu%d: %d soft errors, %d chksum errors, %d hard errors\n",
-                   minor(dev), uuc->uu_serrs, uuc->uu_cerrs, uuc->uu_herrs);
+                   UNIT(dev), uuc->uu_serrs, uuc->uu_cerrs, uuc->uu_herrs);
                    uuc->uu_serrs = uuc->uu_cerrs = uuc->uu_herrs = 0;
        }
                    uuc->uu_serrs = uuc->uu_cerrs = uuc->uu_herrs = 0;
        }
-       uuc->uu_dopen[minor(dev)%NDPC] = 0;
+       uuc->uu_dopen[UNIT(dev)] = 0;
 }
 
 uureset(ctlr)
        int ctlr;
 {
 }
 
 uureset(ctlr)
        int ctlr;
 {
-       register struct uu_ctlr *uuc = uu_ctlr[ctlr];
-       register struct packet *cmd = uucmd[ctlr];
-       register struct uudevice *uuaddr;
+       register struct uu_ctlr *uuc = &uu_ctlr[ctlr];
+       register struct packet *cmd = &uucmd[ctlr];
        struct uba_ctlr *um = uuminfo[ctlr];
        struct uba_ctlr *um = uuminfo[ctlr];
+       register struct uudevice *uuaddr = (struct uudevice *)um->um_addr;
 
        um->um_tab.b_active++;
 
        um->um_tab.b_active++;
-       uuc->uu_state = TUS_INIT1;
+       uuc->uu_state = UUS_INIT1;
        uuc->uu_wbptr = uunull;
        uuc->uu_wcnt = sizeof (uunull);
        cmd->pk_flag = TUF_CMD;
        uuc->uu_wbptr = uunull;
        uuc->uu_wcnt = sizeof (uunull);
        cmd->pk_flag = TUF_CMD;
-       cmd->pk_mcount = sizeof (uucmd) - 4;
+       cmd->pk_mcount = sizeof (*cmd) - 4;
        cmd->pk_mod = 0;
        cmd->pk_seq = 0;
        cmd->pk_mod = 0;
        cmd->pk_seq = 0;
-       cmd->pk_sw = MRSP ? TUSW_MRSP : 0;
-       uuaddr = (struct uudevice *)um->um_addr;
+       cmd->pk_sw = 0;
        uuaddr->rcs = 0;
        uuaddr->tcs = UUCS_INTR | UUCS_BREAK;
        uuxintr(ctlr);                          /* start output */
 }
 
        uuaddr->rcs = 0;
        uuaddr->tcs = UUCS_INTR | UUCS_BREAK;
        uuxintr(ctlr);                          /* start output */
 }
 
+uudgo()
+{
+}
+
 /*
  * Strategy routine for block I/O
  */
 uustrategy(bp)
        register struct buf *bp;
 {
 /*
  * Strategy routine for block I/O
  */
 uustrategy(bp)
        register struct buf *bp;
 {
-       register struct buf *dp;
+       register struct buf *uutab;
        struct uba_device *ui;
        struct uba_device *ui;
-       struct uu_ctlr *uuc;
-       int s, unit = minor(bp->b_dev);
+       int s, unit = UNIT(bp->b_dev);
 
        if (unit > NUU)
                goto bad;
 
        if (unit > NUU)
                goto bad;
@@ -310,126 +306,123 @@ uustrategy(bp)
        ui = uudinfo[unit];
        if (ui == 0 || ui->ui_alive == 0)
                goto bad;
        ui = uudinfo[unit];
        if (ui == 0 || ui->ui_alive == 0)
                goto bad;
-       uuc = &uu_ctlr[ui->ui_mi->um_ctlr];
+       uutab = &ui->ui_mi->um_tab;     /* one request queue per controller */
+       if ((bp->b_flags&B_READ) == 0)
+               uu_pee(&pcnt[UNIT(bp->b_dev)]);
        s = spl5();
        s = spl5();
-       bp->b_cylin = bp->b_blkno;
-       dp = &uuutab[unit];
-       disksort(dp, bp);
-       if (dp->b_active == 0) {
-               uuustart(ui);
-               bp = &ui->ui_mi->um_tab;
-               if (bp->b_actf && bp->b_active == 0)
-                       uustart(ui->ui_mi);
-       }
+       bp->av_forw = NULL;
+       if (uutab->b_actf == NULL)
+               uutab->b_actf = bp;
+       else
+               uutab->b_actl->av_forw = bp;
+       uutab->b_actl = bp;
+       if (uutab->b_active == 0)
+               uustart(ui->ui_mi);
        splx(s);
        return;
 
 bad:
        bp->b_flags |= B_ERROR;
        splx(s);
        return;
 
 bad:
        bp->b_flags |= B_ERROR;
+       bp->b_error = ENXIO;
        iodone(bp);
        return;
 }
 
        iodone(bp);
        return;
 }
 
-/*
- * Unit start routine.
- * Put this unit on the ready queue for the controller
- */
-uuustart(ui)
-       register struct uba_device *ui;
-{
-       struct buf *dp = &uuutab[ui->ui_unit];
-       struct uba_ctlr *um = ui->ui_mi;
-       
-       dp->b_forw = NULL;
-       if (um->um_tab.b_actf == NULL)
-               um->um_tab.b_actf = dp;
-       else
-               um->um_tab.b_actl->b_forw = dp;
-       um->um_tab.b_actl = dp;
-       dp->b_active++;
-}
 /*
  * Start the transfer
  */
 uustart(um)
        register struct uba_ctlr *um;
 {
 /*
  * Start the transfer
  */
 uustart(um)
        register struct uba_ctlr *um;
 {
-       register struct uudevice *uuaddr;
        register struct buf *bp;
        register struct uu_ctlr *uuc;
        register struct buf *bp;
        register struct uu_ctlr *uuc;
-       struct buf *dp;
        struct packet *cmd;
        struct packet *cmd;
-       int unit;
+       int ctlr;
 
 
-loop:
-       if ((dp = um->um_tab.b_actf) == NULL)
+       bp = um->um_tab.b_actf;
+       if (bp == NULL)
                return;
                return;
-       if ((bp = dp->b_actf) == NULL) {
-               um->um_tab.b_actf = dp->b_forw;
-               goto loop;
-       }
-       unit = minor(bp->b_dev);
-       uuc = &uu_ctlr[um->um_ctlr];
-       cmd = &uucmd[um->um_ctlr];
-       if (uuc->uu_state != TUS_IDLE) {
-               uureset(um->um_ctlr);
+       ctlr = um->um_ctlr;
+       uuc = &uu_ctlr[ctlr];
+       cmd = &uucmd[ctlr];
+       if (uuc->uu_state != UUS_IDLE) {
+               uureset(ctlr);
                return;
        }
        um->um_tab.b_active++;
                return;
        }
        um->um_tab.b_active++;
-       uuaddr = (struct uudevice *)um->um_addr;
        cmd->pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE;
        cmd->pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ?
            TUMD_WRV : 0;
        cmd->pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE;
        cmd->pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ?
            TUMD_WRV : 0;
-       cmd->pk_unit = (minor(bp->b_dev)&DNUM);
-       cmd->pk_sw = MRSP ? TUSW_MRSP : 0;
-       cmd->pk_count = uu->uu_count = bp->b_bcount;
+       cmd->pk_unit = UNIT(bp->b_dev);
+       cmd->pk_sw = 0;
+       cmd->pk_count = uuc->uu_count = bp->b_bcount;
        cmd->pk_block = bp->b_blkno;
        cmd->pk_chksum =
        cmd->pk_block = bp->b_blkno;
        cmd->pk_chksum =
-           uuchk(*((short *)&cmd), (u_short *)&cmd.pk_op,
-               (int)cmd.pk_mcount);
-       uuc->uu_state = bp->b_flags&B_READ ? TUS_SENDR : TUS_SENDW;
+           uuchk(*((short *)cmd), (u_short *)&cmd->pk_op,
+               (int)cmd->pk_mcount);
+       uuc->uu_state = bp->b_flags&B_READ ? UUS_SENDR : UUS_SENDW;
        uuc->uu_addr = bp->b_un.b_addr;
        uuc->uu_count = bp->b_bcount;
        uuc->uu_addr = bp->b_un.b_addr;
        uuc->uu_count = bp->b_bcount;
-       uuc->uu_wbptr = (u_char *)&uucmd;
-       uuc->uu_wcnt = sizeof (uucmd);
-       uuxintr(um->um_ctlr);
+       uuc->uu_wbptr = (u_char *)cmd;
+       uuc->uu_wcnt = sizeof (*cmd);
+       uuxintr(ctlr);
 }
 
 /*
  * TU58 receiver interrupt
  */
 }
 
 /*
  * TU58 receiver interrupt
  */
-uurintr()
+uurintr(ctlr)
+       int ctlr;
 {
 {
-       register struct buf *bp;
-       register int c;
-
-       c = mfpr(CSRD)&0xff;            /* get the char, clear the interrupt */
-       if (MRSP) {
-               while ((mfpr(CSTS)&READY) == 0)
-                       ;
-               mtpr(CSTD, TUF_CONT);   /* ACK */
+       struct uba_ctlr *um = uuminfo[ctlr];
+       register struct buf *bp = um->um_tab.b_actf;
+       register struct uu_ctlr *uuc = &uu_ctlr[ctlr];
+       register struct uudevice *uuaddr = (struct uudevice *)um->um_addr;
+       register struct buf *uutab = &um->um_tab;
+       struct packet *data, *cmd;
+       int c;
+
+       if (!uutab->b_active)
+               return;
+       cmd = &uucmd[ctlr];
+       c = uuaddr->rdb;
+       if (c & UURDB_ERROR) {
+               if (c & UURDB_ORUN) {
+                       printf("data overrun, ");
+                       goto bad;
+               } else {
+                       printf("uu%d: break received, device reset, state=", 
+                               UNIT(bp->b_dev));
+                       printstate(uuc->uu_state);
+                       uureset(ctlr);
+                       printf("\n");
+                       return;
+               }
        }
        }
-       if (uu->uu_rcnt) {              /* still waiting for data? */
-               *uu->uu_rbptr++ = c;    /* yup, put it there */
-               if (--uu->uu_rcnt)      /* decrement count, any left? */
+top:
+       c &= 0xff;
+       if (uuc->uu_rcnt) {             /* still waiting for data? */
+               *uuc->uu_rbptr++ = c;   /* yup, put it there */
+               if (--uuc->uu_rcnt)     /* decrement count, any left? */
                        return;         /* get some more */
        }
                        return;         /* get some more */
        }
+       data = &uudata[ctlr];
 
        /*
         * We got all the data we were expecting for now,
         * switch on the uu_state of the transfer.
         */
 
        /*
         * We got all the data we were expecting for now,
         * switch on the uu_state of the transfer.
         */
-       switch(uu->uu_state) {
+       switch(uuc->uu_state) {
 
        /*
         * If we get an unexpected "continue",
         * start all over again...
         */
 
        /*
         * If we get an unexpected "continue",
         * start all over again...
         */
-       case TUS_INIT2:
-               uu->uu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
-               uu->uu_flag = 0;
-               wakeup((caddr_t)&uu);
-               uustart();
+       case UUS_INIT2:
+               uuc->uu_state = c == TUF_CONT ? UUS_IDLE : UUS_INIT1;
+               uuc->uu_flag = 0;
+               wakeup((caddr_t)uuc);
+               uustart(um);
                break;
 
        /*
                break;
 
        /*
@@ -437,126 +430,144 @@ uurintr()
         * is on a "continue", so if we don't
         * get it, reset the world.
         */
         * is on a "continue", so if we don't
         * get it, reset the world.
         */
-       case TUS_WAIT:                  /* waiting for continue */
-               if (c != TUF_CONT) {
-                       uu->uu_state = TUS_INIT1;
+       case UUS_WAIT:                  /* waiting for continue */
+               switch(c) {
+               case TUF_CONT:  /* got the expected continue */
+                       uuc->uu_flag = 0;
+                       data->pk_flag = TUF_DATA;
+                       data->pk_mcount = MIN(128, uuc->uu_count);
+                       data->pk_chksum =
+                           tuchk(*((short *)data), (caddr_t)uuc->uu_addr,
+                               (int)data->pk_mcount);
+                       uuc->uu_state = UUS_SENDH;
+                       uuc->uu_wbptr = (u_char *)data;
+                       uuc->uu_wcnt = 2;
+                       tuxintr();
+                       break;
+
+               case TUF_CMD:   /* sending us an END packet...error */
+                       uuc->uu_state = UUS_GET;
+                       uuc->uu_rbptr = (u_char *) data;
+                       uuc->uu_rcnt = sizeof (*data);
+                       uuc->uu_flag = 1;
+                       uuaddr->tcs = 0;
+                       goto top;
+
+               case TUF_INITF:
+                       tureset();
+                       break;
+
+               default:        /* something random...bad news */
+                       uuc->uu_state = UUS_INIT1;
                        break;
                }
                        break;
                }
-               uu->uu_flag = 0;
-               uudata.pk_flag = TUF_DATA;
-               uudata.pk_mcount = MIN(128, uu->uu_count);
-               uudata.pk_chksum =
-                   uuchk(*((short *)&uudata), (u_short *)uu->uu_addr,
-                       (int)uudata.pk_mcount);
-               uu->uu_state = TUS_SENDH;
-               uu->uu_wbptr = (u_char *)&uudata;
-               uu->uu_wcnt = 2;
-               uuxintr();
                break;
 
                break;
 
-       case TUS_SENDW:
+       case UUS_SENDW:
                if (c != TUF_CONT)
                        goto bad;
                if (c != TUF_CONT)
                        goto bad;
-               uureset();
+               uureset(ctlr);
                break;
 
        /*
         * Got header, now get data; amount to
         * fetch is included in packet.
         */
                break;
 
        /*
         * Got header, now get data; amount to
         * fetch is included in packet.
         */
-       case TUS_GETH:
-               if (uudata.pk_flag == TUF_DATA)
-                       uu->uu_rbptr = (u_char *)uu->uu_addr;
-               uu->uu_rcnt = uudata.pk_mcount;
-               uu->uu_state = TUS_GETD;
+       case UUS_GETH:
+               if (data->pk_flag == TUF_DATA)
+                       uuc->uu_rbptr = (u_char *)uuc->uu_addr;
+               uuc->uu_rcnt = data->pk_mcount;
+               uuc->uu_state = UUS_GETD;
                break;
 
        /*
         * Got the data, now fetch the checksum.
         */
                break;
 
        /*
         * Got the data, now fetch the checksum.
         */
-       case TUS_GETD:
-               uu->uu_rbptr = (u_char *)&uudata.pk_chksum;
-               uu->uu_rcnt = sizeof (uudata.pk_chksum);
-               uu->uu_state = TUS_GETC;
+       case UUS_GETD:
+               uuc->uu_rbptr = (u_char *)&data->pk_chksum;
+               uuc->uu_rcnt = sizeof (data->pk_chksum);
+               uuc->uu_state = UUS_GETC;
                break;
 
                break;
 
-       case TUS_GET:
-       case TUS_GETC:
+       case UUS_GET:
+       case UUS_GETC:
                /* got entire packet */
 #ifdef notdef
                /* got entire packet */
 #ifdef notdef
-               if (uudata.pk_chksum !=
-                   uuchk(*((short *)&uudata), (u_short *)
-                    (uudata.pk_flag == TUF_DATA ? uu->uu_addr : &uudata.pk_op),
-                    (int)uudata.pk_mcount))
-                       uu->uu_cerrs++;
+               if (data->pk_chksum !=
+                   uuchk(*((short *)data), (u_short *)
+                    (data->pk_flag == TUF_DATA ? uuc->uu_addr : &data->pk_op),
+                    (int)data->pk_mcount))
+                       uuc->uu_cerrs++;
 #endif
 #endif
-               if (uudata.pk_flag == TUF_DATA) {
+               if (data->pk_flag == TUF_DATA) {
                        /* data packet, advance to next */
                        /* data packet, advance to next */
-                       uu->uu_addr += uudata.pk_mcount;
-                       uu->uu_count -= uudata.pk_mcount;
-                       uu->uu_state = TUS_GETH;
-                       uu->uu_rbptr = (u_char *)&uudata; /* next packet */
-                       uu->uu_rcnt = 2;
-               } else if (uudata.pk_flag==TUF_CMD && uudata.pk_op==TUOP_END) {
+                       uuc->uu_addr += data->pk_mcount;
+                       uuc->uu_count -= data->pk_mcount;
+                       uuc->uu_state = UUS_GETH;
+                       uuc->uu_rbptr = (u_char *)data; /* next packet */
+                       uuc->uu_rcnt = 2;
+               } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) {
                        /* end packet, idle and reenable transmitter */
                        /* end packet, idle and reenable transmitter */
-                       uu->uu_state = TUS_IDLE;
-                       uu->uu_flag = 0;
-                       mtpr(CSTS, IE);
+                       uuc->uu_state = UUS_IDLE;
+                       uuc->uu_flag = 0;
+                       uuaddr->rcs = UUCS_INTR;
                        printd("ON ");
                        printd("ON ");
-                       if ((bp = uutab.b_actf) == NULL) {
-                               printf("uu: no bp, active %d\n",uutab.b_active);
-                               uustart();
+                       if (bp == NULL) {
+                               printf("uu: no bp active\n");
+                               uustart(um);
                                return;
                        }
                                return;
                        }
-                       if (uudata.pk_mod > 1) {        /* hard error */
+                       if (data->pk_mod > 1) {        /* hard error */
                                bp->b_flags |= B_ERROR;
                                bp->b_flags |= B_ERROR;
-                               uu->uu_herrs++;
+                               uuc->uu_herrs++;
                                harderr(bp, "uu");
                                harderr(bp, "uu");
-                               printf("  pk_mod %o\n", uudata.pk_mod&0377);
-                       } else if (uudata.pk_mod != 0)  /* soft error */
-                               uu->uu_serrs++;
-                       uutab.b_active = NULL;
-                       uutab.b_actf = bp->av_forw;
-                       bp->b_resid = uu->uu_count;
+                               printf(" pk_mod %o\n", data->pk_mod&0xff);
+                       } else if (data->pk_mod != 0)   /* soft error */
+                               uuc->uu_serrs++;
+                       uutab->b_active = NULL;
+                       uutab->b_actf = bp->av_forw;
+                       bp->b_resid = uuc->uu_count;
                        if ((bp->b_flags&B_READ) == 0)
                        if ((bp->b_flags&B_READ) == 0)
-                               uu_vee(&pcnt[minor(bp->b_dev)&DNUM]);
+                               uu_vee(&pcnt[UNIT(bp->b_dev)]);
                        iodone(bp);
                        iodone(bp);
-                       uustart();
+                       uustart(um);
                } else {
                        printf("neither data nor end: %o %o\n",
                } else {
                        printf("neither data nor end: %o %o\n",
-                           uudata.pk_flag&0xff, uudata.pk_op&0xff);
-                       mtpr(CSRS, 0);          /* flush the rest */
-                       uu->uu_state = TUS_INIT1;
+                           data->pk_flag&0xff, data->pk_op&0xff);
+                       uuaddr->rcs = 0;                /* flush the rest */
+                       uuc->uu_state = UUS_INIT1;
                }
                break;
 
                }
                break;
 
-       case TUS_IDLE:
-       case TUS_INIT1:
+       case UUS_IDLE:
+       case UUS_INIT1:
                break;
 
        default:
 bad:
                if (c == TUF_INITF) {
                break;
 
        default:
 bad:
                if (c == TUF_INITF) {
-                       printf("uu protocol error, state=");
-                       printstate(uu->uu_state);
+                       printf("uu%d protocol error, state=", UNIT(bp->b_dev));
+                       printstate(uuc->uu_state);
                        printf(", op=%x, cnt=%d, block=%d\n",
                        printf(", op=%x, cnt=%d, block=%d\n",
-                           uucmd.pk_op, uucmd.pk_count, uucmd.pk_block);
-                       uutab.b_active = NULL;
-                       if (bp = uutab.b_actf) {
+                           cmd->pk_op, cmd->pk_count, cmd->pk_block);
+                       uutab->b_active = NULL;
+                       if (bp = uutab->b_actf) {
                                bp->b_flags |= B_ERROR;
                                bp->b_flags |= B_ERROR;
-                               uutab.b_actf = bp->av_forw;
+                               uutab->b_actf = bp->av_forw;
                                if ((bp->b_flags&B_READ) == 0)
                                if ((bp->b_flags&B_READ) == 0)
-                                       uu_vee(&pcnt[minor(bp->b_dev)&DNUM]);
+                                       uu_vee(&pcnt[UNIT(bp->b_dev)]);
                                iodone(bp);
                        }
                                iodone(bp);
                        }
-                       uu->uu_state = TUS_INIT1;
+                       uuc->uu_state = UUS_INIT1;
                } else {
                } else {
-                       printf("uu receive state error, state=");
+                       printf("uu%d receive state error, state=", 
+                               UNIT(bp->b_dev));
+                       printstate(uuc->uu_state);
                        printf(", byte=%x\n", c);
 #ifdef notdef
                        printf(", byte=%x\n", c);
 #ifdef notdef
-                       uu->uu_state = TUS_INIT1; */
+                       uuc->uu_state = UUS_INIT1; */
 #endif
 #endif
-                       wakeup((caddr_t)&uu);
+                       wakeup((caddr_t)uuc);
                }
        }
 }
                }
        }
 }
@@ -564,18 +575,25 @@ bad:
 /*
  * TU58 transmitter interrupt
  */
 /*
  * TU58 transmitter interrupt
  */
-uuxintr()
+uuxintr(ctlr)
+       int ctlr;
 {
 {
+       register struct uu_ctlr *uuc = &uu_ctlr[ctlr];
+       register struct uudevice *uuaddr = 
+                               (struct uudevice *) uuminfo[ctlr]->um_addr;
+       register struct packet *data;
+       int c;
 
 top:
 
 top:
-       if (uu->uu_wcnt) {
+       if (uuc->uu_wcnt) {
                /* still stuff to send, send one byte */
                /* still stuff to send, send one byte */
-               while ((mfpr(CSTS) & READY) == 0)
+               while ((uuaddr->tcs & UUCS_READY) == 0)
                        ;
                        ;
-               mtpr(CSTD, *uu->uu_wbptr++);
-               uu->uu_wcnt--;
+               uuaddr->tdb = *uuc->uu_wbptr++;
+               uuc->uu_wcnt--;
                return;
        }
                return;
        }
+       data = &uudata[ctlr];
 
        /*
         * Last message byte was sent out.
 
        /*
         * Last message byte was sent out.
@@ -583,110 +601,110 @@ top:
         */
        if (uudebug) {
                printf("uuxintr: state=");
         */
        if (uudebug) {
                printf("uuxintr: state=");
-               printstate(uu->uu_state);
+               printstate(uuc->uu_state);
        }
        }
-       switch(uu->uu_state) {
+       switch(uuc->uu_state) {
 
        /*
         * Two nulls have been sent, remove break, and send inits
         */
 
        /*
         * Two nulls have been sent, remove break, and send inits
         */
-       case TUS_INIT1: 
-               mtpr(CSTS, IE);
+       case UUS_INIT1: 
+               uuaddr->tcs = UUCS_INTR;
                printd("ON2 ");
                printd("ON2 ");
-               uu->uu_state = TUS_INIT2;
-               uu->uu_wbptr = uuinit;
-               uu->uu_wcnt = sizeof (uuinit);
+               uuc->uu_state = UUS_INIT2;
+               uuc->uu_wbptr = uuinit;
+               uuc->uu_wcnt = sizeof (uuinit);
                goto top;
 
        /*
         * Inits have been sent, wait for a continue msg.
         */
                goto top;
 
        /*
         * Inits have been sent, wait for a continue msg.
         */
-       case TUS_INIT2: 
-               (void) mfpr(CSRD);
-               mtpr(CSRS, IE);
-               uu->uu_flag = 1;
+       case UUS_INIT2: 
+               c = uuaddr->rdb;                /* not used */
+               uuaddr->rcs = UUCS_INTR;
+               uuc->uu_flag = 1;
                break;
 
                break;
 
-       case TUS_IDLE:          /* stray interrupt? */
+       case UUS_IDLE:          /* stray interrupt? */
                break;
 
        /*
         * Read cmd packet sent, get ready for data
         */
                break;
 
        /*
         * Read cmd packet sent, get ready for data
         */
-       case TUS_SENDR:
-               uu->uu_state = TUS_GETH;
-               uu->uu_rbptr = (u_char *)&uudata;
-               uu->uu_rcnt = 2;
-               uu->uu_flag = 1;
-               mtpr(CSTS, 0);  /* disable transmitter interrupts */
+       case UUS_SENDR:
+               uuc->uu_state = UUS_GETH;
+               uuc->uu_rbptr = (u_char *)data;
+               uuc->uu_rcnt = 2;
+               uuc->uu_flag = 1;
+               uuaddr->tcs = 0;        /* disable transmitter interrupts */
                printd("OFF ");
                break;
 
        /*
         * Write cmd packet sent, wait for continue
         */
                printd("OFF ");
                break;
 
        /*
         * Write cmd packet sent, wait for continue
         */
-       case TUS_SENDW: 
-               uu->uu_state = TUS_WAIT;
-               uu->uu_flag = 1;
-               if ((mfpr(CSRS)&IE) == 0) {
+       case UUS_SENDW: 
+               uuc->uu_state = UUS_WAIT;
+               uuc->uu_flag = 1;
+               if ((uuaddr->rcs&UUCS_INTR) == 0) {
                        printf("NO IE\n");
                        printf("NO IE\n");
-                       mtpr(CSRS, IE);
+                       uuaddr->rcs = UUCS_INTR;
                }
                break;
 
        /*
         * Header sent, send data.
         */
                }
                break;
 
        /*
         * Header sent, send data.
         */
-       case TUS_SENDH:
-               uu->uu_state = TUS_SENDD;
-               uu->uu_wbptr = (u_char *)uu->uu_addr;
-               uu->uu_wcnt = uudata.pk_mcount;
+       case UUS_SENDH:
+               uuc->uu_state = UUS_SENDD;
+               uuc->uu_wbptr = (u_char *)uuc->uu_addr;
+               uuc->uu_wcnt = data->pk_mcount;
                goto top;
 
        /*
         * Data sent, follow with checksum.
         */
                goto top;
 
        /*
         * Data sent, follow with checksum.
         */
-       case TUS_SENDD: 
-               uu->uu_state = TUS_SENDC;
-               uu->uu_wbptr = (u_char *)&uudata.pk_chksum;
-               uu->uu_wcnt = sizeof uudata.pk_chksum;
+       case UUS_SENDD: 
+               uuc->uu_state = UUS_SENDC;
+               uuc->uu_wbptr = (u_char *)&data->pk_chksum;
+               uuc->uu_wcnt = sizeof (data->pk_chksum);
                goto top;
 
        /* 
         * Checksum sent, wait for continue.
         */
                goto top;
 
        /* 
         * Checksum sent, wait for continue.
         */
-       case TUS_SENDC:
+       case UUS_SENDC:
                /*
                 * Updata buffer address and count.
                 */
                /*
                 * Updata buffer address and count.
                 */
-               uu->uu_addr += uudata.pk_mcount;
-               uu->uu_count -= uudata.pk_mcount;
-               if (uu->uu_count) {
-                       uu->uu_state = TUS_WAIT;
-                       uu->uu_flag = 1;
+               uuc->uu_addr += data->pk_mcount;
+               uuc->uu_count -= data->pk_mcount;
+               if (uuc->uu_count) {
+                       uuc->uu_state = UUS_WAIT;
+                       uuc->uu_flag = 1;
                        break;
                }
 
                /*
                 * End of transmission, get ready for end packet.
                 */
                        break;
                }
 
                /*
                 * End of transmission, get ready for end packet.
                 */
-               uu->uu_state = TUS_GET;
-               uu->uu_rbptr = (u_char *)&uudata;
-               uu->uu_rcnt = sizeof (uudata);
-               uu->uu_flag = 1;
-               mtpr(CSTS, 0);
+               uuc->uu_state = UUS_GET;
+               uuc->uu_rbptr = (u_char *)data;
+               uuc->uu_rcnt = sizeof (*data);
+               uuc->uu_flag = 1;
+               uuaddr->tcs = 0;                /* disable transm. interrupts */
                printd("OFF2 ");
                break;
 
        /*
                printd("OFF2 ");
                break;
 
        /*
-        * Random interrupt, probably from MRSP ACK
+        * Random interrupt
         */
        default:
                break;
        }
        if (uudebug) {
                printd("  new uu_state=");
         */
        default:
                break;
        }
        if (uudebug) {
                printd("  new uu_state=");
-               printstate(uu->uu_state);
+               printstate(uuc->uu_state);
        }
 }
 
        }
 }
 
@@ -733,45 +751,75 @@ uuchk(word0, wp, n)
 
 uuwatch()
 {
 
 uuwatch()
 {
-       register int s;
-       register struct buf *bp;
+       register struct uu_ctlr *uuc;
+       register struct uudevice *uuaddr;
+       struct uba_ctlr *um;
+       struct buf *bp, *uutab;
+       int s;
 
 
-       if (uutimer == 0) {
-               uu->uu_flag = 0;
-               return;
-       }
-       if (uu->uu_flag)
-               uu->uu_flag++;
-       if (uu->uu_flag <= 40) {
-               timeout(uuwatch, (caddr_t)0, hz);
+       if (uuwstart == 0)
                return;
                return;
+       for (s=0; s<NDL; s++) {
+               int i;
+
+               uuc = &uu_ctlr[s];
+               um = uuminfo[s];
+               if (uuc->uu_flag)
+                       uuc->uu_flag++;
+               if (uuc->uu_flag <= 40)
+                       continue;
+               printf("uu%d: read stalled\n", s);
+               printf("%X %X %X %X %X %X %X %X\n", uuc->uu_rbptr, uuc->uu_rcnt,
+                      uuc->uu_wbptr, uuc->uu_wcnt, uuc->uu_state, uuc->uu_flag,
+                      uuc->uu_addr, uuc->uu_count);
+               uuc->uu_flag = 0;
+               uuaddr = (struct uudevice *)um->um_addr;
+               uutab = &um->um_tab;
+               i = uuaddr->rdb;                /* dummy */
+               uuaddr->rcs = UUCS_INTR;        /* in case we were flushing */
+               uuaddr->tcs = UUCS_INTR;
+               uuc->uu_state = UUS_IDLE;
+               if (!uutab->b_active) {
+                       wakeup((caddr_t)uuc);
+                       continue;
+               }
+               if (++uutab->b_errcnt <= 1) {
+                       uustart(um);
+                       continue;
+               }
+               if (bp = uutab->b_actf) {
+                       bp->b_flags |= B_ERROR;
+                       if ((bp->b_flags&B_READ) == 0)
+                               uu_vee(&pcnt[UNIT(bp->b_dev)]);
+                       iodone(bp);
+               }
        }
        }
-       printf("uu: read stalled\n");
-       printf("%X %X %X %X %X %X %X %X\n", uu->uu_rbptr, uu->uu_rcnt,
-               uu->uu_wbptr, uu->uu_wcnt, uu->uu_state, uu->uu_flag,
-               uu->uu_addr, uu->uu_count);
-       uu->uu_flag = 0;
-       s = splx(TUIPL);
-       (void) mfpr(CSRD);
-       mtpr(CSRS, IE);         /* in case we were flushing */
-       mtpr(CSTS, IE);
-       uu->uu_state = TUS_IDLE;
-       if (!uutab.b_active) {
-               wakeup((caddr_t)&uu);
-               goto retry;
-       }
-       if (++uutab.b_errcnt <= 1) {
-               uustart();
-               goto retry;
+       timeout(uuwatch, (caddr_t)0, hz);
+       return;
+}
+
+uu_pee(cp)
+char *cp;
+{
+       register int s;
+
+       s = spl5();
+       if (++(*cp) > NTUQ) {
+               sleep(cp, PRIBIO);
        }
        }
-       if (bp = uutab.b_actf) {
-               bp->b_flags |= B_ERROR;
-               if ((bp->b_flags&B_READ) == 0)
-                       uu_vee(&pcnt[minor(bp->b_dev)&DNUM]);
-               iodone(bp);
+       splx(s);
+}
+
+uu_vee(cp)
+char *cp;
+{
+       register int s;
+
+       s = spl5();
+       if (--(*cp) <= NTUQ) {
+               wakeup(cp);
        }
        }
-retry:
        splx(s);
        splx(s);
-       timeout(uuwatch, (caddr_t)0, hz);
 }
 #endif
 }
 #endif
+