1*13834Ssam /* uu.c 4.8 83/07/07 */ 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 1013156Shelge * common errors. It is assumed that the 1111876Shelge * TU58 will follow the RSP protocol exactly, very few protocol 1211896Shelge * errors are checked for. 1311876Shelge */ 1411896Shelge 1512332Shelge #include "../machine/pte.h" 1611896Shelge 1711876Shelge #include "../h/param.h" 1811876Shelge #include "../h/systm.h" 1911876Shelge #include "../h/buf.h" 2011876Shelge #include "../h/conf.h" 2112332Shelge #include "../h/time.h" 2211896Shelge #include "../h/kernel.h" 2311896Shelge #include "../h/errno.h" 2411896Shelge #include "../h/file.h" 2511876Shelge 2611876Shelge #include "../vax/cpu.h" 2712332Shelge #include "../vax/nexus.h" 2812937Shelge #include "../vax/rsp.h" 2912332Shelge 3011896Shelge #include "../vaxuba/ubavar.h" 3111896Shelge #include "../vaxuba/ubareg.h" 3211896Shelge #include "../vaxuba/uureg.h" 3311876Shelge 3411876Shelge #define NTUBLK 512 /* number of blocks on a TU58 cassette */ 3512857Shelge #define WRV 01 /* bit in minor dev => write w. read verify */ 3612332Shelge #define NDPC 02 /* drives per controller */ 3712857Shelge #define NUX NDPC * NUU /* number of drives */ 3812332Shelge #define NTUQ 02 /* # of block which can be queued up */ 3912857Shelge #define UMASK 01 /* unit number mask */ 4012937Shelge #define UUIPL 0x14 /* ipl level to use */ 4111876Shelge 4212857Shelge struct packet uucmd[NUU]; /* a command sent to the TU58 */ 4312857Shelge struct packet uudata[NUU]; /* a command or data returned from TU58 */ 4412857Shelge struct buf uitab[NUU]; /* buffer queue headers */ 4511876Shelge 4611876Shelge /* 4712937Shelge * Driver soft carrier structure 4811876Shelge */ 4912937Shelge struct uu_softc { 5012937Shelge u_char *tu_rbptr; /* pointer to buffer for read */ 5112937Shelge int tu_rcnt; /* how much to read */ 5212937Shelge u_char *tu_wbptr; /* pointer to buffer for write */ 5312937Shelge int tu_wcnt; /* how much to write */ 5412937Shelge int tu_state; /* current state of tansfer operation */ 5512937Shelge int tu_flag; /* read in progress flag */ 5612937Shelge char *tu_addr; /* real buffer data address */ 5712937Shelge int tu_count; /* real requested count */ 5812937Shelge int tu_serrs; /* count of soft errors */ 5912937Shelge int tu_cerrs; /* count of checksum errors */ 6012937Shelge int tu_herrs; /* count of hard errors */ 6112937Shelge char tu_dopen[2]; /* drive is open */ 6213014Shelge } uu_softc[NUU]; 6311876Shelge 6412937Shelge #if defined(VAX750) || defined(VAX730) 6512937Shelge extern char *tustates[]; 6612937Shelge #else 6712937Shelge char *tustates[TUS_NSTATES] = { 6811876Shelge "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", 6913014Shelge "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR" 7011876Shelge }; 7112937Shelge #endif 7212332Shelge 7312857Shelge #define UNIT(dev) (minor(dev)>>1) 7411876Shelge 7513156Shelge u_char uunull[4] = { 0, 0, 0, 0 }; /* nulls to send for initialization */ 7611896Shelge u_char uuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ 7711876Shelge 7811896Shelge struct uba_device *uudinfo[NUU]; 7911896Shelge 8012857Shelge int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch(); 8112857Shelge u_short uustd[] = { 0176500 }; 8212857Shelge struct uba_driver uudriver = 8312857Shelge { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo }; 8411896Shelge 8511896Shelge int uuwstart; 8612937Shelge static char pcnt[NUX]; /* pee/vee counters, one per drive */ 8711896Shelge 8811876Shelge /*ARGSUSED*/ 8911896Shelge uuprobe(reg) 9011896Shelge caddr_t reg; 9111876Shelge { 9211896Shelge register int br, cvec; /* value result */ 9311896Shelge struct uudevice *uuaddr = (struct uudevice *)reg; 9411876Shelge 9511876Shelge #ifdef lint 9611896Shelge br = 0; cvec = br; br = cvec; 9711896Shelge uurintr(0); uuxintr(0); 9811876Shelge #endif 9912857Shelge uuaddr->tcs = UUCS_INTR; 10012857Shelge DELAY(1000); 10112857Shelge uuaddr->tcs = 0; 10212857Shelge cvec -= 4; /* since we are using the xmitter intrpt */ 10311896Shelge return(sizeof (*uuaddr)); 10411896Shelge } 10511896Shelge 10611896Shelge uuattach(ui) 10712857Shelge register struct uba_device *ui; 10811896Shelge { 10911896Shelge } 11011896Shelge 11111896Shelge /*ARGSUSED1*/ 11211896Shelge uuopen(dev, flag) 11311896Shelge dev_t dev; 11411896Shelge int flag; 11511896Shelge { 11611896Shelge register struct uba_device *ui; 11713014Shelge register struct uu_softc *uuc; 11811896Shelge register struct uudevice *uuaddr; 11912332Shelge int ctlr, unit = UNIT(dev), s; 12011896Shelge 12112857Shelge ctlr = unit / NDPC; 12212857Shelge if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0) 12311876Shelge return (ENXIO); 12412937Shelge uuc = &uu_softc[ctlr]; 12512937Shelge if (uuc->tu_dopen[unit&UMASK]) 12611896Shelge return (EBUSY); 12711896Shelge if (uuwstart++ == 0) 12811896Shelge timeout(uuwatch, (caddr_t)0, hz); 12911896Shelge 13012937Shelge uuc->tu_dopen[unit&UMASK]++; 13112857Shelge uuaddr = (struct uudevice *)ui->ui_addr; 13212857Shelge s = splx(UUIPL); 13311876Shelge /* 13413014Shelge * If the other device on this controller 13513014Shelge * is already active, just return 13613014Shelge */ 13713014Shelge if (uuc->tu_dopen[0] && uuc->tu_dopen[1]) 13813156Shelge goto ok; 13913014Shelge 14013014Shelge /* 14111896Shelge * If the unit already initialized, 14211876Shelge * just enable interrupts and return. 14311876Shelge */ 14412937Shelge if (uuc->tu_state == TUS_IDLE) { 14511896Shelge uuaddr->rcs = UUCS_INTR; 14612937Shelge goto ok; 14711876Shelge } 14811876Shelge 14911876Shelge /* 15011876Shelge * Must initialize, reset the cassette 15111876Shelge * and wait for things to settle down. 15211876Shelge */ 15311896Shelge uureset(ctlr); 15411896Shelge sleep((caddr_t)uuc, PZERO+1); 15512857Shelge uitab[ctlr].b_active = NULL; 15612937Shelge if (uuc->tu_state != TUS_IDLE) { 15712937Shelge uuc->tu_state = TUS_INIT1; 15812937Shelge uuc->tu_dopen[unit&UMASK] = 0; 15912937Shelge uuc->tu_rcnt = uuc->tu_wcnt = 0; 16011896Shelge uuaddr->rcs = 0; 16111896Shelge uuaddr->tcs = 0; 16211896Shelge splx(s); 16312937Shelge return (EIO); 16411876Shelge } 16512937Shelge ok: 16611876Shelge splx(s); 16711876Shelge return (0); 16811876Shelge } 16911876Shelge 17011896Shelge uuclose(dev, flag) 17111896Shelge dev_t dev; 17211896Shelge int flag; 17311876Shelge { 17413014Shelge register struct uu_softc *uuc; 17511876Shelge 17613156Shelge uuc = &uu_softc[UNIT(dev)/NDPC]; 17713156Shelge uuc->tu_dopen[UNIT(dev)&UMASK] = 0; 17811876Shelge } 17911876Shelge 18011896Shelge uureset(ctlr) 18111896Shelge int ctlr; 18211876Shelge { 18313014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 18412332Shelge register struct packet *cmd = &uucmd[ctlr]; 18512857Shelge struct uba_device *ui = uudinfo[ctlr]; 18612857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 18711876Shelge 18812857Shelge uitab[ctlr].b_active++; 18912937Shelge uuc->tu_state = TUS_INIT1; 19012937Shelge uuc->tu_wbptr = uunull; 19112937Shelge uuc->tu_wcnt = sizeof (uunull); 19211896Shelge cmd->pk_flag = TUF_CMD; 19312332Shelge cmd->pk_mcount = sizeof (*cmd) - 4; 19411896Shelge cmd->pk_mod = 0; 19511896Shelge cmd->pk_seq = 0; 19612332Shelge cmd->pk_sw = 0; 19711896Shelge uuaddr->rcs = 0; 19811896Shelge uuaddr->tcs = UUCS_INTR | UUCS_BREAK; 19911896Shelge uuxintr(ctlr); /* start output */ 20011876Shelge } 20111876Shelge 20211876Shelge /* 20311876Shelge * Strategy routine for block I/O 20411876Shelge */ 20511896Shelge uustrategy(bp) 20611876Shelge register struct buf *bp; 20711876Shelge { 20812332Shelge register struct buf *uutab; 20911896Shelge struct uba_device *ui; 21012857Shelge int s, unit = UNIT(minor(bp->b_dev)); 21111876Shelge 21212857Shelge if (unit > NUX) 21311896Shelge goto bad; 21411896Shelge if (bp->b_blkno >= NTUBLK) 21511896Shelge goto bad; 21612857Shelge ui = uudinfo[unit/NDPC]; 21711896Shelge if (ui == 0 || ui->ui_alive == 0) 21811896Shelge goto bad; 21912857Shelge uutab = &uitab[unit/NDPC]; /* one request queue per controller */ 22013156Shelge s = splx(UUIPL); 22112332Shelge if ((bp->b_flags&B_READ) == 0) 22212937Shelge tu_pee(&pcnt[unit]); 22312937Shelge bp->av_forw = NULL; 22412332Shelge if (uutab->b_actf == NULL) 22512332Shelge uutab->b_actf = bp; 22612332Shelge else 22712937Shelge uutab->b_actl->av_forw = bp; 22812332Shelge uutab->b_actl = bp; 22912332Shelge if (uutab->b_active == 0) 23012857Shelge uustart(ui); 23111876Shelge splx(s); 23211896Shelge return; 23311896Shelge 23411896Shelge bad: 23511896Shelge bp->b_flags |= B_ERROR; 23612332Shelge bp->b_error = ENXIO; 23711896Shelge iodone(bp); 23811896Shelge return; 23911876Shelge } 24011876Shelge 24111876Shelge /* 24211876Shelge * Start the transfer 24311876Shelge */ 24412857Shelge uustart(ui) 24512857Shelge register struct uba_device *ui; 24611876Shelge { 24711876Shelge register struct buf *bp; 24813014Shelge register struct uu_softc *uuc; 24911896Shelge struct packet *cmd; 25012857Shelge int ctlr = ui->ui_unit; 25111876Shelge 25212857Shelge if ((bp = uitab[ctlr].b_actf) == NULL) 25311876Shelge return; 25412937Shelge uuc = &uu_softc[ctlr]; 25512332Shelge cmd = &uucmd[ctlr]; 25612937Shelge if (uuc->tu_state != TUS_IDLE) { 25712332Shelge uureset(ctlr); 25811876Shelge return; 25911876Shelge } 26012857Shelge uitab[ctlr].b_active++; 26112937Shelge uitab[ctlr].b_errcnt = 0; 26212937Shelge uuc->tu_addr = bp->b_un.b_addr; 26312937Shelge uuc->tu_count = cmd->pk_count = bp->b_bcount; 26412937Shelge cmd->pk_block = bp->b_blkno; 26512937Shelge if (bp->b_flags&B_READ) { 26612937Shelge cmd->pk_op = TUOP_READ; 26712937Shelge cmd->pk_mod = 0; 26812937Shelge uuc->tu_state = TUS_SENDR; 26912937Shelge } else { 27012937Shelge cmd->pk_op = TUOP_WRITE; 27112937Shelge cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0; 27212937Shelge uuc->tu_state = TUS_SENDW; 27312937Shelge } 27412857Shelge cmd->pk_unit = UNIT(minor(bp->b_dev)); 27512332Shelge cmd->pk_sw = 0; 27611896Shelge cmd->pk_chksum = 27712937Shelge tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount); 27812937Shelge uuc->tu_wbptr = (u_char *)cmd; 27912937Shelge uuc->tu_wcnt = sizeof (*cmd); 28012332Shelge uuxintr(ctlr); 28111876Shelge } 28211876Shelge 28311876Shelge /* 28413014Shelge * TU58 receiver interrupt, 28513014Shelge * handles whatever condition the 28613014Shelge * pseudo DMA routine in locore is 28713014Shelge * unable to handle, or, if UUDMA is 28813014Shelge * undefined, handle all receiver interrupt 28913014Shelge * processing 29011876Shelge */ 29112332Shelge uurintr(ctlr) 29212332Shelge int ctlr; 29311876Shelge { 29412857Shelge struct uba_device *ui = uudinfo[ctlr]; 29513014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 29612857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 29712857Shelge register struct buf *uutab = &uitab[ctlr]; 29812332Shelge struct packet *data, *cmd; 29912937Shelge struct buf *bp; 30012937Shelge int c, unit; 30111876Shelge 30212857Shelge c = uuaddr->rdb; 30312937Shelge data = &uudata[ctlr]; 30413014Shelge cmd = &uucmd[ctlr]; 30513014Shelge #if !defined(UUDMA) 30613014Shelge if (c & UURDB_ERROR) 30713014Shelge uuc->tu_state = TUS_RCVERR; 30813014Shelge else { 30913014Shelge if (uuc->tu_rcnt) { 31013014Shelge *uuc->tu_rbptr++ = c; 31113014Shelge if (--uuc->tu_rcnt) 31213014Shelge return; 31313014Shelge } 31413014Shelge } 31513014Shelge #endif 31613014Shelge 31713014Shelge /* 31813014Shelge * Switch on the tu_state of the transfer. 31913014Shelge */ 32013014Shelge switch(uuc->tu_state) { 32113014Shelge 32213014Shelge /* 32313014Shelge * A data error occured in uudma 32413014Shelge * (either overrun or break) 32513014Shelge */ 32613014Shelge case TUS_RCVERR: 32713156Shelge if ((c & UURDB_ORUN) == 0) 32813156Shelge printf("uu%d: break received, transfer restarted\n", 329*13834Ssam data->pk_unit); 33013156Shelge uuc->tu_serrs++; 33113014Shelge uu_restart(ctlr, ui); 33213014Shelge break; 33311876Shelge 33411876Shelge /* 33511876Shelge * If we get an unexpected "continue", 33611876Shelge * start all over again... 33711876Shelge */ 33812937Shelge case TUS_INIT2: 33912937Shelge uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; 34012937Shelge uuc->tu_flag = 0; 34112332Shelge wakeup((caddr_t)uuc); 34212857Shelge uustart(ui); 34311876Shelge break; 34411876Shelge 34511876Shelge /* 34611876Shelge * Only transition from this state 34711876Shelge * is on a "continue", so if we don't 34811876Shelge * get it, reset the world. 34911876Shelge */ 35012937Shelge case TUS_WAIT: /* waiting for continue */ 35112332Shelge switch(c) { 35212332Shelge case TUF_CONT: /* got the expected continue */ 35312937Shelge uuc->tu_flag = 0; 35412332Shelge data->pk_flag = TUF_DATA; 35512937Shelge data->pk_mcount = MIN(128, uuc->tu_count); 35612332Shelge data->pk_chksum = 35712937Shelge tuchk(*((short *)data), (caddr_t)uuc->tu_addr, 35812332Shelge (int)data->pk_mcount); 35912937Shelge uuc->tu_state = TUS_SENDH; 36012937Shelge uuc->tu_wbptr = (u_char *)data; 36112937Shelge uuc->tu_wcnt = 2; 36212857Shelge uuxintr(ctlr); 36311876Shelge break; 36412332Shelge 36512332Shelge case TUF_CMD: /* sending us an END packet...error */ 36612937Shelge uuc->tu_state = TUS_GET; 36712937Shelge uuc->tu_rbptr = (u_char *)data; 36813014Shelge uuc->tu_rcnt = sizeof (*data) - 1; 36912937Shelge uuc->tu_flag = 1; 37012332Shelge uuaddr->tcs = 0; 37113014Shelge *uuc->tu_rbptr++ = c & UUDB_DMASK; 37213014Shelge break; 37312332Shelge 37412332Shelge case TUF_INITF: 37512857Shelge uureset(ctlr); 37612332Shelge break; 37712332Shelge 37812332Shelge default: /* something random...bad news */ 37912937Shelge uuc->tu_state = TUS_INIT1; 38012332Shelge break; 38111876Shelge } 38211876Shelge break; 38311876Shelge 38412937Shelge case TUS_SENDW: 38512937Shelge if (c != TUF_CONT && c != TUF_INITF) 38611876Shelge goto bad; 38713014Shelge uu_restart(ctlr, ui); 38811876Shelge break; 38911876Shelge 39011876Shelge /* 39111876Shelge * Got header, now get data; amount to 39211896Shelge * fetch is included in packet. 39313014Shelge * (data packets are handled entirely 39413014Shelge * in uudma) 39511876Shelge */ 39612937Shelge case TUS_GETH: 39713156Shelge #ifndef UUDMA 39813156Shelge if (data->pk_flag == TUF_DATA) 39913156Shelge uuc->tu_rbptr = (u_char *)uuc->tu_addr; 40013156Shelge #endif 40112937Shelge uuc->tu_rcnt = data->pk_mcount; 40212937Shelge uuc->tu_state = TUS_GETD; 40311876Shelge break; 40411876Shelge 40511876Shelge /* 40611876Shelge * Got the data, now fetch the checksum. 40711876Shelge */ 40812937Shelge case TUS_GETD: 40912937Shelge uuc->tu_rbptr = (u_char *)&data->pk_chksum; 41012937Shelge uuc->tu_rcnt = sizeof (data->pk_chksum); 41112937Shelge uuc->tu_state = TUS_GETC; 41211876Shelge break; 41311876Shelge 41412937Shelge case TUS_GETC: 41511876Shelge /* got entire packet */ 41612332Shelge if (data->pk_chksum != 41712937Shelge tuchk(*((short *)data), (u_short *) 41813014Shelge (data->pk_flag == TUF_DATA ? 41913156Shelge (u_short *) uuc->tu_addr : (u_short *)&data->pk_op), 42012332Shelge (int)data->pk_mcount)) 42113014Shelge case TUS_CHKERR: 42212937Shelge uuc->tu_cerrs++; 42313014Shelge case TUS_GET: 42412332Shelge if (data->pk_flag == TUF_DATA) { 42511876Shelge /* data packet, advance to next */ 42612937Shelge uuc->tu_addr += data->pk_mcount; 42712937Shelge uuc->tu_count -= data->pk_mcount; 42812937Shelge uuc->tu_state = TUS_GETH; 42912937Shelge uuc->tu_rbptr = (u_char *)data; /* next packet */ 43012937Shelge uuc->tu_rcnt = 2; 43112332Shelge } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { 43211876Shelge /* end packet, idle and reenable transmitter */ 43312937Shelge uuc->tu_state = TUS_IDLE; 43412937Shelge uuc->tu_flag = 0; 43512937Shelge uuaddr->tcs = UUCS_INTR; 43612937Shelge if ((bp = uutab->b_actf) == NULL) { 43713156Shelge printf("uu%d: no bp, active %d\n", 438*13834Ssam data->pk_unit, uitab[ctlr].b_active); 43912857Shelge uustart(ui); 44011876Shelge return; 44111876Shelge } 44212937Shelge unit = UNIT(minor(bp->b_dev)); 44312332Shelge if (data->pk_mod > 1) { /* hard error */ 44413014Shelge printf("uu%d: hard error bn%d,", unit, 445*13834Ssam bp->b_blkno); 44613014Shelge printf(" pk_mod %o\n", data->pk_mod&0xff); 44711876Shelge bp->b_flags |= B_ERROR; 44812937Shelge uuc->tu_herrs++; 44912332Shelge } else if (data->pk_mod != 0) /* soft error */ 45012937Shelge uuc->tu_serrs++; 45112332Shelge uutab->b_active = NULL; 45212937Shelge uutab->b_actf = bp->av_forw; 45312937Shelge bp->b_resid = uuc->tu_count; 45411876Shelge if ((bp->b_flags&B_READ) == 0) 45512937Shelge tu_vee(&pcnt[unit]); 45611876Shelge iodone(bp); 45712857Shelge uustart(ui); 45811876Shelge } else { 45913156Shelge /* 46013156Shelge * Neither data nor end: data was lost 46113156Shelge * somehow, restart the transfer. 46213156Shelge */ 46312332Shelge uuaddr->rcs = 0; /* flush the rest */ 46413014Shelge uu_restart(ctlr, ui); 46513156Shelge uuc->tu_serrs++; 46611876Shelge } 46711876Shelge break; 46811876Shelge 46912937Shelge case TUS_IDLE: 47012937Shelge case TUS_INIT1: 47111876Shelge break; 47211876Shelge 47311876Shelge default: 47411876Shelge bad: 47511876Shelge if (c == TUF_INITF) { 47613156Shelge printf("uu%d protocol error, state=", data->pk_unit); 47712937Shelge printstate(uuc->tu_state); 47811876Shelge printf(", op=%x, cnt=%d, block=%d\n", 47912332Shelge cmd->pk_op, cmd->pk_count, cmd->pk_block); 48012332Shelge uutab->b_active = NULL; 48112332Shelge if (bp = uutab->b_actf) { 48211876Shelge bp->b_flags |= B_ERROR; 48312937Shelge uutab->b_actf = bp->av_forw; 48411876Shelge if ((bp->b_flags&B_READ) == 0) 48512937Shelge tu_vee(&pcnt[unit]); 48611876Shelge iodone(bp); 48711876Shelge } 48812937Shelge uuc->tu_state = TUS_INIT1; 48911876Shelge } else { 49012332Shelge printf("uu%d receive state error, state=", 49113156Shelge data->pk_unit); 49212937Shelge printstate(uuc->tu_state); 49313014Shelge printf(", byte=%x\n", c & 0xff); 49411876Shelge #ifdef notdef 49512937Shelge uuc->tu_state = TUS_INIT1; 49611876Shelge #endif 49712332Shelge wakeup((caddr_t)uuc); 49811876Shelge } 49911876Shelge } 50011876Shelge } 50111876Shelge 50212937Shelge 50312937Shelge /* 50411876Shelge * TU58 transmitter interrupt 50511876Shelge */ 50612332Shelge uuxintr(ctlr) 50712332Shelge int ctlr; 50811876Shelge { 50913014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 51012857Shelge register struct uudevice *uuaddr; 51112332Shelge register struct packet *data; 51212857Shelge struct uba_device *ui = uudinfo[ctlr]; 51312332Shelge int c; 51411876Shelge 51512857Shelge data = &uudata[ctlr]; 51612857Shelge uuaddr = (struct uudevice *) ui->ui_addr; 51711876Shelge top: 51812937Shelge if (uuc->tu_wcnt) { 51911876Shelge /* still stuff to send, send one byte */ 52012332Shelge while ((uuaddr->tcs & UUCS_READY) == 0) 52111876Shelge ; 52212937Shelge uuaddr->tdb = *uuc->tu_wbptr++; 52312937Shelge uuc->tu_wcnt--; 52411876Shelge return; 52511876Shelge } 52611876Shelge 52711876Shelge /* 52811876Shelge * Last message byte was sent out. 52912937Shelge * Switch on tu_state of transfer. 53011876Shelge */ 53112937Shelge switch(uuc->tu_state) { 53211876Shelge 53311876Shelge /* 53411876Shelge * Two nulls have been sent, remove break, and send inits 53511876Shelge */ 53612937Shelge case TUS_INIT1: 53712332Shelge uuaddr->tcs = UUCS_INTR; 53812937Shelge uuc->tu_state = TUS_INIT2; 53912937Shelge uuc->tu_wbptr = uuinit; 54012937Shelge uuc->tu_wcnt = sizeof (uuinit); 54111876Shelge goto top; 54211876Shelge 54311876Shelge /* 54411876Shelge * Inits have been sent, wait for a continue msg. 54511876Shelge */ 54612937Shelge case TUS_INIT2: 54712857Shelge c = uuaddr->rdb; /* prevent overrun error */ 54812332Shelge uuaddr->rcs = UUCS_INTR; 54912937Shelge uuc->tu_flag = 1; 55011876Shelge break; 55111876Shelge 55211876Shelge /* 55311876Shelge * Read cmd packet sent, get ready for data 55411876Shelge */ 55512937Shelge case TUS_SENDR: 55612937Shelge uuc->tu_state = TUS_GETH; 55712937Shelge uuc->tu_rbptr = (u_char *)data; 55812937Shelge uuc->tu_rcnt = 2; 55912937Shelge uuc->tu_flag = 1; 56012332Shelge uuaddr->tcs = 0; /* disable transmitter interrupts */ 56112937Shelge uuaddr->rcs = UUCS_INTR; 56211876Shelge break; 56311876Shelge 56411876Shelge /* 56511876Shelge * Write cmd packet sent, wait for continue 56611876Shelge */ 56712937Shelge case TUS_SENDW: 56812937Shelge uuc->tu_state = TUS_WAIT; 56912937Shelge uuc->tu_flag = 1; 57012332Shelge if ((uuaddr->rcs&UUCS_INTR) == 0) { 57111876Shelge printf("NO IE\n"); 57212332Shelge uuaddr->rcs = UUCS_INTR; 57311876Shelge } 57411876Shelge break; 57511876Shelge 57611876Shelge /* 57711876Shelge * Header sent, send data. 57811876Shelge */ 57912937Shelge case TUS_SENDH: 58012937Shelge uuc->tu_state = TUS_SENDD; 58112937Shelge uuc->tu_wbptr = (u_char *)uuc->tu_addr; 58212937Shelge uuc->tu_wcnt = data->pk_mcount; 58311876Shelge goto top; 58411876Shelge 58511876Shelge /* 58611876Shelge * Data sent, follow with checksum. 58711876Shelge */ 58812937Shelge case TUS_SENDD: 58912937Shelge uuc->tu_state = TUS_SENDC; 59012937Shelge uuc->tu_wbptr = (u_char *)&data->pk_chksum; 59112937Shelge uuc->tu_wcnt = sizeof (data->pk_chksum); 59211876Shelge goto top; 59311876Shelge 59411876Shelge /* 59511876Shelge * Checksum sent, wait for continue. 59611876Shelge */ 59712937Shelge case TUS_SENDC: 59811876Shelge /* 59912937Shelge * Update buffer address and count. 60011876Shelge */ 60112937Shelge uuc->tu_addr += data->pk_mcount; 60212937Shelge uuc->tu_count -= data->pk_mcount; 60312937Shelge if (uuc->tu_count) { 60412937Shelge uuc->tu_state = TUS_WAIT; 60512937Shelge uuc->tu_flag = 1; 60611876Shelge break; 60711876Shelge } 60811876Shelge 60911876Shelge /* 61011876Shelge * End of transmission, get ready for end packet. 61111876Shelge */ 61212937Shelge uuc->tu_state = TUS_GET; 61312937Shelge uuc->tu_rbptr = (u_char *)data; 61412937Shelge uuc->tu_rcnt = sizeof (*data); 61512937Shelge uuc->tu_flag = 1; 61612332Shelge uuaddr->tcs = 0; /* disable transm. interrupts */ 61711876Shelge break; 61811876Shelge 61911876Shelge /* 62012332Shelge * Random interrupt 62111876Shelge */ 62213156Shelge case TUS_IDLE: /* stray interrupt? */ 62313156Shelge 62411876Shelge default: 62511876Shelge break; 62611876Shelge } 62712937Shelge } 62812937Shelge 62912937Shelge uuwatch() 63012937Shelge { 63113014Shelge register struct uu_softc *uuc; 63212937Shelge register struct uudevice *uuaddr; 63312937Shelge struct uba_device *ui; 63412937Shelge struct buf *bp, *uutab; 63512937Shelge int s, ctlr, active = 0; 63612937Shelge 63712937Shelge for (ctlr=0; ctlr<NUU; ctlr++) { 63812937Shelge int i; 63912937Shelge 64012937Shelge uuc = &uu_softc[ctlr]; 64112937Shelge ui = uudinfo[ctlr]; 64212937Shelge uuaddr = (struct uudevice *)ui->ui_addr; 64312937Shelge uutab = &uitab[ctlr]; 64412937Shelge if ((uuc->tu_dopen[0] == 0) && (uuc->tu_dopen[1] == 0) && 64512937Shelge (uutab->b_active == 0)) { 64613156Shelge /* 64713156Shelge * If both devices on this controller have 64813156Shelge * been closed and the request queue is 64913156Shelge * empty, mark ths controller not active 65013156Shelge */ 65112937Shelge uuc->tu_flag = 0; 65212937Shelge uuaddr->rcs = 0; 65312937Shelge continue; 65412937Shelge } 65512937Shelge active++; 65612937Shelge if (uuc->tu_flag) 65712937Shelge uuc->tu_flag++; 65812937Shelge if (uuc->tu_flag <= 40) 65912937Shelge continue; 66013156Shelge printf("uu%d: read stalled\n", uudata[ctlr].pk_unit); 661*13834Ssam #ifdef notdef 66212937Shelge printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt, 66313156Shelge uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr, 66413156Shelge uuc->tu_count); 665*13834Ssam #endif 66612937Shelge uuc->tu_flag = 0; 66712937Shelge s = splx(UUIPL); 66812937Shelge i = uuaddr->rdb; /* dummy */ 66912937Shelge uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ 67012937Shelge uuaddr->tcs = UUCS_INTR; 67112937Shelge uuc->tu_state = TUS_IDLE; 67212937Shelge if (!uutab->b_active) { 67312937Shelge wakeup((caddr_t)uuc); 67412937Shelge goto retry; 67512937Shelge } 67612937Shelge if (++uutab->b_errcnt <= 1) { 67712937Shelge uustart(ui); 67812937Shelge goto retry; 67912937Shelge } 68012937Shelge if (bp = uutab->b_actf) { 68112937Shelge bp->b_flags |= B_ERROR; 68212937Shelge if ((bp->b_flags&B_READ) == 0) 68312937Shelge tu_vee(&pcnt[UNIT(minor(bp->b_dev))]); 68412937Shelge iodone(bp); 68512937Shelge } 68612937Shelge retry: 68712937Shelge (void) splx(s); 68811876Shelge } 68912937Shelge if (active) 69012937Shelge timeout(uuwatch, (caddr_t)0, hz); 69112937Shelge else 69212937Shelge uuwstart = 0; 69312937Shelge return; 69411876Shelge } 69511876Shelge 69612937Shelge #if !defined(VAX750) && !defined(VAX730) 69711876Shelge /* 69811876Shelge * Compute checksum TU58 fashion 69911876Shelge */ 70011876Shelge #ifdef lint 70112937Shelge tuchk(word, cp, n) 70211876Shelge register word; 70311876Shelge register unsigned short *cp; 70411876Shelge int n; 70511876Shelge { 70611876Shelge register int c = n >> 1; 70711876Shelge register long temp; 70811876Shelge 70911876Shelge do { 71011876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 71111876Shelge word += temp; 71211876Shelge } while (--c > 0); 71311876Shelge if (n & 1) 71411876Shelge word += *(unsigned char *)cp; 71511876Shelge while (word & 0xffff0000) 71611876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 71711876Shelge return (word); 71811876Shelge } 71911876Shelge #else 72012937Shelge tuchk(word0, wp, n) 72111896Shelge register int word0; /* r11 */ 72211896Shelge register char *wp; /* r10 */ 72311896Shelge register int n; /* r9 */ 72411876Shelge { 72511876Shelge asm("loop:"); 72611896Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 72711896Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 72811876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 72911896Shelge asm(" blbc r9,ok"); /* odd byte count? */ 73011896Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 73111896Shelge asm(" addw2 r10,r11"); /* add it in */ 73211896Shelge asm(" adwc $0,r11"); /* and the carry */ 73311876Shelge asm("ok:"); 73411896Shelge asm(" movl r11,r0"); /* return sum */ 73511876Shelge } 73611876Shelge #endif 73711876Shelge 73812937Shelge tu_pee(cp) 73912332Shelge char *cp; 74012332Shelge { 74112332Shelge register int s; 74212332Shelge 74312857Shelge s = splx(UUIPL); 74412332Shelge if (++(*cp) > NTUQ) { 74512332Shelge sleep(cp, PRIBIO); 74611876Shelge } 74712332Shelge splx(s); 74812332Shelge } 74912332Shelge 75012937Shelge tu_vee(cp) 75112332Shelge char *cp; 75212332Shelge { 75312332Shelge register int s; 75412332Shelge 75512857Shelge s = splx(UUIPL); 75612332Shelge if (--(*cp) <= NTUQ) { 75712332Shelge wakeup(cp); 75811876Shelge } 75911876Shelge splx(s); 76011876Shelge } 76111876Shelge #endif 76212332Shelge 76312937Shelge uuioctl(dev, cmd, data, flag) 76412937Shelge dev_t dev; 76512937Shelge caddr_t data; 76612937Shelge { 76712937Shelge /* 76813156Shelge * add code to wind/rewind cassette here 76912937Shelge */ 77012937Shelge return (ENXIO); 77112937Shelge } 77212937Shelge 77312937Shelge #endif 77412937Shelge 77513014Shelge uu_restart(ctlr, ui) 77613014Shelge int ctlr; 77713014Shelge struct uba_device *ui; 77813014Shelge { 77913014Shelge uureset(ctlr); 78013014Shelge timeout(uustart, (caddr_t)ui, hz * 3); 78113014Shelge } 782