123359Smckusick /* 229257Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323359Smckusick * All rights reserved. The Berkeley software License Agreement 423359Smckusick * specifies the terms and conditions for redistribution. 523359Smckusick * 6*45810Sbostic * @(#)uu.c 7.5 (Berkeley) 12/16/90 723359Smckusick */ 811876Shelge 912332Shelge #include "uu.h" 1012857Shelge #if NUU > 0 1111876Shelge /* 1211896Shelge * TU58 DECtape II/DL11 device driver 1311876Shelge * 1413156Shelge * The TU58 is treated as a block device (only). Error detection and 1513156Shelge * recovery is not very extensive, but sufficient to handle the most 1614091Shelge * common errors. It is assumed that the TU58 will follow the RSP 1714091Shelge * protocol exactly, very few protocol errors are checked for. 1814091Shelge * 1914091Shelge * To reduce interrupt latency, `options UUDMA' should be specified 2014091Shelge * in the config file to make sure the `pseudo-DMA' code in locore.s 2114091Shelge * will be compiled into the system. Otherwise overrun errors will 2214091Shelge * occur frequently (these errors are not reported). 2314091Shelge * 2414091Shelge * TODO: 2514091Shelge * 2614091Shelge * - Add ioctl code to wind/rewind cassette 2714091Shelge * 2811876Shelge */ 2911896Shelge 30*45810Sbostic #include "../include/pte.h" 3111896Shelge 32*45810Sbostic #include "sys/param.h" 33*45810Sbostic #include "sys/systm.h" 34*45810Sbostic #include "sys/buf.h" 35*45810Sbostic #include "sys/conf.h" 36*45810Sbostic #include "sys/time.h" 37*45810Sbostic #include "sys/kernel.h" 38*45810Sbostic #include "sys/errno.h" 39*45810Sbostic #include "sys/file.h" 4011876Shelge 41*45810Sbostic #include "../include/cpu.h" 4212332Shelge #include "../vax/nexus.h" 4312937Shelge #include "../vax/rsp.h" 4412332Shelge 4517084Sbloom #include "ubavar.h" 4617084Sbloom #include "ubareg.h" 4717084Sbloom #include "uureg.h" 4811876Shelge 4911876Shelge #define NTUBLK 512 /* number of blocks on a TU58 cassette */ 5012857Shelge #define WRV 01 /* bit in minor dev => write w. read verify */ 5112332Shelge #define NDPC 02 /* drives per controller */ 5212857Shelge #define NUX NDPC * NUU /* number of drives */ 5314091Shelge #define NUUQ 02 /* # of block which can be queued up */ 5412857Shelge #define UMASK 01 /* unit number mask */ 5512937Shelge #define UUIPL 0x14 /* ipl level to use */ 5611876Shelge 5712857Shelge struct packet uucmd[NUU]; /* a command sent to the TU58 */ 5812857Shelge struct packet uudata[NUU]; /* a command or data returned from TU58 */ 5912857Shelge struct buf uitab[NUU]; /* buffer queue headers */ 6011876Shelge 6111876Shelge /* 6212937Shelge * Driver soft carrier structure 6311876Shelge */ 6412937Shelge struct uu_softc { 6512937Shelge u_char *tu_rbptr; /* pointer to buffer for read */ 6612937Shelge int tu_rcnt; /* how much to read */ 6712937Shelge u_char *tu_wbptr; /* pointer to buffer for write */ 6812937Shelge int tu_wcnt; /* how much to write */ 6912937Shelge int tu_state; /* current state of tansfer operation */ 7012937Shelge int tu_flag; /* read in progress flag */ 7112937Shelge char *tu_addr; /* real buffer data address */ 7212937Shelge int tu_count; /* real requested count */ 7312937Shelge int tu_serrs; /* count of soft errors */ 7412937Shelge int tu_cerrs; /* count of checksum errors */ 7512937Shelge int tu_herrs; /* count of hard errors */ 7612937Shelge char tu_dopen[2]; /* drive is open */ 7713014Shelge } uu_softc[NUU]; 7811876Shelge 7912937Shelge #if defined(VAX750) || defined(VAX730) 8012937Shelge extern char *tustates[]; 8112937Shelge #else 8212937Shelge char *tustates[TUS_NSTATES] = { 8311876Shelge "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", 8413014Shelge "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR" 8511876Shelge }; 8612937Shelge #endif 8712332Shelge 8812857Shelge #define UNIT(dev) (minor(dev)>>1) 8911876Shelge 9014091Shelge u_char uunull[2] = { 0, 0 }; /* nulls to send for initialization */ 9111896Shelge u_char uuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ 9211876Shelge 9311896Shelge struct uba_device *uudinfo[NUU]; 9411896Shelge 9512857Shelge int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch(); 9625521Stef u_short uustd[] = { 0176500, 0 }; 9712857Shelge struct uba_driver uudriver = 9812857Shelge { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo }; 9911896Shelge 10011896Shelge int uuwstart; 10114152Shelge int uuwake(); 10214091Shelge static char uu_pcnt[NUX]; /* pee/vee counters, one per drive */ 10311896Shelge 10411876Shelge /*ARGSUSED*/ 10511896Shelge uuprobe(reg) 10611896Shelge caddr_t reg; 10711876Shelge { 10811896Shelge register int br, cvec; /* value result */ 10911896Shelge struct uudevice *uuaddr = (struct uudevice *)reg; 11011876Shelge 11111876Shelge #ifdef lint 11211896Shelge br = 0; cvec = br; br = cvec; 11311896Shelge uurintr(0); uuxintr(0); 11411876Shelge #endif 11512857Shelge uuaddr->tcs = UUCS_INTR; 11612857Shelge DELAY(1000); 11712857Shelge uuaddr->tcs = 0; 11812857Shelge cvec -= 4; /* since we are using the xmitter intrpt */ 11911896Shelge return(sizeof (*uuaddr)); 12011896Shelge } 12111896Shelge 12211896Shelge uuattach(ui) 12312857Shelge register struct uba_device *ui; 12411896Shelge { 12511896Shelge } 12611896Shelge 12711896Shelge /*ARGSUSED1*/ 12811896Shelge uuopen(dev, flag) 12911896Shelge dev_t dev; 13011896Shelge int flag; 13111896Shelge { 13211896Shelge register struct uba_device *ui; 13313014Shelge register struct uu_softc *uuc; 13411896Shelge register struct uudevice *uuaddr; 13540728Skarels int ctlr, unit = UNIT(dev), s, error; 13611896Shelge 13712857Shelge ctlr = unit / NDPC; 13812857Shelge if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0) 13911876Shelge return (ENXIO); 14012937Shelge uuc = &uu_softc[ctlr]; 14112937Shelge if (uuc->tu_dopen[unit&UMASK]) 14211896Shelge return (EBUSY); 14311896Shelge if (uuwstart++ == 0) 14411896Shelge timeout(uuwatch, (caddr_t)0, hz); 14511896Shelge 14612937Shelge uuc->tu_dopen[unit&UMASK]++; 14712857Shelge uuaddr = (struct uudevice *)ui->ui_addr; 14812857Shelge s = splx(UUIPL); 14911876Shelge /* 15013014Shelge * If the other device on this controller 15114091Shelge * is already active, no need to initialize 15213014Shelge */ 15313014Shelge if (uuc->tu_dopen[0] && uuc->tu_dopen[1]) 15413156Shelge goto ok; 15513014Shelge 15613014Shelge /* 15711896Shelge * If the unit already initialized, 15811876Shelge * just enable interrupts and return. 15911876Shelge */ 16012937Shelge if (uuc->tu_state == TUS_IDLE) { 16111896Shelge uuaddr->rcs = UUCS_INTR; 16212937Shelge goto ok; 16311876Shelge } 16411876Shelge 16511876Shelge /* 16611876Shelge * Must initialize, reset the cassette 16711876Shelge * and wait for things to settle down. 16811876Shelge */ 16911896Shelge uureset(ctlr); 17040728Skarels if (error = tsleep((caddr_t)uuc, (PZERO+1) | PCATCH, devopn, 0)) { 17140728Skarels splx(s); 17240728Skarels return (error); 17340728Skarels } 17412857Shelge uitab[ctlr].b_active = NULL; 17512937Shelge if (uuc->tu_state != TUS_IDLE) { 17612937Shelge uuc->tu_state = TUS_INIT1; 17712937Shelge uuc->tu_dopen[unit&UMASK] = 0; 17812937Shelge uuc->tu_rcnt = uuc->tu_wcnt = 0; 17911896Shelge uuaddr->rcs = 0; 18011896Shelge uuaddr->tcs = 0; 18111896Shelge splx(s); 18212937Shelge return (EIO); 18311876Shelge } 18412937Shelge ok: 18511876Shelge splx(s); 18611876Shelge return (0); 18711876Shelge } 18811876Shelge 18914091Shelge /* 19014091Shelge * Wait for all outstanding IO on this drive 19114091Shelge * complete, before closing. If both drives on 19214091Shelge * this controller are idle, mark the controller 19314091Shelge * `inactive'. 19414091Shelge */ 19514091Shelge 19611896Shelge uuclose(dev, flag) 19711896Shelge dev_t dev; 19811896Shelge int flag; 19911876Shelge { 20014091Shelge int s, unit = UNIT(dev); 20114091Shelge register struct uu_softc *uuc = &uu_softc[unit/NDPC]; 20214091Shelge struct buf *bp, *last = NULL; 20314091Shelge struct uudevice *uuaddr = (struct uudevice *)uudinfo[unit/NDPC]->ui_addr; 20411876Shelge 20514091Shelge s = splx(UUIPL); 20614091Shelge while (uu_pcnt[unit]) 20714091Shelge sleep(&uu_pcnt[unit], PRIBIO); 20814091Shelge /* 20914091Shelge * No more writes are pending, scan the 21014091Shelge * buffer queue for oustanding reads from 21114091Shelge * this unit. 21214091Shelge */ 21314152Shelge for (bp = uitab[unit/NDPC].b_actf; bp; bp = bp->b_actf) { 21414091Shelge if (bp->b_dev == dev) 21514091Shelge last = bp; 21614152Shelge } 21714152Shelge if (last) { 21814152Shelge last->b_flags |= B_CALL; 21914152Shelge last->b_iodone = uuwake; 22014152Shelge sleep((caddr_t)last, PRIBIO); 22114152Shelge } 22214091Shelge uuc->tu_dopen[unit&UMASK] = 0; 22314091Shelge if (!uuc->tu_dopen[0] && !uuc->tu_dopen[1]) { 22414091Shelge uuc->tu_flag = 0; 22514091Shelge uuaddr->rcs = 0; 22614091Shelge } 22714091Shelge splx(s); 22840728Skarels return (0); 22911876Shelge } 23011876Shelge 23114152Shelge uuwake(bp) 23214152Shelge struct buf *bp; 23314152Shelge { 23414152Shelge wakeup(bp); 23514152Shelge } 23614152Shelge 23711896Shelge uureset(ctlr) 23811896Shelge int ctlr; 23911876Shelge { 24013014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 24112332Shelge register struct packet *cmd = &uucmd[ctlr]; 24212857Shelge struct uba_device *ui = uudinfo[ctlr]; 24312857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 24411876Shelge 24512857Shelge uitab[ctlr].b_active++; 24612937Shelge uuc->tu_state = TUS_INIT1; 24712937Shelge uuc->tu_wbptr = uunull; 24812937Shelge uuc->tu_wcnt = sizeof (uunull); 24914091Shelge uuc->tu_rcnt = 0; 25011896Shelge cmd->pk_flag = TUF_CMD; 25112332Shelge cmd->pk_mcount = sizeof (*cmd) - 4; 25211896Shelge cmd->pk_mod = 0; 25311896Shelge cmd->pk_seq = 0; 25412332Shelge cmd->pk_sw = 0; 25511896Shelge uuaddr->rcs = 0; 25611896Shelge uuaddr->tcs = UUCS_INTR | UUCS_BREAK; 25711896Shelge uuxintr(ctlr); /* start output */ 25811876Shelge } 25911876Shelge 26011876Shelge /* 26111876Shelge * Strategy routine for block I/O 26211876Shelge */ 26311896Shelge uustrategy(bp) 26411876Shelge register struct buf *bp; 26511876Shelge { 26612332Shelge register struct buf *uutab; 26711896Shelge struct uba_device *ui; 26814091Shelge int s, unit = UNIT(bp->b_dev); 26911876Shelge 27014091Shelge if ((unit > NUX) || (bp->b_blkno >= NTUBLK)) 27111896Shelge goto bad; 27212857Shelge ui = uudinfo[unit/NDPC]; 27311896Shelge if (ui == 0 || ui->ui_alive == 0) 27411896Shelge goto bad; 27512857Shelge uutab = &uitab[unit/NDPC]; /* one request queue per controller */ 27613156Shelge s = splx(UUIPL); 27712332Shelge if ((bp->b_flags&B_READ) == 0) 27814091Shelge tu_pee(&uu_pcnt[unit]); 27914091Shelge bp->b_actf = NULL; 28012332Shelge if (uutab->b_actf == NULL) 28112332Shelge uutab->b_actf = bp; 28212332Shelge else 28314091Shelge uutab->b_actl->b_actf = bp; 28412332Shelge uutab->b_actl = bp; 28512332Shelge if (uutab->b_active == 0) 28612857Shelge uustart(ui); 28711876Shelge splx(s); 28811896Shelge return; 28911896Shelge 29011896Shelge bad: 29111896Shelge bp->b_flags |= B_ERROR; 29212332Shelge bp->b_error = ENXIO; 29311896Shelge iodone(bp); 29411896Shelge return; 29511876Shelge } 29611876Shelge 29711876Shelge /* 29811876Shelge * Start the transfer 29911876Shelge */ 30012857Shelge uustart(ui) 30112857Shelge register struct uba_device *ui; 30211876Shelge { 30311876Shelge register struct buf *bp; 30413014Shelge register struct uu_softc *uuc; 30511896Shelge struct packet *cmd; 30614152Shelge int ctlr = ui->ui_unit, s; 30711876Shelge 30812857Shelge if ((bp = uitab[ctlr].b_actf) == NULL) 30911876Shelge return; 31014152Shelge s = splx(UUIPL); 31112937Shelge uuc = &uu_softc[ctlr]; 31212937Shelge if (uuc->tu_state != TUS_IDLE) { 31312332Shelge uureset(ctlr); 31414152Shelge splx(s); 31511876Shelge return; 31611876Shelge } 31714091Shelge cmd = &uucmd[ctlr]; 31812857Shelge uitab[ctlr].b_active++; 31912937Shelge uitab[ctlr].b_errcnt = 0; 32012937Shelge uuc->tu_addr = bp->b_un.b_addr; 32112937Shelge uuc->tu_count = cmd->pk_count = bp->b_bcount; 32212937Shelge cmd->pk_block = bp->b_blkno; 32312937Shelge if (bp->b_flags&B_READ) { 32412937Shelge cmd->pk_op = TUOP_READ; 32512937Shelge cmd->pk_mod = 0; 32612937Shelge uuc->tu_state = TUS_SENDR; 32712937Shelge } else { 32812937Shelge cmd->pk_op = TUOP_WRITE; 32912937Shelge cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0; 33012937Shelge uuc->tu_state = TUS_SENDW; 33112937Shelge } 33214091Shelge cmd->pk_unit = UNIT(bp->b_dev)&UMASK; 33312332Shelge cmd->pk_sw = 0; 33411896Shelge cmd->pk_chksum = 33512937Shelge tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount); 33612937Shelge uuc->tu_wbptr = (u_char *)cmd; 33712937Shelge uuc->tu_wcnt = sizeof (*cmd); 33812332Shelge uuxintr(ctlr); 33914152Shelge splx(s); 34011876Shelge } 34111876Shelge 34211876Shelge /* 34314091Shelge * TU58 receiver interrupt, handles whatever condition the 34414091Shelge * pseudo DMA routine in locore is unable to handle, 34514091Shelge * or, if UUDMA is undefined, handle all receiver interrupt 34614091Shelge * processing. 34711876Shelge */ 34812332Shelge uurintr(ctlr) 34912332Shelge int ctlr; 35011876Shelge { 35112857Shelge struct uba_device *ui = uudinfo[ctlr]; 35213014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 35312857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 35412857Shelge register struct buf *uutab = &uitab[ctlr]; 35512332Shelge struct packet *data, *cmd; 35612937Shelge struct buf *bp; 35712937Shelge int c, unit; 35811876Shelge 35912857Shelge c = uuaddr->rdb; 36012937Shelge data = &uudata[ctlr]; 36113014Shelge cmd = &uucmd[ctlr]; 36213014Shelge #if !defined(UUDMA) 36313014Shelge if (c & UURDB_ERROR) 36413014Shelge uuc->tu_state = TUS_RCVERR; 36513014Shelge else { 36613014Shelge if (uuc->tu_rcnt) { 36713014Shelge *uuc->tu_rbptr++ = c; 36813014Shelge if (--uuc->tu_rcnt) 36913014Shelge return; 37013014Shelge } 37113014Shelge } 37213014Shelge #endif 37313014Shelge 37413014Shelge /* 37513014Shelge * Switch on the tu_state of the transfer. 37613014Shelge */ 37713014Shelge switch(uuc->tu_state) { 37813014Shelge 37913014Shelge /* 38013014Shelge * A data error occured in uudma 38113014Shelge * (either overrun or break) 38213014Shelge */ 38313014Shelge case TUS_RCVERR: 38413156Shelge if ((c & UURDB_ORUN) == 0) 38513156Shelge printf("uu%d: break received, transfer restarted\n", 38613834Ssam data->pk_unit); 38714091Shelge #ifdef UUDEBUG 38814091Shelge else 38914091Shelge printf("uu%d: data overrun, recovered\n", 39014091Shelge data->pk_unit); 39114091Shelge #endif 39213156Shelge uuc->tu_serrs++; 39313014Shelge uu_restart(ctlr, ui); 39413014Shelge break; 39511876Shelge 39611876Shelge /* 39711876Shelge * If we get an unexpected "continue", 39811876Shelge * start all over again... 39911876Shelge */ 40012937Shelge case TUS_INIT2: 40112937Shelge uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; 40212937Shelge uuc->tu_flag = 0; 40312332Shelge wakeup((caddr_t)uuc); 40412857Shelge uustart(ui); 40511876Shelge break; 40611876Shelge 40711876Shelge /* 40811876Shelge * Only transition from this state 40911876Shelge * is on a "continue", so if we don't 41011876Shelge * get it, reset the world. 41111876Shelge */ 41212937Shelge case TUS_WAIT: /* waiting for continue */ 41312332Shelge switch(c) { 41412332Shelge case TUF_CONT: /* got the expected continue */ 41512937Shelge uuc->tu_flag = 0; 41612332Shelge data->pk_flag = TUF_DATA; 41712937Shelge data->pk_mcount = MIN(128, uuc->tu_count); 41812332Shelge data->pk_chksum = 41912937Shelge tuchk(*((short *)data), (caddr_t)uuc->tu_addr, 42012332Shelge (int)data->pk_mcount); 42112937Shelge uuc->tu_state = TUS_SENDH; 42212937Shelge uuc->tu_wbptr = (u_char *)data; 42312937Shelge uuc->tu_wcnt = 2; 42412857Shelge uuxintr(ctlr); 42511876Shelge break; 42612332Shelge 42712332Shelge case TUF_CMD: /* sending us an END packet...error */ 42812937Shelge uuc->tu_state = TUS_GET; 42912937Shelge uuc->tu_rbptr = (u_char *)data; 43013014Shelge uuc->tu_rcnt = sizeof (*data) - 1; 43112937Shelge uuc->tu_flag = 1; 43212332Shelge uuaddr->tcs = 0; 43313014Shelge *uuc->tu_rbptr++ = c & UUDB_DMASK; 43413014Shelge break; 43512332Shelge 43612332Shelge case TUF_INITF: 43712857Shelge uureset(ctlr); 43812332Shelge break; 43912332Shelge 44012332Shelge default: /* something random...bad news */ 44112937Shelge uuc->tu_state = TUS_INIT1; 44212332Shelge break; 44311876Shelge } 44411876Shelge break; 44511876Shelge 44612937Shelge case TUS_SENDW: 44712937Shelge if (c != TUF_CONT && c != TUF_INITF) 44811876Shelge goto bad; 44913014Shelge uu_restart(ctlr, ui); 45011876Shelge break; 45111876Shelge 45211876Shelge /* 45311876Shelge * Got header, now get data; amount to 45411896Shelge * fetch is included in packet. 45513014Shelge * (data packets are handled entirely 45613014Shelge * in uudma) 45711876Shelge */ 45812937Shelge case TUS_GETH: 45913156Shelge #ifndef UUDMA 46013156Shelge if (data->pk_flag == TUF_DATA) 46113156Shelge uuc->tu_rbptr = (u_char *)uuc->tu_addr; 46213156Shelge #endif 46312937Shelge uuc->tu_rcnt = data->pk_mcount; 46412937Shelge uuc->tu_state = TUS_GETD; 46511876Shelge break; 46611876Shelge 46711876Shelge /* 46811876Shelge * Got the data, now fetch the checksum. 46911876Shelge */ 47012937Shelge case TUS_GETD: 47112937Shelge uuc->tu_rbptr = (u_char *)&data->pk_chksum; 47212937Shelge uuc->tu_rcnt = sizeof (data->pk_chksum); 47312937Shelge uuc->tu_state = TUS_GETC; 47411876Shelge break; 47511876Shelge 47612937Shelge case TUS_GETC: 47711876Shelge /* got entire packet */ 47812332Shelge if (data->pk_chksum != 47912937Shelge tuchk(*((short *)data), (u_short *) 48013014Shelge (data->pk_flag == TUF_DATA ? 48113156Shelge (u_short *) uuc->tu_addr : (u_short *)&data->pk_op), 48212332Shelge (int)data->pk_mcount)) 48313014Shelge case TUS_CHKERR: 48412937Shelge uuc->tu_cerrs++; 48513014Shelge case TUS_GET: 48612332Shelge if (data->pk_flag == TUF_DATA) { 48711876Shelge /* data packet, advance to next */ 48812937Shelge uuc->tu_addr += data->pk_mcount; 48912937Shelge uuc->tu_count -= data->pk_mcount; 49012937Shelge uuc->tu_state = TUS_GETH; 49112937Shelge uuc->tu_rbptr = (u_char *)data; /* next packet */ 49212937Shelge uuc->tu_rcnt = 2; 49312332Shelge } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { 49411876Shelge /* end packet, idle and reenable transmitter */ 49512937Shelge uuc->tu_state = TUS_IDLE; 49612937Shelge uuc->tu_flag = 0; 49712937Shelge uuaddr->tcs = UUCS_INTR; 49812937Shelge if ((bp = uutab->b_actf) == NULL) { 49913156Shelge printf("uu%d: no bp, active %d\n", 50013834Ssam data->pk_unit, uitab[ctlr].b_active); 50112857Shelge uustart(ui); 50211876Shelge return; 50311876Shelge } 50414091Shelge unit = UNIT(bp->b_dev); 50512332Shelge if (data->pk_mod > 1) { /* hard error */ 50613014Shelge printf("uu%d: hard error bn%d,", unit, 50713834Ssam bp->b_blkno); 50814091Shelge printf(" pk_mod 0%o\n", data->pk_mod&0xff); 50911876Shelge bp->b_flags |= B_ERROR; 51012937Shelge uuc->tu_herrs++; 51114091Shelge } else if (data->pk_mod) /* soft error */ 51212937Shelge uuc->tu_serrs++; 51312332Shelge uutab->b_active = NULL; 51414091Shelge uutab->b_actf = bp->b_actf; 51512937Shelge bp->b_resid = uuc->tu_count; 51611876Shelge if ((bp->b_flags&B_READ) == 0) 51714091Shelge tu_vee(&uu_pcnt[unit]); 51811876Shelge iodone(bp); 51912857Shelge uustart(ui); 52011876Shelge } else { 52113156Shelge /* 52213156Shelge * Neither data nor end: data was lost 52314091Shelge * somehow, flush and restart the transfer. 52413156Shelge */ 52514091Shelge uuaddr->rcs = 0; 52613014Shelge uu_restart(ctlr, ui); 52713156Shelge uuc->tu_serrs++; 52811876Shelge } 52911876Shelge break; 53011876Shelge 53112937Shelge case TUS_IDLE: 53212937Shelge case TUS_INIT1: 53311876Shelge break; 53411876Shelge 53511876Shelge default: 53611876Shelge bad: 53711876Shelge if (c == TUF_INITF) { 53813156Shelge printf("uu%d protocol error, state=", data->pk_unit); 53912937Shelge printstate(uuc->tu_state); 54011876Shelge printf(", op=%x, cnt=%d, block=%d\n", 54112332Shelge cmd->pk_op, cmd->pk_count, cmd->pk_block); 54212332Shelge uutab->b_active = NULL; 54312332Shelge if (bp = uutab->b_actf) { 54411876Shelge bp->b_flags |= B_ERROR; 54514091Shelge uutab->b_actf = bp->b_actf; 54611876Shelge if ((bp->b_flags&B_READ) == 0) 54714091Shelge tu_vee(&uu_pcnt[unit]); 54811876Shelge iodone(bp); 54911876Shelge } 55012937Shelge uuc->tu_state = TUS_INIT1; 55111876Shelge } else { 55212332Shelge printf("uu%d receive state error, state=", 55313156Shelge data->pk_unit); 55412937Shelge printstate(uuc->tu_state); 55513014Shelge printf(", byte=%x\n", c & 0xff); 55611876Shelge #ifdef notdef 55712937Shelge uuc->tu_state = TUS_INIT1; 55811876Shelge #endif 55912332Shelge wakeup((caddr_t)uuc); 56011876Shelge } 56111876Shelge } 56211876Shelge } 56311876Shelge 56412937Shelge 56512937Shelge /* 56611876Shelge * TU58 transmitter interrupt 56711876Shelge */ 56812332Shelge uuxintr(ctlr) 56912332Shelge int ctlr; 57011876Shelge { 57113014Shelge register struct uu_softc *uuc = &uu_softc[ctlr]; 57212857Shelge register struct uudevice *uuaddr; 57312332Shelge register struct packet *data; 57412857Shelge struct uba_device *ui = uudinfo[ctlr]; 57512332Shelge int c; 57611876Shelge 57712857Shelge data = &uudata[ctlr]; 57812857Shelge uuaddr = (struct uudevice *) ui->ui_addr; 57911876Shelge top: 58014091Shelge if (uuc->tu_wcnt > 0) { 58111876Shelge /* still stuff to send, send one byte */ 58212332Shelge while ((uuaddr->tcs & UUCS_READY) == 0) 58311876Shelge ; 58412937Shelge uuaddr->tdb = *uuc->tu_wbptr++; 58512937Shelge uuc->tu_wcnt--; 58611876Shelge return; 58711876Shelge } 58811876Shelge 58911876Shelge /* 59011876Shelge * Last message byte was sent out. 59112937Shelge * Switch on tu_state of transfer. 59211876Shelge */ 59312937Shelge switch(uuc->tu_state) { 59411876Shelge 59511876Shelge /* 59611876Shelge * Two nulls have been sent, remove break, and send inits 59711876Shelge */ 59812937Shelge case TUS_INIT1: 59914091Shelge uuc->tu_flag = 0; 60012332Shelge uuaddr->tcs = UUCS_INTR; 60112937Shelge uuc->tu_state = TUS_INIT2; 60212937Shelge uuc->tu_wbptr = uuinit; 60312937Shelge uuc->tu_wcnt = sizeof (uuinit); 60411876Shelge goto top; 60511876Shelge 60611876Shelge /* 60711876Shelge * Inits have been sent, wait for a continue msg. 60811876Shelge */ 60912937Shelge case TUS_INIT2: 61012857Shelge c = uuaddr->rdb; /* prevent overrun error */ 61112332Shelge uuaddr->rcs = UUCS_INTR; 61212937Shelge uuc->tu_flag = 1; 61311876Shelge break; 61411876Shelge 61511876Shelge /* 61611876Shelge * Read cmd packet sent, get ready for data 61711876Shelge */ 61812937Shelge case TUS_SENDR: 61912937Shelge uuc->tu_state = TUS_GETH; 62012937Shelge uuc->tu_rbptr = (u_char *)data; 62112937Shelge uuc->tu_rcnt = 2; 62212937Shelge uuc->tu_flag = 1; 62314091Shelge uuaddr->tcs = 0; 62412937Shelge uuaddr->rcs = UUCS_INTR; 62511876Shelge break; 62611876Shelge 62711876Shelge /* 62811876Shelge * Write cmd packet sent, wait for continue 62911876Shelge */ 63012937Shelge case TUS_SENDW: 63112937Shelge uuc->tu_state = TUS_WAIT; 63212937Shelge uuc->tu_flag = 1; 63312332Shelge if ((uuaddr->rcs&UUCS_INTR) == 0) { 63411876Shelge printf("NO IE\n"); 63512332Shelge uuaddr->rcs = UUCS_INTR; 63611876Shelge } 63711876Shelge break; 63811876Shelge 63911876Shelge /* 64011876Shelge * Header sent, send data. 64111876Shelge */ 64212937Shelge case TUS_SENDH: 64312937Shelge uuc->tu_state = TUS_SENDD; 64412937Shelge uuc->tu_wbptr = (u_char *)uuc->tu_addr; 64512937Shelge uuc->tu_wcnt = data->pk_mcount; 64611876Shelge goto top; 64711876Shelge 64811876Shelge /* 64911876Shelge * Data sent, follow with checksum. 65011876Shelge */ 65112937Shelge case TUS_SENDD: 65212937Shelge uuc->tu_state = TUS_SENDC; 65312937Shelge uuc->tu_wbptr = (u_char *)&data->pk_chksum; 65414091Shelge uuc->tu_wcnt = 2; 65511876Shelge goto top; 65611876Shelge 65711876Shelge /* 65811876Shelge * Checksum sent, wait for continue. 65911876Shelge */ 66012937Shelge case TUS_SENDC: 66111876Shelge /* 66212937Shelge * Update buffer address and count. 66311876Shelge */ 66412937Shelge uuc->tu_addr += data->pk_mcount; 66512937Shelge uuc->tu_count -= data->pk_mcount; 66614091Shelge if (uuc->tu_count > 0) { 66712937Shelge uuc->tu_state = TUS_WAIT; 66812937Shelge uuc->tu_flag = 1; 66911876Shelge break; 67011876Shelge } 67111876Shelge 67211876Shelge /* 67311876Shelge * End of transmission, get ready for end packet. 67411876Shelge */ 67512937Shelge uuc->tu_state = TUS_GET; 67612937Shelge uuc->tu_rbptr = (u_char *)data; 67712937Shelge uuc->tu_rcnt = sizeof (*data); 67812937Shelge uuc->tu_flag = 1; 67914091Shelge uuaddr->tcs = 0; 68011876Shelge break; 68111876Shelge 68211876Shelge /* 68312332Shelge * Random interrupt 68411876Shelge */ 68513156Shelge case TUS_IDLE: /* stray interrupt? */ 68613156Shelge 68711876Shelge default: 68811876Shelge break; 68911876Shelge } 69012937Shelge } 69112937Shelge 69212937Shelge uuwatch() 69312937Shelge { 69413014Shelge register struct uu_softc *uuc; 69512937Shelge register struct uudevice *uuaddr; 69612937Shelge struct uba_device *ui; 69712937Shelge struct buf *bp, *uutab; 69812937Shelge int s, ctlr, active = 0; 69912937Shelge 70012937Shelge for (ctlr=0; ctlr<NUU; ctlr++) { 70112937Shelge int i; 70212937Shelge 70312937Shelge uuc = &uu_softc[ctlr]; 70414091Shelge 70514091Shelge if (uuc->tu_dopen[0] || uuc->tu_dopen[1]) 70614091Shelge active++; 70714091Shelge if (uuc->tu_flag == 0) 70814091Shelge /* 70914091Shelge * If no read is in progress 71014091Shelge * just skip 71114091Shelge */ 71214091Shelge continue; 71314091Shelge 71412937Shelge ui = uudinfo[ctlr]; 71512937Shelge uuaddr = (struct uudevice *)ui->ui_addr; 71612937Shelge uutab = &uitab[ctlr]; 71714091Shelge if (uuc->tu_flag++ < 40) 71812937Shelge continue; 71913156Shelge printf("uu%d: read stalled\n", uudata[ctlr].pk_unit); 72014091Shelge #ifdef UUDEBUG 72112937Shelge printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt, 72213156Shelge uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr, 72313156Shelge uuc->tu_count); 72413834Ssam #endif 72514091Shelge s = splx(UUIPL); 72612937Shelge uuc->tu_flag = 0; 72712937Shelge i = uuaddr->rdb; /* dummy */ 72812937Shelge uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ 72912937Shelge uuaddr->tcs = UUCS_INTR; 73012937Shelge uuc->tu_state = TUS_IDLE; 73112937Shelge if (!uutab->b_active) { 73212937Shelge wakeup((caddr_t)uuc); 73312937Shelge goto retry; 73412937Shelge } 73512937Shelge if (++uutab->b_errcnt <= 1) { 73612937Shelge uustart(ui); 73712937Shelge goto retry; 73812937Shelge } 73912937Shelge if (bp = uutab->b_actf) { 74012937Shelge bp->b_flags |= B_ERROR; 74112937Shelge if ((bp->b_flags&B_READ) == 0) 74214091Shelge tu_vee(&uu_pcnt[UNIT(bp->b_dev)]); 74312937Shelge iodone(bp); 74412937Shelge } 74512937Shelge retry: 74612937Shelge (void) splx(s); 74711876Shelge } 74812937Shelge if (active) 74912937Shelge timeout(uuwatch, (caddr_t)0, hz); 75012937Shelge else 75112937Shelge uuwstart = 0; 75212937Shelge return; 75311876Shelge } 75411876Shelge 75512937Shelge #if !defined(VAX750) && !defined(VAX730) 75611876Shelge /* 75711876Shelge * Compute checksum TU58 fashion 75811876Shelge */ 75911876Shelge #ifdef lint 76012937Shelge tuchk(word, cp, n) 76111876Shelge register word; 76211876Shelge register unsigned short *cp; 76311876Shelge int n; 76411876Shelge { 76511876Shelge register int c = n >> 1; 76611876Shelge register long temp; 76711876Shelge 76811876Shelge do { 76911876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 77011876Shelge word += temp; 77111876Shelge } while (--c > 0); 77211876Shelge if (n & 1) 77311876Shelge word += *(unsigned char *)cp; 77411876Shelge while (word & 0xffff0000) 77511876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 77611876Shelge return (word); 77711876Shelge } 77811876Shelge #else 77912937Shelge tuchk(word0, wp, n) 78011896Shelge register int word0; /* r11 */ 78111896Shelge register char *wp; /* r10 */ 78211896Shelge register int n; /* r9 */ 78311876Shelge { 78411876Shelge asm("loop:"); 78511896Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 78611896Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 78711876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 78811896Shelge asm(" blbc r9,ok"); /* odd byte count? */ 78911896Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 79011896Shelge asm(" addw2 r10,r11"); /* add it in */ 79111896Shelge asm(" adwc $0,r11"); /* and the carry */ 79211876Shelge asm("ok:"); 79311896Shelge asm(" movl r11,r0"); /* return sum */ 79411876Shelge } 79511876Shelge #endif 79611876Shelge 79714091Shelge /* 79814091Shelge * Make sure this incredibly slow device 79914091Shelge * doesn't eat up all the buffers in the 80014091Shelge * system by putting the requesting process 80114091Shelge * (remember: this device is 'single-user') 80214091Shelge * to sleep if the write-behind queue grows 80314091Shelge * larger than NUUQ. 80414091Shelge */ 80512937Shelge tu_pee(cp) 80614091Shelge char *cp; 80712332Shelge { 80812332Shelge register int s; 80912332Shelge 81012857Shelge s = splx(UUIPL); 81114091Shelge if (++(*cp) > NUUQ) 81212332Shelge sleep(cp, PRIBIO); 81312332Shelge splx(s); 81412332Shelge } 81512332Shelge 81612937Shelge tu_vee(cp) 81714091Shelge char *cp; 81812332Shelge { 81912332Shelge register int s; 82012332Shelge 82112857Shelge s = splx(UUIPL); 82214091Shelge if (--(*cp) <= NUUQ) 82312332Shelge wakeup(cp); 82411876Shelge splx(s); 82511876Shelge } 82611876Shelge #endif 82712332Shelge 82812937Shelge uuioctl(dev, cmd, data, flag) 82912937Shelge dev_t dev; 83012937Shelge caddr_t data; 83112937Shelge { 83212937Shelge /* 83313156Shelge * add code to wind/rewind cassette here 83412937Shelge */ 83512937Shelge return (ENXIO); 83612937Shelge } 83712937Shelge 83813014Shelge uu_restart(ctlr, ui) 83913014Shelge int ctlr; 84013014Shelge struct uba_device *ui; 84113014Shelge { 84213014Shelge uureset(ctlr); 84313014Shelge timeout(uustart, (caddr_t)ui, hz * 3); 84413014Shelge } 84514091Shelge 84614091Shelge #endif 847