1*14152Shelge /* uu.c 4.10 83/07/27 */ 211876Shelge 312332Shelge #include "uu.h" 412857Shelge #if NUU > 0 511876Shelge /* 611896Shelge * TU58 DECtape II/DL11 device driver 711876Shelge * 813156Shelge * The TU58 is treated as a block device (only). Error detection and 913156Shelge * recovery is not very extensive, but sufficient to handle the most 1014091Shelge * common errors. It is assumed that the TU58 will follow the RSP 1114091Shelge * protocol exactly, very few protocol errors are checked for. 1214091Shelge * 1314091Shelge * To reduce interrupt latency, `options UUDMA' should be specified 1414091Shelge * in the config file to make sure the `pseudo-DMA' code in locore.s 1514091Shelge * will be compiled into the system. Otherwise overrun errors will 1614091Shelge * occur frequently (these errors are not reported). 1714091Shelge * 1814091Shelge * TODO: 1914091Shelge * 2014091Shelge * - Add ioctl code to wind/rewind cassette 2114091Shelge * 2211876Shelge */ 2311896Shelge 2412332Shelge #include "../machine/pte.h" 2511896Shelge 2611876Shelge #include "../h/param.h" 2711876Shelge #include "../h/systm.h" 2811876Shelge #include "../h/buf.h" 2911876Shelge #include "../h/conf.h" 3012332Shelge #include "../h/time.h" 3111896Shelge #include "../h/kernel.h" 3211896Shelge #include "../h/errno.h" 3311896Shelge #include "../h/file.h" 3411876Shelge 3511876Shelge #include "../vax/cpu.h" 3612332Shelge #include "../vax/nexus.h" 3712937Shelge #include "../vax/rsp.h" 3812332Shelge 3911896Shelge #include "../vaxuba/ubavar.h" 4011896Shelge #include "../vaxuba/ubareg.h" 4111896Shelge #include "../vaxuba/uureg.h" 4211876Shelge 4311876Shelge #define NTUBLK 512 /* number of blocks on a TU58 cassette */ 4412857Shelge #define WRV 01 /* bit in minor dev => write w. read verify */ 4512332Shelge #define NDPC 02 /* drives per controller */ 4612857Shelge #define NUX NDPC * NUU /* number of drives */ 4714091Shelge #define NUUQ 02 /* # of block which can be queued up */ 4812857Shelge #define UMASK 01 /* unit number mask */ 4912937Shelge #define UUIPL 0x14 /* ipl level to use */ 5011876Shelge 5112857Shelge struct packet uucmd[NUU]; /* a command sent to the TU58 */ 5212857Shelge struct packet uudata[NUU]; /* a command or data returned from TU58 */ 5312857Shelge struct buf uitab[NUU]; /* buffer queue headers */ 5411876Shelge 5511876Shelge /* 5612937Shelge * Driver soft carrier structure 5711876Shelge */ 5812937Shelge struct uu_softc { 5912937Shelge u_char *tu_rbptr; /* pointer to buffer for read */ 6012937Shelge int tu_rcnt; /* how much to read */ 6112937Shelge u_char *tu_wbptr; /* pointer to buffer for write */ 6212937Shelge int tu_wcnt; /* how much to write */ 6312937Shelge int tu_state; /* current state of tansfer operation */ 6412937Shelge int tu_flag; /* read in progress flag */ 6512937Shelge char *tu_addr; /* real buffer data address */ 6612937Shelge int tu_count; /* real requested count */ 6712937Shelge int tu_serrs; /* count of soft errors */ 6812937Shelge int tu_cerrs; /* count of checksum errors */ 6912937Shelge int tu_herrs; /* count of hard errors */ 7012937Shelge char tu_dopen[2]; /* drive is open */ 7113014Shelge } uu_softc[NUU]; 7211876Shelge 7312937Shelge #if defined(VAX750) || defined(VAX730) 7412937Shelge extern char *tustates[]; 7512937Shelge #else 7612937Shelge char *tustates[TUS_NSTATES] = { 7711876Shelge "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", 7813014Shelge "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR" 7911876Shelge }; 8012937Shelge #endif 8112332Shelge 8212857Shelge #define UNIT(dev) (minor(dev)>>1) 8311876Shelge 8414091Shelge u_char uunull[2] = { 0, 0 }; /* nulls to send for initialization */ 8511896Shelge u_char uuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ 8611876Shelge 8711896Shelge struct uba_device *uudinfo[NUU]; 8811896Shelge 8912857Shelge int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch(); 9012857Shelge u_short uustd[] = { 0176500 }; 9112857Shelge struct uba_driver uudriver = 9212857Shelge { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo }; 9311896Shelge 9411896Shelge int uuwstart; 95*14152Shelge int uuwake(); 9614091Shelge static char uu_pcnt[NUX]; /* pee/vee counters, one per drive */ 9711896Shelge 9811876Shelge /*ARGSUSED*/ 9911896Shelge uuprobe(reg) 10011896Shelge caddr_t reg; 10111876Shelge { 10211896Shelge register int br, cvec; /* value result */ 10311896Shelge struct uudevice *uuaddr = (struct uudevice *)reg; 10411876Shelge 10511876Shelge #ifdef lint 10611896Shelge br = 0; cvec = br; br = cvec; 10711896Shelge uurintr(0); uuxintr(0); 10811876Shelge #endif 10912857Shelge uuaddr->tcs = UUCS_INTR; 11012857Shelge DELAY(1000); 11112857Shelge uuaddr->tcs = 0; 11212857Shelge cvec -= 4; /* since we are using the xmitter intrpt */ 11311896Shelge return(sizeof (*uuaddr)); 11411896Shelge } 11511896Shelge 11611896Shelge uuattach(ui) 11712857Shelge register struct uba_device *ui; 11811896Shelge { 11911896Shelge } 12011896Shelge 12111896Shelge /*ARGSUSED1*/ 12211896Shelge uuopen(dev, flag) 12311896Shelge dev_t dev; 12411896Shelge int flag; 12511896Shelge { 12611896Shelge register struct uba_device *ui; 12713014Shelge register struct uu_softc *uuc; 12811896Shelge register struct uudevice *uuaddr; 12912332Shelge int ctlr, unit = UNIT(dev), s; 13011896Shelge 13112857Shelge ctlr = unit / NDPC; 13212857Shelge if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0) 13311876Shelge return (ENXIO); 13412937Shelge uuc = &uu_softc[ctlr]; 13512937Shelge if (uuc->tu_dopen[unit&UMASK]) 13611896Shelge return (EBUSY); 13711896Shelge if (uuwstart++ == 0) 13811896Shelge timeout(uuwatch, (caddr_t)0, hz); 13911896Shelge 14012937Shelge uuc->tu_dopen[unit&UMASK]++; 14112857Shelge uuaddr = (struct uudevice *)ui->ui_addr; 14212857Shelge s = splx(UUIPL); 14311876Shelge /* 14413014Shelge * If the other device on this controller 14514091Shelge * is already active, no need to initialize 14613014Shelge */ 14713014Shelge if (uuc->tu_dopen[0] && uuc->tu_dopen[1]) 14813156Shelge goto ok; 14913014Shelge 15013014Shelge /* 15111896Shelge * If the unit already initialized, 15211876Shelge * just enable interrupts and return. 15311876Shelge */ 15412937Shelge if (uuc->tu_state == TUS_IDLE) { 15511896Shelge uuaddr->rcs = UUCS_INTR; 15612937Shelge goto ok; 15711876Shelge } 15811876Shelge 15911876Shelge /* 16011876Shelge * Must initialize, reset the cassette 16111876Shelge * and wait for things to settle down. 16211876Shelge */ 16311896Shelge uureset(ctlr); 16411896Shelge sleep((caddr_t)uuc, PZERO+1); 16512857Shelge uitab[ctlr].b_active = NULL; 16612937Shelge if (uuc->tu_state != TUS_IDLE) { 16712937Shelge uuc->tu_state = TUS_INIT1; 16812937Shelge uuc->tu_dopen[unit&UMASK] = 0; 16912937Shelge uuc->tu_rcnt = uuc->tu_wcnt = 0; 17011896Shelge uuaddr->rcs = 0; 17111896Shelge uuaddr->tcs = 0; 17211896Shelge splx(s); 17312937Shelge return (EIO); 17411876Shelge } 17512937Shelge ok: 17611876Shelge splx(s); 17711876Shelge return (0); 17811876Shelge } 17911876Shelge 18014091Shelge /* 18114091Shelge * Wait for all outstanding IO on this drive 18214091Shelge * complete, before closing. If both drives on 18314091Shelge * this controller are idle, mark the controller 18414091Shelge * `inactive'. 18514091Shelge */ 18614091Shelge 18711896Shelge uuclose(dev, flag) 18811896Shelge dev_t dev; 18911896Shelge int flag; 19011876Shelge { 19114091Shelge int s, unit = UNIT(dev); 19214091Shelge register struct uu_softc *uuc = &uu_softc[unit/NDPC]; 19314091Shelge struct buf *bp, *last = NULL; 19414091Shelge struct uudevice *uuaddr = (struct uudevice *)uudinfo[unit/NDPC]->ui_addr; 19511876Shelge 19614091Shelge s = splx(UUIPL); 19714091Shelge while (uu_pcnt[unit]) 19814091Shelge sleep(&uu_pcnt[unit], PRIBIO); 19914091Shelge /* 20014091Shelge * No more writes are pending, scan the 20114091Shelge * buffer queue for oustanding reads from 20214091Shelge * this unit. 20314091Shelge */ 204*14152Shelge for (bp = uitab[unit/NDPC].b_actf; bp; bp = bp->b_actf) { 20514091Shelge if (bp->b_dev == dev) 20614091Shelge last = bp; 207*14152Shelge } 208*14152Shelge if (last) { 209*14152Shelge last->b_flags |= B_CALL; 210*14152Shelge last->b_iodone = uuwake; 211*14152Shelge sleep((caddr_t)last, PRIBIO); 212*14152Shelge } 21314091Shelge uuc->tu_dopen[unit&UMASK] = 0; 21414091Shelge if (!uuc->tu_dopen[0] && !uuc->tu_dopen[1]) { 21514091Shelge uuc->tu_flag = 0; 21614091Shelge uuaddr->rcs = 0; 21714091Shelge } 21814091Shelge splx(s); 21911876Shelge } 22011876Shelge 221*14152Shelge uuwake(bp) 222*14152Shelge struct buf *bp; 223*14152Shelge { 224*14152Shelge wakeup(bp); 225*14152Shelge } 226*14152Shelge 22711896Shelge uureset(ctlr) 22811896Shelge int ctlr; 22911876Shelge { 23013014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 23112332Shelge register struct packet *cmd = &uucmd[ctlr]; 23212857Shelge struct uba_device *ui = uudinfo[ctlr]; 23312857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 23411876Shelge 23512857Shelge uitab[ctlr].b_active++; 23612937Shelge uuc->tu_state = TUS_INIT1; 23712937Shelge uuc->tu_wbptr = uunull; 23812937Shelge uuc->tu_wcnt = sizeof (uunull); 23914091Shelge uuc->tu_rcnt = 0; 24011896Shelge cmd->pk_flag = TUF_CMD; 24112332Shelge cmd->pk_mcount = sizeof (*cmd) - 4; 24211896Shelge cmd->pk_mod = 0; 24311896Shelge cmd->pk_seq = 0; 24412332Shelge cmd->pk_sw = 0; 24511896Shelge uuaddr->rcs = 0; 24611896Shelge uuaddr->tcs = UUCS_INTR | UUCS_BREAK; 24711896Shelge uuxintr(ctlr); /* start output */ 24811876Shelge } 24911876Shelge 25011876Shelge /* 25111876Shelge * Strategy routine for block I/O 25211876Shelge */ 25311896Shelge uustrategy(bp) 25411876Shelge register struct buf *bp; 25511876Shelge { 25612332Shelge register struct buf *uutab; 25711896Shelge struct uba_device *ui; 25814091Shelge int s, unit = UNIT(bp->b_dev); 25911876Shelge 26014091Shelge if ((unit > NUX) || (bp->b_blkno >= NTUBLK)) 26111896Shelge goto bad; 26212857Shelge ui = uudinfo[unit/NDPC]; 26311896Shelge if (ui == 0 || ui->ui_alive == 0) 26411896Shelge goto bad; 26512857Shelge uutab = &uitab[unit/NDPC]; /* one request queue per controller */ 26613156Shelge s = splx(UUIPL); 26712332Shelge if ((bp->b_flags&B_READ) == 0) 26814091Shelge tu_pee(&uu_pcnt[unit]); 26914091Shelge bp->b_actf = NULL; 27012332Shelge if (uutab->b_actf == NULL) 27112332Shelge uutab->b_actf = bp; 27212332Shelge else 27314091Shelge uutab->b_actl->b_actf = bp; 27412332Shelge uutab->b_actl = bp; 27512332Shelge if (uutab->b_active == 0) 27612857Shelge uustart(ui); 27711876Shelge splx(s); 27811896Shelge return; 27911896Shelge 28011896Shelge bad: 28111896Shelge bp->b_flags |= B_ERROR; 28212332Shelge bp->b_error = ENXIO; 28311896Shelge iodone(bp); 28411896Shelge return; 28511876Shelge } 28611876Shelge 28711876Shelge /* 28811876Shelge * Start the transfer 28911876Shelge */ 29012857Shelge uustart(ui) 29112857Shelge register struct uba_device *ui; 29211876Shelge { 29311876Shelge register struct buf *bp; 29413014Shelge register struct uu_softc *uuc; 29511896Shelge struct packet *cmd; 296*14152Shelge int ctlr = ui->ui_unit, s; 29711876Shelge 29812857Shelge if ((bp = uitab[ctlr].b_actf) == NULL) 29911876Shelge return; 300*14152Shelge s = splx(UUIPL); 30112937Shelge uuc = &uu_softc[ctlr]; 30212937Shelge if (uuc->tu_state != TUS_IDLE) { 30312332Shelge uureset(ctlr); 304*14152Shelge splx(s); 30511876Shelge return; 30611876Shelge } 30714091Shelge cmd = &uucmd[ctlr]; 30812857Shelge uitab[ctlr].b_active++; 30912937Shelge uitab[ctlr].b_errcnt = 0; 31012937Shelge uuc->tu_addr = bp->b_un.b_addr; 31112937Shelge uuc->tu_count = cmd->pk_count = bp->b_bcount; 31212937Shelge cmd->pk_block = bp->b_blkno; 31312937Shelge if (bp->b_flags&B_READ) { 31412937Shelge cmd->pk_op = TUOP_READ; 31512937Shelge cmd->pk_mod = 0; 31612937Shelge uuc->tu_state = TUS_SENDR; 31712937Shelge } else { 31812937Shelge cmd->pk_op = TUOP_WRITE; 31912937Shelge cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0; 32012937Shelge uuc->tu_state = TUS_SENDW; 32112937Shelge } 32214091Shelge cmd->pk_unit = UNIT(bp->b_dev)&UMASK; 32312332Shelge cmd->pk_sw = 0; 32411896Shelge cmd->pk_chksum = 32512937Shelge tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount); 32612937Shelge uuc->tu_wbptr = (u_char *)cmd; 32712937Shelge uuc->tu_wcnt = sizeof (*cmd); 32812332Shelge uuxintr(ctlr); 329*14152Shelge splx(s); 33011876Shelge } 33111876Shelge 33211876Shelge /* 33314091Shelge * TU58 receiver interrupt, handles whatever condition the 33414091Shelge * pseudo DMA routine in locore is unable to handle, 33514091Shelge * or, if UUDMA is undefined, handle all receiver interrupt 33614091Shelge * processing. 33711876Shelge */ 33812332Shelge uurintr(ctlr) 33912332Shelge int ctlr; 34011876Shelge { 34112857Shelge struct uba_device *ui = uudinfo[ctlr]; 34213014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 34312857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 34412857Shelge register struct buf *uutab = &uitab[ctlr]; 34512332Shelge struct packet *data, *cmd; 34612937Shelge struct buf *bp; 34712937Shelge int c, unit; 34811876Shelge 34912857Shelge c = uuaddr->rdb; 35012937Shelge data = &uudata[ctlr]; 35113014Shelge cmd = &uucmd[ctlr]; 35213014Shelge #if !defined(UUDMA) 35313014Shelge if (c & UURDB_ERROR) 35413014Shelge uuc->tu_state = TUS_RCVERR; 35513014Shelge else { 35613014Shelge if (uuc->tu_rcnt) { 35713014Shelge *uuc->tu_rbptr++ = c; 35813014Shelge if (--uuc->tu_rcnt) 35913014Shelge return; 36013014Shelge } 36113014Shelge } 36213014Shelge #endif 36313014Shelge 36413014Shelge /* 36513014Shelge * Switch on the tu_state of the transfer. 36613014Shelge */ 36713014Shelge switch(uuc->tu_state) { 36813014Shelge 36913014Shelge /* 37013014Shelge * A data error occured in uudma 37113014Shelge * (either overrun or break) 37213014Shelge */ 37313014Shelge case TUS_RCVERR: 37413156Shelge if ((c & UURDB_ORUN) == 0) 37513156Shelge printf("uu%d: break received, transfer restarted\n", 37613834Ssam data->pk_unit); 37714091Shelge #ifdef UUDEBUG 37814091Shelge else 37914091Shelge printf("uu%d: data overrun, recovered\n", 38014091Shelge data->pk_unit); 38114091Shelge #endif 38213156Shelge uuc->tu_serrs++; 38313014Shelge uu_restart(ctlr, ui); 38413014Shelge break; 38511876Shelge 38611876Shelge /* 38711876Shelge * If we get an unexpected "continue", 38811876Shelge * start all over again... 38911876Shelge */ 39012937Shelge case TUS_INIT2: 39112937Shelge uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; 39212937Shelge uuc->tu_flag = 0; 39312332Shelge wakeup((caddr_t)uuc); 39412857Shelge uustart(ui); 39511876Shelge break; 39611876Shelge 39711876Shelge /* 39811876Shelge * Only transition from this state 39911876Shelge * is on a "continue", so if we don't 40011876Shelge * get it, reset the world. 40111876Shelge */ 40212937Shelge case TUS_WAIT: /* waiting for continue */ 40312332Shelge switch(c) { 40412332Shelge case TUF_CONT: /* got the expected continue */ 40512937Shelge uuc->tu_flag = 0; 40612332Shelge data->pk_flag = TUF_DATA; 40712937Shelge data->pk_mcount = MIN(128, uuc->tu_count); 40812332Shelge data->pk_chksum = 40912937Shelge tuchk(*((short *)data), (caddr_t)uuc->tu_addr, 41012332Shelge (int)data->pk_mcount); 41112937Shelge uuc->tu_state = TUS_SENDH; 41212937Shelge uuc->tu_wbptr = (u_char *)data; 41312937Shelge uuc->tu_wcnt = 2; 41412857Shelge uuxintr(ctlr); 41511876Shelge break; 41612332Shelge 41712332Shelge case TUF_CMD: /* sending us an END packet...error */ 41812937Shelge uuc->tu_state = TUS_GET; 41912937Shelge uuc->tu_rbptr = (u_char *)data; 42013014Shelge uuc->tu_rcnt = sizeof (*data) - 1; 42112937Shelge uuc->tu_flag = 1; 42212332Shelge uuaddr->tcs = 0; 42313014Shelge *uuc->tu_rbptr++ = c & UUDB_DMASK; 42413014Shelge break; 42512332Shelge 42612332Shelge case TUF_INITF: 42712857Shelge uureset(ctlr); 42812332Shelge break; 42912332Shelge 43012332Shelge default: /* something random...bad news */ 43112937Shelge uuc->tu_state = TUS_INIT1; 43212332Shelge break; 43311876Shelge } 43411876Shelge break; 43511876Shelge 43612937Shelge case TUS_SENDW: 43712937Shelge if (c != TUF_CONT && c != TUF_INITF) 43811876Shelge goto bad; 43913014Shelge uu_restart(ctlr, ui); 44011876Shelge break; 44111876Shelge 44211876Shelge /* 44311876Shelge * Got header, now get data; amount to 44411896Shelge * fetch is included in packet. 44513014Shelge * (data packets are handled entirely 44613014Shelge * in uudma) 44711876Shelge */ 44812937Shelge case TUS_GETH: 44913156Shelge #ifndef UUDMA 45013156Shelge if (data->pk_flag == TUF_DATA) 45113156Shelge uuc->tu_rbptr = (u_char *)uuc->tu_addr; 45213156Shelge #endif 45312937Shelge uuc->tu_rcnt = data->pk_mcount; 45412937Shelge uuc->tu_state = TUS_GETD; 45511876Shelge break; 45611876Shelge 45711876Shelge /* 45811876Shelge * Got the data, now fetch the checksum. 45911876Shelge */ 46012937Shelge case TUS_GETD: 46112937Shelge uuc->tu_rbptr = (u_char *)&data->pk_chksum; 46212937Shelge uuc->tu_rcnt = sizeof (data->pk_chksum); 46312937Shelge uuc->tu_state = TUS_GETC; 46411876Shelge break; 46511876Shelge 46612937Shelge case TUS_GETC: 46711876Shelge /* got entire packet */ 46812332Shelge if (data->pk_chksum != 46912937Shelge tuchk(*((short *)data), (u_short *) 47013014Shelge (data->pk_flag == TUF_DATA ? 47113156Shelge (u_short *) uuc->tu_addr : (u_short *)&data->pk_op), 47212332Shelge (int)data->pk_mcount)) 47313014Shelge case TUS_CHKERR: 47412937Shelge uuc->tu_cerrs++; 47513014Shelge case TUS_GET: 47612332Shelge if (data->pk_flag == TUF_DATA) { 47711876Shelge /* data packet, advance to next */ 47812937Shelge uuc->tu_addr += data->pk_mcount; 47912937Shelge uuc->tu_count -= data->pk_mcount; 48012937Shelge uuc->tu_state = TUS_GETH; 48112937Shelge uuc->tu_rbptr = (u_char *)data; /* next packet */ 48212937Shelge uuc->tu_rcnt = 2; 48312332Shelge } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { 48411876Shelge /* end packet, idle and reenable transmitter */ 48512937Shelge uuc->tu_state = TUS_IDLE; 48612937Shelge uuc->tu_flag = 0; 48712937Shelge uuaddr->tcs = UUCS_INTR; 48812937Shelge if ((bp = uutab->b_actf) == NULL) { 48913156Shelge printf("uu%d: no bp, active %d\n", 49013834Ssam data->pk_unit, uitab[ctlr].b_active); 49112857Shelge uustart(ui); 49211876Shelge return; 49311876Shelge } 49414091Shelge unit = UNIT(bp->b_dev); 49512332Shelge if (data->pk_mod > 1) { /* hard error */ 49613014Shelge printf("uu%d: hard error bn%d,", unit, 49713834Ssam bp->b_blkno); 49814091Shelge printf(" pk_mod 0%o\n", data->pk_mod&0xff); 49911876Shelge bp->b_flags |= B_ERROR; 50012937Shelge uuc->tu_herrs++; 50114091Shelge } else if (data->pk_mod) /* soft error */ 50212937Shelge uuc->tu_serrs++; 50312332Shelge uutab->b_active = NULL; 50414091Shelge uutab->b_actf = bp->b_actf; 50512937Shelge bp->b_resid = uuc->tu_count; 50611876Shelge if ((bp->b_flags&B_READ) == 0) 50714091Shelge tu_vee(&uu_pcnt[unit]); 50811876Shelge iodone(bp); 50912857Shelge uustart(ui); 51011876Shelge } else { 51113156Shelge /* 51213156Shelge * Neither data nor end: data was lost 51314091Shelge * somehow, flush and restart the transfer. 51413156Shelge */ 51514091Shelge uuaddr->rcs = 0; 51613014Shelge uu_restart(ctlr, ui); 51713156Shelge uuc->tu_serrs++; 51811876Shelge } 51911876Shelge break; 52011876Shelge 52112937Shelge case TUS_IDLE: 52212937Shelge case TUS_INIT1: 52311876Shelge break; 52411876Shelge 52511876Shelge default: 52611876Shelge bad: 52711876Shelge if (c == TUF_INITF) { 52813156Shelge printf("uu%d protocol error, state=", data->pk_unit); 52912937Shelge printstate(uuc->tu_state); 53011876Shelge printf(", op=%x, cnt=%d, block=%d\n", 53112332Shelge cmd->pk_op, cmd->pk_count, cmd->pk_block); 53212332Shelge uutab->b_active = NULL; 53312332Shelge if (bp = uutab->b_actf) { 53411876Shelge bp->b_flags |= B_ERROR; 53514091Shelge uutab->b_actf = bp->b_actf; 53611876Shelge if ((bp->b_flags&B_READ) == 0) 53714091Shelge tu_vee(&uu_pcnt[unit]); 53811876Shelge iodone(bp); 53911876Shelge } 54012937Shelge uuc->tu_state = TUS_INIT1; 54111876Shelge } else { 54212332Shelge printf("uu%d receive state error, state=", 54313156Shelge data->pk_unit); 54412937Shelge printstate(uuc->tu_state); 54513014Shelge printf(", byte=%x\n", c & 0xff); 54611876Shelge #ifdef notdef 54712937Shelge uuc->tu_state = TUS_INIT1; 54811876Shelge #endif 54912332Shelge wakeup((caddr_t)uuc); 55011876Shelge } 55111876Shelge } 55211876Shelge } 55311876Shelge 55412937Shelge 55512937Shelge /* 55611876Shelge * TU58 transmitter interrupt 55711876Shelge */ 55812332Shelge uuxintr(ctlr) 55912332Shelge int ctlr; 56011876Shelge { 56113014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 56212857Shelge register struct uudevice *uuaddr; 56312332Shelge register struct packet *data; 56412857Shelge struct uba_device *ui = uudinfo[ctlr]; 56512332Shelge int c; 56611876Shelge 56712857Shelge data = &uudata[ctlr]; 56812857Shelge uuaddr = (struct uudevice *) ui->ui_addr; 56911876Shelge top: 57014091Shelge if (uuc->tu_wcnt > 0) { 57111876Shelge /* still stuff to send, send one byte */ 57212332Shelge while ((uuaddr->tcs & UUCS_READY) == 0) 57311876Shelge ; 57412937Shelge uuaddr->tdb = *uuc->tu_wbptr++; 57512937Shelge uuc->tu_wcnt--; 57611876Shelge return; 57711876Shelge } 57811876Shelge 57911876Shelge /* 58011876Shelge * Last message byte was sent out. 58112937Shelge * Switch on tu_state of transfer. 58211876Shelge */ 58312937Shelge switch(uuc->tu_state) { 58411876Shelge 58511876Shelge /* 58611876Shelge * Two nulls have been sent, remove break, and send inits 58711876Shelge */ 58812937Shelge case TUS_INIT1: 58914091Shelge uuc->tu_flag = 0; 59012332Shelge uuaddr->tcs = UUCS_INTR; 59112937Shelge uuc->tu_state = TUS_INIT2; 59212937Shelge uuc->tu_wbptr = uuinit; 59312937Shelge uuc->tu_wcnt = sizeof (uuinit); 59411876Shelge goto top; 59511876Shelge 59611876Shelge /* 59711876Shelge * Inits have been sent, wait for a continue msg. 59811876Shelge */ 59912937Shelge case TUS_INIT2: 60012857Shelge c = uuaddr->rdb; /* prevent overrun error */ 60112332Shelge uuaddr->rcs = UUCS_INTR; 60212937Shelge uuc->tu_flag = 1; 60311876Shelge break; 60411876Shelge 60511876Shelge /* 60611876Shelge * Read cmd packet sent, get ready for data 60711876Shelge */ 60812937Shelge case TUS_SENDR: 60912937Shelge uuc->tu_state = TUS_GETH; 61012937Shelge uuc->tu_rbptr = (u_char *)data; 61112937Shelge uuc->tu_rcnt = 2; 61212937Shelge uuc->tu_flag = 1; 61314091Shelge uuaddr->tcs = 0; 61412937Shelge uuaddr->rcs = UUCS_INTR; 61511876Shelge break; 61611876Shelge 61711876Shelge /* 61811876Shelge * Write cmd packet sent, wait for continue 61911876Shelge */ 62012937Shelge case TUS_SENDW: 62112937Shelge uuc->tu_state = TUS_WAIT; 62212937Shelge uuc->tu_flag = 1; 62312332Shelge if ((uuaddr->rcs&UUCS_INTR) == 0) { 62411876Shelge printf("NO IE\n"); 62512332Shelge uuaddr->rcs = UUCS_INTR; 62611876Shelge } 62711876Shelge break; 62811876Shelge 62911876Shelge /* 63011876Shelge * Header sent, send data. 63111876Shelge */ 63212937Shelge case TUS_SENDH: 63312937Shelge uuc->tu_state = TUS_SENDD; 63412937Shelge uuc->tu_wbptr = (u_char *)uuc->tu_addr; 63512937Shelge uuc->tu_wcnt = data->pk_mcount; 63611876Shelge goto top; 63711876Shelge 63811876Shelge /* 63911876Shelge * Data sent, follow with checksum. 64011876Shelge */ 64112937Shelge case TUS_SENDD: 64212937Shelge uuc->tu_state = TUS_SENDC; 64312937Shelge uuc->tu_wbptr = (u_char *)&data->pk_chksum; 64414091Shelge uuc->tu_wcnt = 2; 64511876Shelge goto top; 64611876Shelge 64711876Shelge /* 64811876Shelge * Checksum sent, wait for continue. 64911876Shelge */ 65012937Shelge case TUS_SENDC: 65111876Shelge /* 65212937Shelge * Update buffer address and count. 65311876Shelge */ 65412937Shelge uuc->tu_addr += data->pk_mcount; 65512937Shelge uuc->tu_count -= data->pk_mcount; 65614091Shelge if (uuc->tu_count > 0) { 65712937Shelge uuc->tu_state = TUS_WAIT; 65812937Shelge uuc->tu_flag = 1; 65911876Shelge break; 66011876Shelge } 66111876Shelge 66211876Shelge /* 66311876Shelge * End of transmission, get ready for end packet. 66411876Shelge */ 66512937Shelge uuc->tu_state = TUS_GET; 66612937Shelge uuc->tu_rbptr = (u_char *)data; 66712937Shelge uuc->tu_rcnt = sizeof (*data); 66812937Shelge uuc->tu_flag = 1; 66914091Shelge uuaddr->tcs = 0; 67011876Shelge break; 67111876Shelge 67211876Shelge /* 67312332Shelge * Random interrupt 67411876Shelge */ 67513156Shelge case TUS_IDLE: /* stray interrupt? */ 67613156Shelge 67711876Shelge default: 67811876Shelge break; 67911876Shelge } 68012937Shelge } 68112937Shelge 68212937Shelge uuwatch() 68312937Shelge { 68413014Shelge register struct uu_softc *uuc; 68512937Shelge register struct uudevice *uuaddr; 68612937Shelge struct uba_device *ui; 68712937Shelge struct buf *bp, *uutab; 68812937Shelge int s, ctlr, active = 0; 68912937Shelge 69012937Shelge for (ctlr=0; ctlr<NUU; ctlr++) { 69112937Shelge int i; 69212937Shelge 69312937Shelge uuc = &uu_softc[ctlr]; 69414091Shelge 69514091Shelge if (uuc->tu_dopen[0] || uuc->tu_dopen[1]) 69614091Shelge active++; 69714091Shelge if (uuc->tu_flag == 0) 69814091Shelge /* 69914091Shelge * If no read is in progress 70014091Shelge * just skip 70114091Shelge */ 70214091Shelge continue; 70314091Shelge 70412937Shelge ui = uudinfo[ctlr]; 70512937Shelge uuaddr = (struct uudevice *)ui->ui_addr; 70612937Shelge uutab = &uitab[ctlr]; 70714091Shelge if (uuc->tu_flag++ < 40) 70812937Shelge continue; 70913156Shelge printf("uu%d: read stalled\n", uudata[ctlr].pk_unit); 71014091Shelge #ifdef UUDEBUG 71112937Shelge printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt, 71213156Shelge uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr, 71313156Shelge uuc->tu_count); 71413834Ssam #endif 71514091Shelge s = splx(UUIPL); 71612937Shelge uuc->tu_flag = 0; 71712937Shelge i = uuaddr->rdb; /* dummy */ 71812937Shelge uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ 71912937Shelge uuaddr->tcs = UUCS_INTR; 72012937Shelge uuc->tu_state = TUS_IDLE; 72112937Shelge if (!uutab->b_active) { 72212937Shelge wakeup((caddr_t)uuc); 72312937Shelge goto retry; 72412937Shelge } 72512937Shelge if (++uutab->b_errcnt <= 1) { 72612937Shelge uustart(ui); 72712937Shelge goto retry; 72812937Shelge } 72912937Shelge if (bp = uutab->b_actf) { 73012937Shelge bp->b_flags |= B_ERROR; 73112937Shelge if ((bp->b_flags&B_READ) == 0) 73214091Shelge tu_vee(&uu_pcnt[UNIT(bp->b_dev)]); 73312937Shelge iodone(bp); 73412937Shelge } 73512937Shelge retry: 73612937Shelge (void) splx(s); 73711876Shelge } 73812937Shelge if (active) 73912937Shelge timeout(uuwatch, (caddr_t)0, hz); 74012937Shelge else 74112937Shelge uuwstart = 0; 74212937Shelge return; 74311876Shelge } 74411876Shelge 74512937Shelge #if !defined(VAX750) && !defined(VAX730) 74611876Shelge /* 74711876Shelge * Compute checksum TU58 fashion 74811876Shelge */ 74911876Shelge #ifdef lint 75012937Shelge tuchk(word, cp, n) 75111876Shelge register word; 75211876Shelge register unsigned short *cp; 75311876Shelge int n; 75411876Shelge { 75511876Shelge register int c = n >> 1; 75611876Shelge register long temp; 75711876Shelge 75811876Shelge do { 75911876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 76011876Shelge word += temp; 76111876Shelge } while (--c > 0); 76211876Shelge if (n & 1) 76311876Shelge word += *(unsigned char *)cp; 76411876Shelge while (word & 0xffff0000) 76511876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 76611876Shelge return (word); 76711876Shelge } 76811876Shelge #else 76912937Shelge tuchk(word0, wp, n) 77011896Shelge register int word0; /* r11 */ 77111896Shelge register char *wp; /* r10 */ 77211896Shelge register int n; /* r9 */ 77311876Shelge { 77411876Shelge asm("loop:"); 77511896Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 77611896Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 77711876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 77811896Shelge asm(" blbc r9,ok"); /* odd byte count? */ 77911896Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 78011896Shelge asm(" addw2 r10,r11"); /* add it in */ 78111896Shelge asm(" adwc $0,r11"); /* and the carry */ 78211876Shelge asm("ok:"); 78311896Shelge asm(" movl r11,r0"); /* return sum */ 78411876Shelge } 78511876Shelge #endif 78611876Shelge 78714091Shelge /* 78814091Shelge * Make sure this incredibly slow device 78914091Shelge * doesn't eat up all the buffers in the 79014091Shelge * system by putting the requesting process 79114091Shelge * (remember: this device is 'single-user') 79214091Shelge * to sleep if the write-behind queue grows 79314091Shelge * larger than NUUQ. 79414091Shelge */ 79512937Shelge tu_pee(cp) 79614091Shelge char *cp; 79712332Shelge { 79812332Shelge register int s; 79912332Shelge 80012857Shelge s = splx(UUIPL); 80114091Shelge if (++(*cp) > NUUQ) 80212332Shelge sleep(cp, PRIBIO); 80312332Shelge splx(s); 80412332Shelge } 80512332Shelge 80612937Shelge tu_vee(cp) 80714091Shelge char *cp; 80812332Shelge { 80912332Shelge register int s; 81012332Shelge 81112857Shelge s = splx(UUIPL); 81214091Shelge if (--(*cp) <= NUUQ) 81312332Shelge wakeup(cp); 81411876Shelge splx(s); 81511876Shelge } 81611876Shelge #endif 81712332Shelge 81812937Shelge uuioctl(dev, cmd, data, flag) 81912937Shelge dev_t dev; 82012937Shelge caddr_t data; 82112937Shelge { 82212937Shelge /* 82313156Shelge * add code to wind/rewind cassette here 82412937Shelge */ 82512937Shelge return (ENXIO); 82612937Shelge } 82712937Shelge 82813014Shelge uu_restart(ctlr, ui) 82913014Shelge int ctlr; 83013014Shelge struct uba_device *ui; 83113014Shelge { 83213014Shelge uureset(ctlr); 83313014Shelge timeout(uustart, (caddr_t)ui, hz * 3); 83413014Shelge } 83514091Shelge 83614091Shelge #endif 837