1*13014Shelge /* uu.c 4.6 83/06/11 */ 211876Shelge 312332Shelge #include "uu.h" 412857Shelge #if NUU > 0 511876Shelge /* 611896Shelge * TU58 DECtape II/DL11 device driver 711876Shelge * 811896Shelge * The TU58 * is treated as a block device (only). Error detection and 911876Shelge * recovery is almost non-existant. It is assumed that the 1011876Shelge * TU58 will follow the RSP protocol exactly, very few protocol 1111896Shelge * errors are checked for. 1211876Shelge */ 1311896Shelge 1412332Shelge #include "../machine/pte.h" 1511896Shelge 1611876Shelge #include "../h/param.h" 1711876Shelge #include "../h/systm.h" 1811876Shelge #include "../h/buf.h" 1911876Shelge #include "../h/conf.h" 2012332Shelge #include "../h/time.h" 2111896Shelge #include "../h/kernel.h" 2211896Shelge #include "../h/errno.h" 2311896Shelge #include "../h/uio.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 */ 62*13014Shelge } 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", 69*13014Shelge "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR" 7011876Shelge }; 7112937Shelge #endif 7212332Shelge 7312857Shelge #define UNIT(dev) (minor(dev)>>1) 7411876Shelge 7511896Shelge u_char uunull[2] = { 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; 117*13014Shelge 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 /* 134*13014Shelge * If the other device on this controller 135*13014Shelge * is already active, just return 136*13014Shelge */ 137*13014Shelge if (uuc->tu_dopen[0] && uuc->tu_dopen[1]) 138*13014Shelge return; 139*13014Shelge 140*13014Shelge /* 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 { 174*13014Shelge register struct uu_softc *uuc; 17512857Shelge int unit = UNIT(dev); 17612937Shelge int ctlr = unit/NDPC; 17711876Shelge 17812937Shelge uuc = &uu_softc[ctlr]; 17912937Shelge if (uuc->tu_serrs + uuc->tu_cerrs + uuc->tu_herrs != 0) { 18011876Shelge /* 18111876Shelge * A tu58 is like nothing ever seen before; 18211876Shelge * I guess this is appropriate then... 18311876Shelge */ 18411876Shelge uprintf( 18512857Shelge "uu%d: %d soft errors, %d checksum errors, %d hard errors\n", 18612937Shelge unit, uuc->tu_serrs, uuc->tu_cerrs, uuc->tu_herrs); 18712937Shelge uuc->tu_serrs = uuc->tu_cerrs = uuc->tu_herrs = 0; 18811876Shelge } 18912937Shelge uuc->tu_dopen[unit&UMASK] = 0; 19011876Shelge } 19111876Shelge 19211896Shelge uureset(ctlr) 19311896Shelge int ctlr; 19411876Shelge { 195*13014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 19612332Shelge register struct packet *cmd = &uucmd[ctlr]; 19712857Shelge struct uba_device *ui = uudinfo[ctlr]; 19812857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 19911876Shelge 20012857Shelge uitab[ctlr].b_active++; 20112937Shelge uuc->tu_state = TUS_INIT1; 20212937Shelge uuc->tu_wbptr = uunull; 20312937Shelge uuc->tu_wcnt = sizeof (uunull); 20411896Shelge cmd->pk_flag = TUF_CMD; 20512332Shelge cmd->pk_mcount = sizeof (*cmd) - 4; 20611896Shelge cmd->pk_mod = 0; 20711896Shelge cmd->pk_seq = 0; 20812332Shelge cmd->pk_sw = 0; 20911896Shelge uuaddr->rcs = 0; 21011896Shelge uuaddr->tcs = UUCS_INTR | UUCS_BREAK; 21111896Shelge uuxintr(ctlr); /* start output */ 21211876Shelge } 21311876Shelge 21411876Shelge /* 21511876Shelge * Strategy routine for block I/O 21611876Shelge */ 21711896Shelge uustrategy(bp) 21811876Shelge register struct buf *bp; 21911876Shelge { 22012332Shelge register struct buf *uutab; 22111896Shelge struct uba_device *ui; 22212857Shelge int s, unit = UNIT(minor(bp->b_dev)); 22311876Shelge 22412857Shelge if (unit > NUX) 22511896Shelge goto bad; 22611896Shelge if (bp->b_blkno >= NTUBLK) 22711896Shelge goto bad; 22812857Shelge ui = uudinfo[unit/NDPC]; 22911896Shelge if (ui == 0 || ui->ui_alive == 0) 23011896Shelge goto bad; 23112857Shelge uutab = &uitab[unit/NDPC]; /* one request queue per controller */ 23212332Shelge if ((bp->b_flags&B_READ) == 0) 23312937Shelge tu_pee(&pcnt[unit]); 23412857Shelge s = splx(UUIPL); 23512937Shelge bp->av_forw = NULL; 23612332Shelge if (uutab->b_actf == NULL) 23712332Shelge uutab->b_actf = bp; 23812332Shelge else 23912937Shelge uutab->b_actl->av_forw = bp; 24012332Shelge uutab->b_actl = bp; 24112332Shelge if (uutab->b_active == 0) 24212857Shelge uustart(ui); 24311876Shelge splx(s); 24411896Shelge return; 24511896Shelge 24611896Shelge bad: 24711896Shelge bp->b_flags |= B_ERROR; 24812332Shelge bp->b_error = ENXIO; 24911896Shelge iodone(bp); 25011896Shelge return; 25111876Shelge } 25211876Shelge 25311876Shelge /* 25411876Shelge * Start the transfer 25511876Shelge */ 25612857Shelge uustart(ui) 25712857Shelge register struct uba_device *ui; 25811876Shelge { 25911876Shelge register struct buf *bp; 260*13014Shelge register struct uu_softc *uuc; 26111896Shelge struct packet *cmd; 26212857Shelge int ctlr = ui->ui_unit; 26311876Shelge 26412857Shelge if ((bp = uitab[ctlr].b_actf) == NULL) 26511876Shelge return; 26612937Shelge uuc = &uu_softc[ctlr]; 26712332Shelge cmd = &uucmd[ctlr]; 26812937Shelge if (uuc->tu_state != TUS_IDLE) { 26912332Shelge uureset(ctlr); 27011876Shelge return; 27111876Shelge } 27212857Shelge uitab[ctlr].b_active++; 27312937Shelge uitab[ctlr].b_errcnt = 0; 27412937Shelge uuc->tu_addr = bp->b_un.b_addr; 27512937Shelge uuc->tu_count = cmd->pk_count = bp->b_bcount; 27612937Shelge cmd->pk_block = bp->b_blkno; 27712937Shelge if (bp->b_flags&B_READ) { 27812937Shelge cmd->pk_op = TUOP_READ; 27912937Shelge cmd->pk_mod = 0; 28012937Shelge uuc->tu_state = TUS_SENDR; 28112937Shelge } else { 28212937Shelge cmd->pk_op = TUOP_WRITE; 28312937Shelge cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0; 28412937Shelge uuc->tu_state = TUS_SENDW; 28512937Shelge } 28612857Shelge cmd->pk_unit = UNIT(minor(bp->b_dev)); 28712332Shelge cmd->pk_sw = 0; 28811896Shelge cmd->pk_chksum = 28912937Shelge tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount); 29012937Shelge uuc->tu_wbptr = (u_char *)cmd; 29112937Shelge uuc->tu_wcnt = sizeof (*cmd); 29212332Shelge uuxintr(ctlr); 29311876Shelge } 29411876Shelge 29511876Shelge /* 296*13014Shelge * TU58 receiver interrupt, 297*13014Shelge * handles whatever condition the 298*13014Shelge * pseudo DMA routine in locore is 299*13014Shelge * unable to handle, or, if UUDMA is 300*13014Shelge * undefined, handle all receiver interrupt 301*13014Shelge * processing 30211876Shelge */ 30312332Shelge uurintr(ctlr) 30412332Shelge int ctlr; 30511876Shelge { 30612857Shelge struct uba_device *ui = uudinfo[ctlr]; 307*13014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 30812857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 30912857Shelge register struct buf *uutab = &uitab[ctlr]; 31012332Shelge struct packet *data, *cmd; 31112937Shelge struct buf *bp; 31212937Shelge int c, unit; 31311876Shelge 31412857Shelge c = uuaddr->rdb; 31512937Shelge data = &uudata[ctlr]; 316*13014Shelge cmd = &uucmd[ctlr]; 317*13014Shelge #if !defined(UUDMA) 318*13014Shelge if (c & UURDB_ERROR) 319*13014Shelge uuc->tu_state = TUS_RCVERR; 320*13014Shelge else { 321*13014Shelge if (uuc->tu_rcnt) { 322*13014Shelge *uuc->tu_rbptr++ = c; 323*13014Shelge if (--uuc->tu_rcnt) 324*13014Shelge return; 325*13014Shelge } 326*13014Shelge } 327*13014Shelge #endif 328*13014Shelge 329*13014Shelge /* 330*13014Shelge * Switch on the tu_state of the transfer. 331*13014Shelge */ 332*13014Shelge switch(uuc->tu_state) { 333*13014Shelge 334*13014Shelge /* 335*13014Shelge * A data error occured in uudma 336*13014Shelge * (either overrun or break) 337*13014Shelge */ 338*13014Shelge case TUS_RCVERR: 33912937Shelge if (c & UURDB_ORUN) 34012937Shelge printf("uu(%d): data overrun, bytes left: %d", 34112937Shelge ui->ui_unit, 34212937Shelge uuc->tu_count + uuc->tu_rcnt - data->pk_mcount); 34312937Shelge else 34412937Shelge printf("uu(%d): break received", ui->ui_unit); 345*13014Shelge printf(", transfer restarted\n"); 346*13014Shelge uu_restart(ctlr, ui); 347*13014Shelge break; 34811876Shelge 34911876Shelge /* 35011876Shelge * If we get an unexpected "continue", 35111876Shelge * start all over again... 35211876Shelge */ 35312937Shelge case TUS_INIT2: 35412937Shelge uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; 35512937Shelge uuc->tu_flag = 0; 35612332Shelge wakeup((caddr_t)uuc); 35712857Shelge uustart(ui); 35811876Shelge break; 35911876Shelge 36011876Shelge /* 36111876Shelge * Only transition from this state 36211876Shelge * is on a "continue", so if we don't 36311876Shelge * get it, reset the world. 36411876Shelge */ 36512937Shelge case TUS_WAIT: /* waiting for continue */ 36612332Shelge switch(c) { 36712332Shelge case TUF_CONT: /* got the expected continue */ 36812937Shelge uuc->tu_flag = 0; 36912332Shelge data->pk_flag = TUF_DATA; 37012937Shelge data->pk_mcount = MIN(128, uuc->tu_count); 37112332Shelge data->pk_chksum = 37212937Shelge tuchk(*((short *)data), (caddr_t)uuc->tu_addr, 37312332Shelge (int)data->pk_mcount); 37412937Shelge uuc->tu_state = TUS_SENDH; 37512937Shelge uuc->tu_wbptr = (u_char *)data; 37612937Shelge uuc->tu_wcnt = 2; 37712857Shelge uuxintr(ctlr); 37811876Shelge break; 37912332Shelge 38012332Shelge case TUF_CMD: /* sending us an END packet...error */ 38112937Shelge uuc->tu_state = TUS_GET; 38212937Shelge uuc->tu_rbptr = (u_char *)data; 383*13014Shelge uuc->tu_rcnt = sizeof (*data) - 1; 38412937Shelge uuc->tu_flag = 1; 38512332Shelge uuaddr->tcs = 0; 386*13014Shelge *uuc->tu_rbptr++ = c & UUDB_DMASK; 387*13014Shelge break; 38812332Shelge 38912332Shelge case TUF_INITF: 39012857Shelge uureset(ctlr); 39112332Shelge break; 39212332Shelge 39312332Shelge default: /* something random...bad news */ 39412937Shelge uuc->tu_state = TUS_INIT1; 39512332Shelge break; 39611876Shelge } 39711876Shelge break; 39811876Shelge 39912937Shelge case TUS_SENDW: 40012937Shelge if (c != TUF_CONT && c != TUF_INITF) 40111876Shelge goto bad; 402*13014Shelge uu_restart(ctlr, ui); 40311876Shelge break; 40411876Shelge 40511876Shelge /* 40611876Shelge * Got header, now get data; amount to 40711896Shelge * fetch is included in packet. 408*13014Shelge * (data packets are handled entirely 409*13014Shelge * in uudma) 41011876Shelge */ 41112937Shelge case TUS_GETH: 41212937Shelge uuc->tu_rcnt = data->pk_mcount; 41312937Shelge uuc->tu_state = TUS_GETD; 41411876Shelge break; 41511876Shelge 41611876Shelge /* 41711876Shelge * Got the data, now fetch the checksum. 41811876Shelge */ 41912937Shelge case TUS_GETD: 42012937Shelge uuc->tu_rbptr = (u_char *)&data->pk_chksum; 42112937Shelge uuc->tu_rcnt = sizeof (data->pk_chksum); 42212937Shelge uuc->tu_state = TUS_GETC; 42311876Shelge break; 42411876Shelge 42512937Shelge case TUS_GETC: 42611876Shelge /* got entire packet */ 42712332Shelge if (data->pk_chksum != 42812937Shelge tuchk(*((short *)data), (u_short *) 429*13014Shelge (data->pk_flag == TUF_DATA ? 430*13014Shelge (u_short *) uuc->tu_addr : (u_short *)&data->pk_op), 43112332Shelge (int)data->pk_mcount)) 432*13014Shelge case TUS_CHKERR: 43312937Shelge uuc->tu_cerrs++; 434*13014Shelge case TUS_GET: 43512332Shelge if (data->pk_flag == TUF_DATA) { 43611876Shelge /* data packet, advance to next */ 43712937Shelge uuc->tu_addr += data->pk_mcount; 43812937Shelge uuc->tu_count -= data->pk_mcount; 43912937Shelge uuc->tu_state = TUS_GETH; 44012937Shelge uuc->tu_rbptr = (u_char *)data; /* next packet */ 44112937Shelge uuc->tu_rcnt = 2; 44212332Shelge } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { 44311876Shelge /* end packet, idle and reenable transmitter */ 44412937Shelge uuc->tu_state = TUS_IDLE; 44512937Shelge uuc->tu_flag = 0; 44612937Shelge uuaddr->tcs = UUCS_INTR; 44712937Shelge if ((bp = uutab->b_actf) == NULL) { 44812857Shelge printf("uu(%d): no bp, active %d\n", 44912937Shelge ui->ui_unit, uitab[ctlr].b_active); 45012857Shelge uustart(ui); 45111876Shelge return; 45211876Shelge } 45312937Shelge unit = UNIT(minor(bp->b_dev)); 45412332Shelge if (data->pk_mod > 1) { /* hard error */ 455*13014Shelge printf("uu%d: hard error bn%d,", unit, 456*13014Shelge bp->b_blkno); 457*13014Shelge printf(" pk_mod %o\n", data->pk_mod&0xff); 45811876Shelge bp->b_flags |= B_ERROR; 45912937Shelge uuc->tu_herrs++; 46012332Shelge } else if (data->pk_mod != 0) /* soft error */ 46112937Shelge uuc->tu_serrs++; 46212332Shelge uutab->b_active = NULL; 46312937Shelge uutab->b_actf = bp->av_forw; 46412937Shelge bp->b_resid = uuc->tu_count; 46511876Shelge if ((bp->b_flags&B_READ) == 0) 46612937Shelge tu_vee(&pcnt[unit]); 46711876Shelge iodone(bp); 46812857Shelge uustart(ui); 46911876Shelge } else { 47011876Shelge printf("neither data nor end: %o %o\n", 47112332Shelge data->pk_flag&0xff, data->pk_op&0xff); 47212332Shelge uuaddr->rcs = 0; /* flush the rest */ 47312937Shelge uuc->tu_state = TUS_INIT1; 474*13014Shelge uu_restart(ctlr, ui); 47511876Shelge } 47611876Shelge break; 47711876Shelge 47812937Shelge case TUS_IDLE: 47912937Shelge case TUS_INIT1: 48011876Shelge break; 48111876Shelge 48211876Shelge default: 48311876Shelge bad: 48411876Shelge if (c == TUF_INITF) { 48512857Shelge printf("uu%d protocol error, state=", unit); 48612937Shelge printstate(uuc->tu_state); 48711876Shelge printf(", op=%x, cnt=%d, block=%d\n", 48812332Shelge cmd->pk_op, cmd->pk_count, cmd->pk_block); 48912332Shelge uutab->b_active = NULL; 49012332Shelge if (bp = uutab->b_actf) { 49111876Shelge bp->b_flags |= B_ERROR; 49212937Shelge uutab->b_actf = bp->av_forw; 49311876Shelge if ((bp->b_flags&B_READ) == 0) 49412937Shelge tu_vee(&pcnt[unit]); 49511876Shelge iodone(bp); 49611876Shelge } 49712937Shelge uuc->tu_state = TUS_INIT1; 49811876Shelge } else { 49912332Shelge printf("uu%d receive state error, state=", 50012857Shelge unit); 50112937Shelge printstate(uuc->tu_state); 502*13014Shelge printf(", byte=%x\n", c & 0xff); 50311876Shelge #ifdef notdef 50412937Shelge uuc->tu_state = TUS_INIT1; 50511876Shelge #endif 50612332Shelge wakeup((caddr_t)uuc); 50711876Shelge } 50811876Shelge } 50911876Shelge } 51011876Shelge 51112937Shelge 51212937Shelge /* 51311876Shelge * TU58 transmitter interrupt 51411876Shelge */ 51512332Shelge uuxintr(ctlr) 51612332Shelge int ctlr; 51711876Shelge { 518*13014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 51912857Shelge register struct uudevice *uuaddr; 52012332Shelge register struct packet *data; 52112857Shelge struct uba_device *ui = uudinfo[ctlr]; 52212332Shelge int c; 52311876Shelge 52412857Shelge data = &uudata[ctlr]; 52512857Shelge uuaddr = (struct uudevice *) ui->ui_addr; 52611876Shelge top: 52712937Shelge if (uuc->tu_wcnt) { 52811876Shelge /* still stuff to send, send one byte */ 52912332Shelge while ((uuaddr->tcs & UUCS_READY) == 0) 53011876Shelge ; 53112937Shelge uuaddr->tdb = *uuc->tu_wbptr++; 53212937Shelge uuc->tu_wcnt--; 53311876Shelge return; 53411876Shelge } 53511876Shelge 53611876Shelge /* 53711876Shelge * Last message byte was sent out. 53812937Shelge * Switch on tu_state of transfer. 53911876Shelge */ 54012937Shelge switch(uuc->tu_state) { 54111876Shelge 54211876Shelge /* 54311876Shelge * Two nulls have been sent, remove break, and send inits 54411876Shelge */ 54512937Shelge case TUS_INIT1: 54612332Shelge uuaddr->tcs = UUCS_INTR; 54712937Shelge uuc->tu_state = TUS_INIT2; 54812937Shelge uuc->tu_wbptr = uuinit; 54912937Shelge uuc->tu_wcnt = sizeof (uuinit); 55011876Shelge goto top; 55111876Shelge 55211876Shelge /* 55311876Shelge * Inits have been sent, wait for a continue msg. 55411876Shelge */ 55512937Shelge case TUS_INIT2: 55612857Shelge c = uuaddr->rdb; /* prevent overrun error */ 55712332Shelge uuaddr->rcs = UUCS_INTR; 55812937Shelge uuc->tu_flag = 1; 55911876Shelge break; 56011876Shelge 56112937Shelge case TUS_IDLE: /* stray interrupt? */ 56211876Shelge break; 56311876Shelge 56411876Shelge /* 56511876Shelge * Read cmd packet sent, get ready for data 56611876Shelge */ 56712937Shelge case TUS_SENDR: 56812937Shelge uuc->tu_state = TUS_GETH; 56912937Shelge uuc->tu_rbptr = (u_char *)data; 57012937Shelge uuc->tu_rcnt = 2; 57112937Shelge uuc->tu_flag = 1; 57212332Shelge uuaddr->tcs = 0; /* disable transmitter interrupts */ 57312937Shelge uuaddr->rcs = UUCS_INTR; 57411876Shelge break; 57511876Shelge 57611876Shelge /* 57711876Shelge * Write cmd packet sent, wait for continue 57811876Shelge */ 57912937Shelge case TUS_SENDW: 58012937Shelge uuc->tu_state = TUS_WAIT; 58112937Shelge uuc->tu_flag = 1; 58212332Shelge if ((uuaddr->rcs&UUCS_INTR) == 0) { 58311876Shelge printf("NO IE\n"); 58412332Shelge uuaddr->rcs = UUCS_INTR; 58511876Shelge } 58611876Shelge break; 58711876Shelge 58811876Shelge /* 58911876Shelge * Header sent, send data. 59011876Shelge */ 59112937Shelge case TUS_SENDH: 59212937Shelge uuc->tu_state = TUS_SENDD; 59312937Shelge uuc->tu_wbptr = (u_char *)uuc->tu_addr; 59412937Shelge uuc->tu_wcnt = data->pk_mcount; 59511876Shelge goto top; 59611876Shelge 59711876Shelge /* 59811876Shelge * Data sent, follow with checksum. 59911876Shelge */ 60012937Shelge case TUS_SENDD: 60112937Shelge uuc->tu_state = TUS_SENDC; 60212937Shelge uuc->tu_wbptr = (u_char *)&data->pk_chksum; 60312937Shelge uuc->tu_wcnt = sizeof (data->pk_chksum); 60411876Shelge goto top; 60511876Shelge 60611876Shelge /* 60711876Shelge * Checksum sent, wait for continue. 60811876Shelge */ 60912937Shelge case TUS_SENDC: 61011876Shelge /* 61112937Shelge * Update buffer address and count. 61211876Shelge */ 61312937Shelge uuc->tu_addr += data->pk_mcount; 61412937Shelge uuc->tu_count -= data->pk_mcount; 61512937Shelge if (uuc->tu_count) { 61612937Shelge uuc->tu_state = TUS_WAIT; 61712937Shelge uuc->tu_flag = 1; 61811876Shelge break; 61911876Shelge } 62011876Shelge 62111876Shelge /* 62211876Shelge * End of transmission, get ready for end packet. 62311876Shelge */ 62412937Shelge uuc->tu_state = TUS_GET; 62512937Shelge uuc->tu_rbptr = (u_char *)data; 62612937Shelge uuc->tu_rcnt = sizeof (*data); 62712937Shelge uuc->tu_flag = 1; 62812332Shelge uuaddr->tcs = 0; /* disable transm. interrupts */ 62911876Shelge break; 63011876Shelge 63111876Shelge /* 63212332Shelge * Random interrupt 63311876Shelge */ 63411876Shelge default: 63511876Shelge break; 63611876Shelge } 63712937Shelge } 63812937Shelge 63912937Shelge uuwatch() 64012937Shelge { 641*13014Shelge register struct uu_softc *uuc; 64212937Shelge register struct uudevice *uuaddr; 64312937Shelge struct uba_device *ui; 64412937Shelge struct buf *bp, *uutab; 64512937Shelge int s, ctlr, active = 0; 64612937Shelge 64712937Shelge for (ctlr=0; ctlr<NUU; ctlr++) { 64812937Shelge int i; 64912937Shelge 65012937Shelge uuc = &uu_softc[ctlr]; 65112937Shelge ui = uudinfo[ctlr]; 65212937Shelge uuaddr = (struct uudevice *)ui->ui_addr; 65312937Shelge uutab = &uitab[ctlr]; 65412937Shelge if ((uuc->tu_dopen[0] == 0) && (uuc->tu_dopen[1] == 0) && 65512937Shelge (uutab->b_active == 0)) { 65612937Shelge uuc->tu_flag = 0; 65712937Shelge uuaddr->rcs = 0; 65812937Shelge continue; 65912937Shelge } 66012937Shelge active++; 66112937Shelge if (uuc->tu_flag) 66212937Shelge uuc->tu_flag++; 66312937Shelge if (uuc->tu_flag <= 40) 66412937Shelge continue; 66512937Shelge printf("uu(%d): read stalled\n", ctlr); 66612937Shelge printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt, 66712937Shelge uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr, uuc->tu_count); 66812937Shelge uuc->tu_flag = 0; 66912937Shelge s = splx(UUIPL); 67012937Shelge i = uuaddr->rdb; /* dummy */ 67112937Shelge uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ 67212937Shelge uuaddr->tcs = UUCS_INTR; 67312937Shelge uuc->tu_state = TUS_IDLE; 67412937Shelge if (!uutab->b_active) { 67512937Shelge wakeup((caddr_t)uuc); 67612937Shelge goto retry; 67712937Shelge } 67812937Shelge if (++uutab->b_errcnt <= 1) { 67912937Shelge uustart(ui); 68012937Shelge goto retry; 68112937Shelge } 68212937Shelge if (bp = uutab->b_actf) { 68312937Shelge bp->b_flags |= B_ERROR; 68412937Shelge if ((bp->b_flags&B_READ) == 0) 68512937Shelge tu_vee(&pcnt[UNIT(minor(bp->b_dev))]); 68612937Shelge iodone(bp); 68712937Shelge } 68812937Shelge retry: 68912937Shelge (void) splx(s); 69011876Shelge } 69112937Shelge if (active) 69212937Shelge timeout(uuwatch, (caddr_t)0, hz); 69312937Shelge else 69412937Shelge uuwstart = 0; 69512937Shelge return; 69611876Shelge } 69711876Shelge 69812937Shelge #if !defined(VAX750) && !defined(VAX730) 69911876Shelge /* 70011876Shelge * Compute checksum TU58 fashion 70111876Shelge */ 70211876Shelge #ifdef lint 70312937Shelge tuchk(word, cp, n) 70411876Shelge register word; 70511876Shelge register unsigned short *cp; 70611876Shelge int n; 70711876Shelge { 70811876Shelge register int c = n >> 1; 70911876Shelge register long temp; 71011876Shelge 71111876Shelge do { 71211876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 71311876Shelge word += temp; 71411876Shelge } while (--c > 0); 71511876Shelge if (n & 1) 71611876Shelge word += *(unsigned char *)cp; 71711876Shelge while (word & 0xffff0000) 71811876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 71911876Shelge return (word); 72011876Shelge } 72111876Shelge #else 72212937Shelge tuchk(word0, wp, n) 72311896Shelge register int word0; /* r11 */ 72411896Shelge register char *wp; /* r10 */ 72511896Shelge register int n; /* r9 */ 72611876Shelge { 72711876Shelge asm("loop:"); 72811896Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 72911896Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 73011876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 73111896Shelge asm(" blbc r9,ok"); /* odd byte count? */ 73211896Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 73311896Shelge asm(" addw2 r10,r11"); /* add it in */ 73411896Shelge asm(" adwc $0,r11"); /* and the carry */ 73511876Shelge asm("ok:"); 73611896Shelge asm(" movl r11,r0"); /* return sum */ 73711876Shelge } 73811876Shelge #endif 73911876Shelge 74012937Shelge tu_pee(cp) 74112332Shelge char *cp; 74212332Shelge { 74312332Shelge register int s; 74412332Shelge 74512857Shelge s = splx(UUIPL); 74612332Shelge if (++(*cp) > NTUQ) { 74712332Shelge sleep(cp, PRIBIO); 74811876Shelge } 74912332Shelge splx(s); 75012332Shelge } 75112332Shelge 75212937Shelge tu_vee(cp) 75312332Shelge char *cp; 75412332Shelge { 75512332Shelge register int s; 75612332Shelge 75712857Shelge s = splx(UUIPL); 75812332Shelge if (--(*cp) <= NTUQ) { 75912332Shelge wakeup(cp); 76011876Shelge } 76111876Shelge splx(s); 76211876Shelge } 76311876Shelge #endif 76412332Shelge 76512937Shelge uuioctl(dev, cmd, data, flag) 76612937Shelge dev_t dev; 76712937Shelge caddr_t data; 76812937Shelge { 76912937Shelge /* 77012937Shelge * to be added later 77112937Shelge */ 77212937Shelge return (ENXIO); 77312937Shelge } 77412937Shelge 77512937Shelge #endif 77612937Shelge 777*13014Shelge uu_restart(ctlr, ui) 778*13014Shelge int ctlr; 779*13014Shelge struct uba_device *ui; 780*13014Shelge { 781*13014Shelge uureset(ctlr); 782*13014Shelge timeout(uustart, (caddr_t)ui, hz * 3); 783*13014Shelge } 784