1*14091Shelge /* uu.c 4.9 83/07/24 */ 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 10*14091Shelge * common errors. It is assumed that the TU58 will follow the RSP 11*14091Shelge * protocol exactly, very few protocol errors are checked for. 12*14091Shelge * 13*14091Shelge * To reduce interrupt latency, `options UUDMA' should be specified 14*14091Shelge * in the config file to make sure the `pseudo-DMA' code in locore.s 15*14091Shelge * will be compiled into the system. Otherwise overrun errors will 16*14091Shelge * occur frequently (these errors are not reported). 17*14091Shelge * 18*14091Shelge * TODO: 19*14091Shelge * 20*14091Shelge * - Add ioctl code to wind/rewind cassette 21*14091Shelge * 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 */ 47*14091Shelge #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 84*14091Shelge 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*14091Shelge static char uu_pcnt[NUX]; /* pee/vee counters, one per drive */ 9611896Shelge 9711876Shelge /*ARGSUSED*/ 9811896Shelge uuprobe(reg) 9911896Shelge caddr_t reg; 10011876Shelge { 10111896Shelge register int br, cvec; /* value result */ 10211896Shelge struct uudevice *uuaddr = (struct uudevice *)reg; 10311876Shelge 10411876Shelge #ifdef lint 10511896Shelge br = 0; cvec = br; br = cvec; 10611896Shelge uurintr(0); uuxintr(0); 10711876Shelge #endif 10812857Shelge uuaddr->tcs = UUCS_INTR; 10912857Shelge DELAY(1000); 11012857Shelge uuaddr->tcs = 0; 11112857Shelge cvec -= 4; /* since we are using the xmitter intrpt */ 11211896Shelge return(sizeof (*uuaddr)); 11311896Shelge } 11411896Shelge 11511896Shelge uuattach(ui) 11612857Shelge register struct uba_device *ui; 11711896Shelge { 11811896Shelge } 11911896Shelge 12011896Shelge /*ARGSUSED1*/ 12111896Shelge uuopen(dev, flag) 12211896Shelge dev_t dev; 12311896Shelge int flag; 12411896Shelge { 12511896Shelge register struct uba_device *ui; 12613014Shelge register struct uu_softc *uuc; 12711896Shelge register struct uudevice *uuaddr; 12812332Shelge int ctlr, unit = UNIT(dev), s; 12911896Shelge 13012857Shelge ctlr = unit / NDPC; 13112857Shelge if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0) 13211876Shelge return (ENXIO); 13312937Shelge uuc = &uu_softc[ctlr]; 13412937Shelge if (uuc->tu_dopen[unit&UMASK]) 13511896Shelge return (EBUSY); 13611896Shelge if (uuwstart++ == 0) 13711896Shelge timeout(uuwatch, (caddr_t)0, hz); 13811896Shelge 13912937Shelge uuc->tu_dopen[unit&UMASK]++; 14012857Shelge uuaddr = (struct uudevice *)ui->ui_addr; 14112857Shelge s = splx(UUIPL); 14211876Shelge /* 14313014Shelge * If the other device on this controller 144*14091Shelge * is already active, no need to initialize 14513014Shelge */ 14613014Shelge if (uuc->tu_dopen[0] && uuc->tu_dopen[1]) 14713156Shelge goto ok; 14813014Shelge 14913014Shelge /* 15011896Shelge * If the unit already initialized, 15111876Shelge * just enable interrupts and return. 15211876Shelge */ 15312937Shelge if (uuc->tu_state == TUS_IDLE) { 15411896Shelge uuaddr->rcs = UUCS_INTR; 15512937Shelge goto ok; 15611876Shelge } 15711876Shelge 15811876Shelge /* 15911876Shelge * Must initialize, reset the cassette 16011876Shelge * and wait for things to settle down. 16111876Shelge */ 16211896Shelge uureset(ctlr); 16311896Shelge sleep((caddr_t)uuc, PZERO+1); 16412857Shelge uitab[ctlr].b_active = NULL; 16512937Shelge if (uuc->tu_state != TUS_IDLE) { 16612937Shelge uuc->tu_state = TUS_INIT1; 16712937Shelge uuc->tu_dopen[unit&UMASK] = 0; 16812937Shelge uuc->tu_rcnt = uuc->tu_wcnt = 0; 16911896Shelge uuaddr->rcs = 0; 17011896Shelge uuaddr->tcs = 0; 17111896Shelge splx(s); 17212937Shelge return (EIO); 17311876Shelge } 17412937Shelge ok: 17511876Shelge splx(s); 17611876Shelge return (0); 17711876Shelge } 17811876Shelge 179*14091Shelge /* 180*14091Shelge * Wait for all outstanding IO on this drive 181*14091Shelge * complete, before closing. If both drives on 182*14091Shelge * this controller are idle, mark the controller 183*14091Shelge * `inactive'. 184*14091Shelge */ 185*14091Shelge 18611896Shelge uuclose(dev, flag) 18711896Shelge dev_t dev; 18811896Shelge int flag; 18911876Shelge { 190*14091Shelge int s, unit = UNIT(dev); 191*14091Shelge register struct uu_softc *uuc = &uu_softc[unit/NDPC]; 192*14091Shelge struct buf *bp, *last = NULL; 193*14091Shelge struct uudevice *uuaddr = (struct uudevice *)uudinfo[unit/NDPC]->ui_addr; 19411876Shelge 195*14091Shelge s = splx(UUIPL); 196*14091Shelge while (uu_pcnt[unit]) 197*14091Shelge sleep(&uu_pcnt[unit], PRIBIO); 198*14091Shelge /* 199*14091Shelge * No more writes are pending, scan the 200*14091Shelge * buffer queue for oustanding reads from 201*14091Shelge * this unit. 202*14091Shelge */ 203*14091Shelge for (bp = uitab[unit/NDPC].b_actf; bp; bp = bp->b_actf) 204*14091Shelge if (bp->b_dev == dev) 205*14091Shelge last = bp; 206*14091Shelge if (last) 207*14091Shelge iowait(last); 208*14091Shelge uuc->tu_dopen[unit&UMASK] = 0; 209*14091Shelge if (!uuc->tu_dopen[0] && !uuc->tu_dopen[1]) { 210*14091Shelge uuc->tu_flag = 0; 211*14091Shelge uuaddr->rcs = 0; 212*14091Shelge /* 213*14091Shelge * Make sure the device is left in a 214*14091Shelge * known state.... 215*14091Shelge */ 216*14091Shelge if (uuc->tu_state != TUS_IDLE) 217*14091Shelge uuc->tu_state = TUS_INIT1; 218*14091Shelge } 219*14091Shelge splx(s); 22011876Shelge } 22111876Shelge 22211896Shelge uureset(ctlr) 22311896Shelge int ctlr; 22411876Shelge { 22513014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 22612332Shelge register struct packet *cmd = &uucmd[ctlr]; 22712857Shelge struct uba_device *ui = uudinfo[ctlr]; 22812857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 22911876Shelge 23012857Shelge uitab[ctlr].b_active++; 23112937Shelge uuc->tu_state = TUS_INIT1; 23212937Shelge uuc->tu_wbptr = uunull; 23312937Shelge uuc->tu_wcnt = sizeof (uunull); 234*14091Shelge uuc->tu_rcnt = 0; 23511896Shelge cmd->pk_flag = TUF_CMD; 23612332Shelge cmd->pk_mcount = sizeof (*cmd) - 4; 23711896Shelge cmd->pk_mod = 0; 23811896Shelge cmd->pk_seq = 0; 23912332Shelge cmd->pk_sw = 0; 24011896Shelge uuaddr->rcs = 0; 24111896Shelge uuaddr->tcs = UUCS_INTR | UUCS_BREAK; 24211896Shelge uuxintr(ctlr); /* start output */ 24311876Shelge } 24411876Shelge 24511876Shelge /* 24611876Shelge * Strategy routine for block I/O 24711876Shelge */ 24811896Shelge uustrategy(bp) 24911876Shelge register struct buf *bp; 25011876Shelge { 25112332Shelge register struct buf *uutab; 25211896Shelge struct uba_device *ui; 253*14091Shelge int s, unit = UNIT(bp->b_dev); 25411876Shelge 255*14091Shelge if ((unit > NUX) || (bp->b_blkno >= NTUBLK)) 25611896Shelge goto bad; 25712857Shelge ui = uudinfo[unit/NDPC]; 25811896Shelge if (ui == 0 || ui->ui_alive == 0) 25911896Shelge goto bad; 26012857Shelge uutab = &uitab[unit/NDPC]; /* one request queue per controller */ 26113156Shelge s = splx(UUIPL); 26212332Shelge if ((bp->b_flags&B_READ) == 0) 263*14091Shelge tu_pee(&uu_pcnt[unit]); 264*14091Shelge bp->b_actf = NULL; 26512332Shelge if (uutab->b_actf == NULL) 26612332Shelge uutab->b_actf = bp; 26712332Shelge else 268*14091Shelge uutab->b_actl->b_actf = bp; 26912332Shelge uutab->b_actl = bp; 27012332Shelge if (uutab->b_active == 0) 27112857Shelge uustart(ui); 27211876Shelge splx(s); 27311896Shelge return; 27411896Shelge 27511896Shelge bad: 27611896Shelge bp->b_flags |= B_ERROR; 27712332Shelge bp->b_error = ENXIO; 27811896Shelge iodone(bp); 27911896Shelge return; 28011876Shelge } 28111876Shelge 28211876Shelge /* 28311876Shelge * Start the transfer 28411876Shelge */ 28512857Shelge uustart(ui) 28612857Shelge register struct uba_device *ui; 28711876Shelge { 28811876Shelge register struct buf *bp; 28913014Shelge register struct uu_softc *uuc; 29011896Shelge struct packet *cmd; 29112857Shelge int ctlr = ui->ui_unit; 29211876Shelge 29312857Shelge if ((bp = uitab[ctlr].b_actf) == NULL) 29411876Shelge return; 29512937Shelge uuc = &uu_softc[ctlr]; 29612937Shelge if (uuc->tu_state != TUS_IDLE) { 29712332Shelge uureset(ctlr); 29811876Shelge return; 29911876Shelge } 300*14091Shelge cmd = &uucmd[ctlr]; 30112857Shelge uitab[ctlr].b_active++; 30212937Shelge uitab[ctlr].b_errcnt = 0; 30312937Shelge uuc->tu_addr = bp->b_un.b_addr; 30412937Shelge uuc->tu_count = cmd->pk_count = bp->b_bcount; 30512937Shelge cmd->pk_block = bp->b_blkno; 30612937Shelge if (bp->b_flags&B_READ) { 30712937Shelge cmd->pk_op = TUOP_READ; 30812937Shelge cmd->pk_mod = 0; 30912937Shelge uuc->tu_state = TUS_SENDR; 31012937Shelge } else { 31112937Shelge cmd->pk_op = TUOP_WRITE; 31212937Shelge cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0; 31312937Shelge uuc->tu_state = TUS_SENDW; 31412937Shelge } 315*14091Shelge cmd->pk_unit = UNIT(bp->b_dev)&UMASK; 31612332Shelge cmd->pk_sw = 0; 31711896Shelge cmd->pk_chksum = 31812937Shelge tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount); 31912937Shelge uuc->tu_wbptr = (u_char *)cmd; 32012937Shelge uuc->tu_wcnt = sizeof (*cmd); 32112332Shelge uuxintr(ctlr); 32211876Shelge } 32311876Shelge 32411876Shelge /* 325*14091Shelge * TU58 receiver interrupt, handles whatever condition the 326*14091Shelge * pseudo DMA routine in locore is unable to handle, 327*14091Shelge * or, if UUDMA is undefined, handle all receiver interrupt 328*14091Shelge * processing. 32911876Shelge */ 33012332Shelge uurintr(ctlr) 33112332Shelge int ctlr; 33211876Shelge { 33312857Shelge struct uba_device *ui = uudinfo[ctlr]; 33413014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 33512857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 33612857Shelge register struct buf *uutab = &uitab[ctlr]; 33712332Shelge struct packet *data, *cmd; 33812937Shelge struct buf *bp; 33912937Shelge int c, unit; 34011876Shelge 34112857Shelge c = uuaddr->rdb; 34212937Shelge data = &uudata[ctlr]; 34313014Shelge cmd = &uucmd[ctlr]; 34413014Shelge #if !defined(UUDMA) 34513014Shelge if (c & UURDB_ERROR) 34613014Shelge uuc->tu_state = TUS_RCVERR; 34713014Shelge else { 34813014Shelge if (uuc->tu_rcnt) { 34913014Shelge *uuc->tu_rbptr++ = c; 35013014Shelge if (--uuc->tu_rcnt) 35113014Shelge return; 35213014Shelge } 35313014Shelge } 35413014Shelge #endif 35513014Shelge 35613014Shelge /* 35713014Shelge * Switch on the tu_state of the transfer. 35813014Shelge */ 35913014Shelge switch(uuc->tu_state) { 36013014Shelge 36113014Shelge /* 36213014Shelge * A data error occured in uudma 36313014Shelge * (either overrun or break) 36413014Shelge */ 36513014Shelge case TUS_RCVERR: 36613156Shelge if ((c & UURDB_ORUN) == 0) 36713156Shelge printf("uu%d: break received, transfer restarted\n", 36813834Ssam data->pk_unit); 369*14091Shelge #ifdef UUDEBUG 370*14091Shelge else 371*14091Shelge printf("uu%d: data overrun, recovered\n", 372*14091Shelge data->pk_unit); 373*14091Shelge #endif 37413156Shelge uuc->tu_serrs++; 37513014Shelge uu_restart(ctlr, ui); 37613014Shelge break; 37711876Shelge 37811876Shelge /* 37911876Shelge * If we get an unexpected "continue", 38011876Shelge * start all over again... 38111876Shelge */ 38212937Shelge case TUS_INIT2: 38312937Shelge uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; 38412937Shelge uuc->tu_flag = 0; 38512332Shelge wakeup((caddr_t)uuc); 38612857Shelge uustart(ui); 38711876Shelge break; 38811876Shelge 38911876Shelge /* 39011876Shelge * Only transition from this state 39111876Shelge * is on a "continue", so if we don't 39211876Shelge * get it, reset the world. 39311876Shelge */ 39412937Shelge case TUS_WAIT: /* waiting for continue */ 39512332Shelge switch(c) { 39612332Shelge case TUF_CONT: /* got the expected continue */ 39712937Shelge uuc->tu_flag = 0; 39812332Shelge data->pk_flag = TUF_DATA; 39912937Shelge data->pk_mcount = MIN(128, uuc->tu_count); 40012332Shelge data->pk_chksum = 40112937Shelge tuchk(*((short *)data), (caddr_t)uuc->tu_addr, 40212332Shelge (int)data->pk_mcount); 40312937Shelge uuc->tu_state = TUS_SENDH; 40412937Shelge uuc->tu_wbptr = (u_char *)data; 40512937Shelge uuc->tu_wcnt = 2; 40612857Shelge uuxintr(ctlr); 40711876Shelge break; 40812332Shelge 40912332Shelge case TUF_CMD: /* sending us an END packet...error */ 41012937Shelge uuc->tu_state = TUS_GET; 41112937Shelge uuc->tu_rbptr = (u_char *)data; 41213014Shelge uuc->tu_rcnt = sizeof (*data) - 1; 41312937Shelge uuc->tu_flag = 1; 41412332Shelge uuaddr->tcs = 0; 41513014Shelge *uuc->tu_rbptr++ = c & UUDB_DMASK; 41613014Shelge break; 41712332Shelge 41812332Shelge case TUF_INITF: 41912857Shelge uureset(ctlr); 42012332Shelge break; 42112332Shelge 42212332Shelge default: /* something random...bad news */ 42312937Shelge uuc->tu_state = TUS_INIT1; 42412332Shelge break; 42511876Shelge } 42611876Shelge break; 42711876Shelge 42812937Shelge case TUS_SENDW: 42912937Shelge if (c != TUF_CONT && c != TUF_INITF) 43011876Shelge goto bad; 43113014Shelge uu_restart(ctlr, ui); 43211876Shelge break; 43311876Shelge 43411876Shelge /* 43511876Shelge * Got header, now get data; amount to 43611896Shelge * fetch is included in packet. 43713014Shelge * (data packets are handled entirely 43813014Shelge * in uudma) 43911876Shelge */ 44012937Shelge case TUS_GETH: 44113156Shelge #ifndef UUDMA 44213156Shelge if (data->pk_flag == TUF_DATA) 44313156Shelge uuc->tu_rbptr = (u_char *)uuc->tu_addr; 44413156Shelge #endif 44512937Shelge uuc->tu_rcnt = data->pk_mcount; 44612937Shelge uuc->tu_state = TUS_GETD; 44711876Shelge break; 44811876Shelge 44911876Shelge /* 45011876Shelge * Got the data, now fetch the checksum. 45111876Shelge */ 45212937Shelge case TUS_GETD: 45312937Shelge uuc->tu_rbptr = (u_char *)&data->pk_chksum; 45412937Shelge uuc->tu_rcnt = sizeof (data->pk_chksum); 45512937Shelge uuc->tu_state = TUS_GETC; 45611876Shelge break; 45711876Shelge 45812937Shelge case TUS_GETC: 45911876Shelge /* got entire packet */ 46012332Shelge if (data->pk_chksum != 46112937Shelge tuchk(*((short *)data), (u_short *) 46213014Shelge (data->pk_flag == TUF_DATA ? 46313156Shelge (u_short *) uuc->tu_addr : (u_short *)&data->pk_op), 46412332Shelge (int)data->pk_mcount)) 46513014Shelge case TUS_CHKERR: 46612937Shelge uuc->tu_cerrs++; 46713014Shelge case TUS_GET: 46812332Shelge if (data->pk_flag == TUF_DATA) { 46911876Shelge /* data packet, advance to next */ 47012937Shelge uuc->tu_addr += data->pk_mcount; 47112937Shelge uuc->tu_count -= data->pk_mcount; 47212937Shelge uuc->tu_state = TUS_GETH; 47312937Shelge uuc->tu_rbptr = (u_char *)data; /* next packet */ 47412937Shelge uuc->tu_rcnt = 2; 47512332Shelge } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { 47611876Shelge /* end packet, idle and reenable transmitter */ 47712937Shelge uuc->tu_state = TUS_IDLE; 47812937Shelge uuc->tu_flag = 0; 47912937Shelge uuaddr->tcs = UUCS_INTR; 48012937Shelge if ((bp = uutab->b_actf) == NULL) { 48113156Shelge printf("uu%d: no bp, active %d\n", 48213834Ssam data->pk_unit, uitab[ctlr].b_active); 48312857Shelge uustart(ui); 48411876Shelge return; 48511876Shelge } 486*14091Shelge unit = UNIT(bp->b_dev); 48712332Shelge if (data->pk_mod > 1) { /* hard error */ 48813014Shelge printf("uu%d: hard error bn%d,", unit, 48913834Ssam bp->b_blkno); 490*14091Shelge printf(" pk_mod 0%o\n", data->pk_mod&0xff); 49111876Shelge bp->b_flags |= B_ERROR; 49212937Shelge uuc->tu_herrs++; 493*14091Shelge } else if (data->pk_mod) /* soft error */ 49412937Shelge uuc->tu_serrs++; 49512332Shelge uutab->b_active = NULL; 496*14091Shelge uutab->b_actf = bp->b_actf; 49712937Shelge bp->b_resid = uuc->tu_count; 49811876Shelge if ((bp->b_flags&B_READ) == 0) 499*14091Shelge tu_vee(&uu_pcnt[unit]); 50011876Shelge iodone(bp); 50112857Shelge uustart(ui); 50211876Shelge } else { 50313156Shelge /* 50413156Shelge * Neither data nor end: data was lost 505*14091Shelge * somehow, flush and restart the transfer. 50613156Shelge */ 507*14091Shelge uuaddr->rcs = 0; 50813014Shelge uu_restart(ctlr, ui); 50913156Shelge uuc->tu_serrs++; 51011876Shelge } 51111876Shelge break; 51211876Shelge 51312937Shelge case TUS_IDLE: 51412937Shelge case TUS_INIT1: 51511876Shelge break; 51611876Shelge 51711876Shelge default: 51811876Shelge bad: 51911876Shelge if (c == TUF_INITF) { 52013156Shelge printf("uu%d protocol error, state=", data->pk_unit); 52112937Shelge printstate(uuc->tu_state); 52211876Shelge printf(", op=%x, cnt=%d, block=%d\n", 52312332Shelge cmd->pk_op, cmd->pk_count, cmd->pk_block); 52412332Shelge uutab->b_active = NULL; 52512332Shelge if (bp = uutab->b_actf) { 52611876Shelge bp->b_flags |= B_ERROR; 527*14091Shelge uutab->b_actf = bp->b_actf; 52811876Shelge if ((bp->b_flags&B_READ) == 0) 529*14091Shelge tu_vee(&uu_pcnt[unit]); 53011876Shelge iodone(bp); 53111876Shelge } 53212937Shelge uuc->tu_state = TUS_INIT1; 53311876Shelge } else { 53412332Shelge printf("uu%d receive state error, state=", 53513156Shelge data->pk_unit); 53612937Shelge printstate(uuc->tu_state); 53713014Shelge printf(", byte=%x\n", c & 0xff); 53811876Shelge #ifdef notdef 53912937Shelge uuc->tu_state = TUS_INIT1; 54011876Shelge #endif 54112332Shelge wakeup((caddr_t)uuc); 54211876Shelge } 54311876Shelge } 54411876Shelge } 54511876Shelge 54612937Shelge 54712937Shelge /* 54811876Shelge * TU58 transmitter interrupt 54911876Shelge */ 55012332Shelge uuxintr(ctlr) 55112332Shelge int ctlr; 55211876Shelge { 55313014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 55412857Shelge register struct uudevice *uuaddr; 55512332Shelge register struct packet *data; 55612857Shelge struct uba_device *ui = uudinfo[ctlr]; 55712332Shelge int c; 55811876Shelge 55912857Shelge data = &uudata[ctlr]; 56012857Shelge uuaddr = (struct uudevice *) ui->ui_addr; 56111876Shelge top: 562*14091Shelge if (uuc->tu_wcnt > 0) { 56311876Shelge /* still stuff to send, send one byte */ 56412332Shelge while ((uuaddr->tcs & UUCS_READY) == 0) 56511876Shelge ; 56612937Shelge uuaddr->tdb = *uuc->tu_wbptr++; 56712937Shelge uuc->tu_wcnt--; 56811876Shelge return; 56911876Shelge } 57011876Shelge 57111876Shelge /* 57211876Shelge * Last message byte was sent out. 57312937Shelge * Switch on tu_state of transfer. 57411876Shelge */ 57512937Shelge switch(uuc->tu_state) { 57611876Shelge 57711876Shelge /* 57811876Shelge * Two nulls have been sent, remove break, and send inits 57911876Shelge */ 58012937Shelge case TUS_INIT1: 581*14091Shelge uuc->tu_flag = 0; 58212332Shelge uuaddr->tcs = UUCS_INTR; 58312937Shelge uuc->tu_state = TUS_INIT2; 58412937Shelge uuc->tu_wbptr = uuinit; 58512937Shelge uuc->tu_wcnt = sizeof (uuinit); 58611876Shelge goto top; 58711876Shelge 58811876Shelge /* 58911876Shelge * Inits have been sent, wait for a continue msg. 59011876Shelge */ 59112937Shelge case TUS_INIT2: 59212857Shelge c = uuaddr->rdb; /* prevent overrun error */ 59312332Shelge uuaddr->rcs = UUCS_INTR; 59412937Shelge uuc->tu_flag = 1; 59511876Shelge break; 59611876Shelge 59711876Shelge /* 59811876Shelge * Read cmd packet sent, get ready for data 59911876Shelge */ 60012937Shelge case TUS_SENDR: 60112937Shelge uuc->tu_state = TUS_GETH; 60212937Shelge uuc->tu_rbptr = (u_char *)data; 60312937Shelge uuc->tu_rcnt = 2; 60412937Shelge uuc->tu_flag = 1; 605*14091Shelge uuaddr->tcs = 0; 60612937Shelge uuaddr->rcs = UUCS_INTR; 60711876Shelge break; 60811876Shelge 60911876Shelge /* 61011876Shelge * Write cmd packet sent, wait for continue 61111876Shelge */ 61212937Shelge case TUS_SENDW: 61312937Shelge uuc->tu_state = TUS_WAIT; 61412937Shelge uuc->tu_flag = 1; 61512332Shelge if ((uuaddr->rcs&UUCS_INTR) == 0) { 61611876Shelge printf("NO IE\n"); 61712332Shelge uuaddr->rcs = UUCS_INTR; 61811876Shelge } 61911876Shelge break; 62011876Shelge 62111876Shelge /* 62211876Shelge * Header sent, send data. 62311876Shelge */ 62412937Shelge case TUS_SENDH: 62512937Shelge uuc->tu_state = TUS_SENDD; 62612937Shelge uuc->tu_wbptr = (u_char *)uuc->tu_addr; 62712937Shelge uuc->tu_wcnt = data->pk_mcount; 62811876Shelge goto top; 62911876Shelge 63011876Shelge /* 63111876Shelge * Data sent, follow with checksum. 63211876Shelge */ 63312937Shelge case TUS_SENDD: 63412937Shelge uuc->tu_state = TUS_SENDC; 63512937Shelge uuc->tu_wbptr = (u_char *)&data->pk_chksum; 636*14091Shelge uuc->tu_wcnt = 2; 63711876Shelge goto top; 63811876Shelge 63911876Shelge /* 64011876Shelge * Checksum sent, wait for continue. 64111876Shelge */ 64212937Shelge case TUS_SENDC: 64311876Shelge /* 64412937Shelge * Update buffer address and count. 64511876Shelge */ 64612937Shelge uuc->tu_addr += data->pk_mcount; 64712937Shelge uuc->tu_count -= data->pk_mcount; 648*14091Shelge if (uuc->tu_count > 0) { 64912937Shelge uuc->tu_state = TUS_WAIT; 65012937Shelge uuc->tu_flag = 1; 65111876Shelge break; 65211876Shelge } 65311876Shelge 65411876Shelge /* 65511876Shelge * End of transmission, get ready for end packet. 65611876Shelge */ 65712937Shelge uuc->tu_state = TUS_GET; 65812937Shelge uuc->tu_rbptr = (u_char *)data; 65912937Shelge uuc->tu_rcnt = sizeof (*data); 66012937Shelge uuc->tu_flag = 1; 661*14091Shelge uuaddr->tcs = 0; 66211876Shelge break; 66311876Shelge 66411876Shelge /* 66512332Shelge * Random interrupt 66611876Shelge */ 66713156Shelge case TUS_IDLE: /* stray interrupt? */ 66813156Shelge 66911876Shelge default: 67011876Shelge break; 67111876Shelge } 67212937Shelge } 67312937Shelge 67412937Shelge uuwatch() 67512937Shelge { 67613014Shelge register struct uu_softc *uuc; 67712937Shelge register struct uudevice *uuaddr; 67812937Shelge struct uba_device *ui; 67912937Shelge struct buf *bp, *uutab; 68012937Shelge int s, ctlr, active = 0; 68112937Shelge 68212937Shelge for (ctlr=0; ctlr<NUU; ctlr++) { 68312937Shelge int i; 68412937Shelge 68512937Shelge uuc = &uu_softc[ctlr]; 686*14091Shelge 687*14091Shelge if (uuc->tu_dopen[0] || uuc->tu_dopen[1]) 688*14091Shelge active++; 689*14091Shelge if (uuc->tu_flag == 0) 690*14091Shelge /* 691*14091Shelge * If no read is in progress 692*14091Shelge * just skip 693*14091Shelge */ 694*14091Shelge continue; 695*14091Shelge 69612937Shelge ui = uudinfo[ctlr]; 69712937Shelge uuaddr = (struct uudevice *)ui->ui_addr; 69812937Shelge uutab = &uitab[ctlr]; 699*14091Shelge if (uuc->tu_flag++ < 40) 70012937Shelge continue; 70113156Shelge printf("uu%d: read stalled\n", uudata[ctlr].pk_unit); 702*14091Shelge #ifdef UUDEBUG 70312937Shelge printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt, 70413156Shelge uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr, 70513156Shelge uuc->tu_count); 70613834Ssam #endif 707*14091Shelge s = splx(UUIPL); 70812937Shelge uuc->tu_flag = 0; 70912937Shelge i = uuaddr->rdb; /* dummy */ 71012937Shelge uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ 71112937Shelge uuaddr->tcs = UUCS_INTR; 71212937Shelge uuc->tu_state = TUS_IDLE; 71312937Shelge if (!uutab->b_active) { 71412937Shelge wakeup((caddr_t)uuc); 71512937Shelge goto retry; 71612937Shelge } 71712937Shelge if (++uutab->b_errcnt <= 1) { 71812937Shelge uustart(ui); 71912937Shelge goto retry; 72012937Shelge } 72112937Shelge if (bp = uutab->b_actf) { 72212937Shelge bp->b_flags |= B_ERROR; 72312937Shelge if ((bp->b_flags&B_READ) == 0) 724*14091Shelge tu_vee(&uu_pcnt[UNIT(bp->b_dev)]); 72512937Shelge iodone(bp); 72612937Shelge } 72712937Shelge retry: 72812937Shelge (void) splx(s); 72911876Shelge } 73012937Shelge if (active) 73112937Shelge timeout(uuwatch, (caddr_t)0, hz); 73212937Shelge else 73312937Shelge uuwstart = 0; 73412937Shelge return; 73511876Shelge } 73611876Shelge 73712937Shelge #if !defined(VAX750) && !defined(VAX730) 73811876Shelge /* 73911876Shelge * Compute checksum TU58 fashion 74011876Shelge */ 74111876Shelge #ifdef lint 74212937Shelge tuchk(word, cp, n) 74311876Shelge register word; 74411876Shelge register unsigned short *cp; 74511876Shelge int n; 74611876Shelge { 74711876Shelge register int c = n >> 1; 74811876Shelge register long temp; 74911876Shelge 75011876Shelge do { 75111876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 75211876Shelge word += temp; 75311876Shelge } while (--c > 0); 75411876Shelge if (n & 1) 75511876Shelge word += *(unsigned char *)cp; 75611876Shelge while (word & 0xffff0000) 75711876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 75811876Shelge return (word); 75911876Shelge } 76011876Shelge #else 76112937Shelge tuchk(word0, wp, n) 76211896Shelge register int word0; /* r11 */ 76311896Shelge register char *wp; /* r10 */ 76411896Shelge register int n; /* r9 */ 76511876Shelge { 76611876Shelge asm("loop:"); 76711896Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 76811896Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 76911876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 77011896Shelge asm(" blbc r9,ok"); /* odd byte count? */ 77111896Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 77211896Shelge asm(" addw2 r10,r11"); /* add it in */ 77311896Shelge asm(" adwc $0,r11"); /* and the carry */ 77411876Shelge asm("ok:"); 77511896Shelge asm(" movl r11,r0"); /* return sum */ 77611876Shelge } 77711876Shelge #endif 77811876Shelge 779*14091Shelge /* 780*14091Shelge * Make sure this incredibly slow device 781*14091Shelge * doesn't eat up all the buffers in the 782*14091Shelge * system by putting the requesting process 783*14091Shelge * (remember: this device is 'single-user') 784*14091Shelge * to sleep if the write-behind queue grows 785*14091Shelge * larger than NUUQ. 786*14091Shelge */ 78712937Shelge tu_pee(cp) 788*14091Shelge char *cp; 78912332Shelge { 79012332Shelge register int s; 79112332Shelge 79212857Shelge s = splx(UUIPL); 793*14091Shelge if (++(*cp) > NUUQ) 79412332Shelge sleep(cp, PRIBIO); 79512332Shelge splx(s); 79612332Shelge } 79712332Shelge 79812937Shelge tu_vee(cp) 799*14091Shelge char *cp; 80012332Shelge { 80112332Shelge register int s; 80212332Shelge 80312857Shelge s = splx(UUIPL); 804*14091Shelge if (--(*cp) <= NUUQ) 80512332Shelge wakeup(cp); 80611876Shelge splx(s); 80711876Shelge } 80811876Shelge #endif 80912332Shelge 81012937Shelge uuioctl(dev, cmd, data, flag) 81112937Shelge dev_t dev; 81212937Shelge caddr_t data; 81312937Shelge { 81412937Shelge /* 81513156Shelge * add code to wind/rewind cassette here 81612937Shelge */ 81712937Shelge return (ENXIO); 81812937Shelge } 81912937Shelge 82013014Shelge uu_restart(ctlr, ui) 82113014Shelge int ctlr; 82213014Shelge struct uba_device *ui; 82313014Shelge { 82413014Shelge uureset(ctlr); 82513014Shelge timeout(uustart, (caddr_t)ui, hz * 3); 82613014Shelge } 827*14091Shelge 828*14091Shelge #endif 829