1*12937Shelge /* uu.c 4.5 83/06/08 */ 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" 28*12937Shelge #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 */ 40*12937Shelge #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 /* 47*12937Shelge * Driver soft carrier structure 4811876Shelge */ 49*12937Shelge struct uu_softc { 50*12937Shelge u_char *tu_rbptr; /* pointer to buffer for read */ 51*12937Shelge int tu_rcnt; /* how much to read */ 52*12937Shelge u_char *tu_wbptr; /* pointer to buffer for write */ 53*12937Shelge int tu_wcnt; /* how much to write */ 54*12937Shelge int tu_state; /* current state of tansfer operation */ 55*12937Shelge int tu_flag; /* read in progress flag */ 56*12937Shelge char *tu_addr; /* real buffer data address */ 57*12937Shelge int tu_count; /* real requested count */ 58*12937Shelge int tu_serrs; /* count of soft errors */ 59*12937Shelge int tu_cerrs; /* count of checksum errors */ 60*12937Shelge int tu_herrs; /* count of hard errors */ 61*12937Shelge char tu_dopen[2]; /* drive is open */ 62*12937Shelge }; 6311876Shelge 64*12937Shelge struct uu_softc uu_softc[NUU]; 6511876Shelge 66*12937Shelge #if defined(VAX750) || defined(VAX730) 67*12937Shelge extern char *tustates[]; 68*12937Shelge #else 69*12937Shelge char *tustates[TUS_NSTATES] = { 7011876Shelge "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", 7111876Shelge "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT" 7211876Shelge }; 73*12937Shelge #endif 7412332Shelge 7512857Shelge #define UNIT(dev) (minor(dev)>>1) 7611876Shelge 7711896Shelge u_char uunull[2] = { 0, 0 }; /* nulls to send for initialization */ 7811896Shelge u_char uuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ 7911876Shelge 8011896Shelge struct uba_device *uudinfo[NUU]; 8111896Shelge 8212857Shelge int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch(); 8312857Shelge u_short uustd[] = { 0176500 }; 8412857Shelge struct uba_driver uudriver = 8512857Shelge { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo }; 8611896Shelge 8711896Shelge int uuwstart; 88*12937Shelge static char pcnt[NUX]; /* pee/vee counters, one per drive */ 8911896Shelge 9011876Shelge /*ARGSUSED*/ 9111896Shelge uuprobe(reg) 9211896Shelge caddr_t reg; 9311876Shelge { 9411896Shelge register int br, cvec; /* value result */ 9511896Shelge struct uudevice *uuaddr = (struct uudevice *)reg; 9611876Shelge 9711876Shelge #ifdef lint 9811896Shelge br = 0; cvec = br; br = cvec; 9911896Shelge uurintr(0); uuxintr(0); 10011876Shelge #endif 10112857Shelge uuaddr->tcs = UUCS_INTR; 10212857Shelge DELAY(1000); 10312857Shelge uuaddr->tcs = 0; 10412857Shelge cvec -= 4; /* since we are using the xmitter intrpt */ 10511896Shelge return(sizeof (*uuaddr)); 10611896Shelge } 10711896Shelge 10811896Shelge uuattach(ui) 10912857Shelge register struct uba_device *ui; 11011896Shelge { 11111896Shelge } 11211896Shelge 11311896Shelge /*ARGSUSED1*/ 11411896Shelge uuopen(dev, flag) 11511896Shelge dev_t dev; 11611896Shelge int flag; 11711896Shelge { 11811896Shelge register struct uba_device *ui; 119*12937Shelge register struct tu *uuc; 12011896Shelge register struct uudevice *uuaddr; 12112332Shelge int ctlr, unit = UNIT(dev), s; 12211896Shelge 12312857Shelge ctlr = unit / NDPC; 12412857Shelge if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0) 12511876Shelge return (ENXIO); 126*12937Shelge uuc = &uu_softc[ctlr]; 127*12937Shelge if (uuc->tu_dopen[unit&UMASK]) 12811896Shelge return (EBUSY); 12911896Shelge if (uuwstart++ == 0) 13011896Shelge timeout(uuwatch, (caddr_t)0, hz); 13111896Shelge 132*12937Shelge uuc->tu_dopen[unit&UMASK]++; 13312857Shelge uuaddr = (struct uudevice *)ui->ui_addr; 13412857Shelge s = splx(UUIPL); 13511876Shelge /* 13611896Shelge * If the unit already initialized, 13711876Shelge * just enable interrupts and return. 13811876Shelge */ 139*12937Shelge if (uuc->tu_state == TUS_IDLE) { 14011896Shelge uuaddr->rcs = UUCS_INTR; 141*12937Shelge goto ok; 14211876Shelge } 14311876Shelge 14411876Shelge /* 14511876Shelge * Must initialize, reset the cassette 14611876Shelge * and wait for things to settle down. 14711876Shelge */ 14811896Shelge uureset(ctlr); 14911896Shelge sleep((caddr_t)uuc, PZERO+1); 15012857Shelge uitab[ctlr].b_active = NULL; 151*12937Shelge if (uuc->tu_state != TUS_IDLE) { 152*12937Shelge uuc->tu_state = TUS_INIT1; 153*12937Shelge uuc->tu_dopen[unit&UMASK] = 0; 154*12937Shelge uuc->tu_rcnt = uuc->tu_wcnt = 0; 15511896Shelge uuaddr->rcs = 0; 15611896Shelge uuaddr->tcs = 0; 15711896Shelge splx(s); 158*12937Shelge return (EIO); 15911876Shelge } 160*12937Shelge ok: 16111876Shelge splx(s); 16211876Shelge return (0); 16311876Shelge } 16411876Shelge 16511896Shelge uuclose(dev, flag) 16611896Shelge dev_t dev; 16711896Shelge int flag; 16811876Shelge { 169*12937Shelge register struct tu *uuc; 17012857Shelge int unit = UNIT(dev); 171*12937Shelge int ctlr = unit/NDPC; 17211876Shelge 173*12937Shelge uuc = &uu_softc[ctlr]; 174*12937Shelge if (uuc->tu_serrs + uuc->tu_cerrs + uuc->tu_herrs != 0) { 17511876Shelge /* 17611876Shelge * A tu58 is like nothing ever seen before; 17711876Shelge * I guess this is appropriate then... 17811876Shelge */ 17911876Shelge uprintf( 18012857Shelge "uu%d: %d soft errors, %d checksum errors, %d hard errors\n", 181*12937Shelge unit, uuc->tu_serrs, uuc->tu_cerrs, uuc->tu_herrs); 182*12937Shelge uuc->tu_serrs = uuc->tu_cerrs = uuc->tu_herrs = 0; 18311876Shelge } 184*12937Shelge uuc->tu_dopen[unit&UMASK] = 0; 18511876Shelge } 18611876Shelge 18711896Shelge uureset(ctlr) 18811896Shelge int ctlr; 18911876Shelge { 190*12937Shelge register struct tu *uuc = &uu_softc[ctlr]; 19112332Shelge register struct packet *cmd = &uucmd[ctlr]; 19212857Shelge struct uba_device *ui = uudinfo[ctlr]; 19312857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 19411876Shelge 19512857Shelge printf ("uureset\n"); 19612857Shelge uitab[ctlr].b_active++; 197*12937Shelge uuc->tu_state = TUS_INIT1; 198*12937Shelge uuc->tu_wbptr = uunull; 199*12937Shelge uuc->tu_wcnt = sizeof (uunull); 20011896Shelge cmd->pk_flag = TUF_CMD; 20112332Shelge cmd->pk_mcount = sizeof (*cmd) - 4; 20211896Shelge cmd->pk_mod = 0; 20311896Shelge cmd->pk_seq = 0; 20412332Shelge cmd->pk_sw = 0; 20511896Shelge uuaddr->rcs = 0; 20611896Shelge uuaddr->tcs = UUCS_INTR | UUCS_BREAK; 20711896Shelge uuxintr(ctlr); /* start output */ 20811876Shelge } 20911876Shelge 21011876Shelge /* 21111876Shelge * Strategy routine for block I/O 21211876Shelge */ 21311896Shelge uustrategy(bp) 21411876Shelge register struct buf *bp; 21511876Shelge { 21612332Shelge register struct buf *uutab; 21711896Shelge struct uba_device *ui; 21812857Shelge int s, unit = UNIT(minor(bp->b_dev)); 21911876Shelge 22012857Shelge if (unit > NUX) 22111896Shelge goto bad; 22211896Shelge if (bp->b_blkno >= NTUBLK) 22311896Shelge goto bad; 22412857Shelge ui = uudinfo[unit/NDPC]; 22511896Shelge if (ui == 0 || ui->ui_alive == 0) 22611896Shelge goto bad; 22712857Shelge uutab = &uitab[unit/NDPC]; /* one request queue per controller */ 22812332Shelge if ((bp->b_flags&B_READ) == 0) 229*12937Shelge tu_pee(&pcnt[unit]); 23012857Shelge s = splx(UUIPL); 231*12937Shelge bp->av_forw = NULL; 23212332Shelge if (uutab->b_actf == NULL) 23312332Shelge uutab->b_actf = bp; 23412332Shelge else 235*12937Shelge uutab->b_actl->av_forw = bp; 23612332Shelge uutab->b_actl = bp; 23712332Shelge if (uutab->b_active == 0) 23812857Shelge uustart(ui); 23911876Shelge splx(s); 24011896Shelge return; 24111896Shelge 24211896Shelge bad: 24311896Shelge bp->b_flags |= B_ERROR; 24412332Shelge bp->b_error = ENXIO; 24511896Shelge iodone(bp); 24611896Shelge return; 24711876Shelge } 24811876Shelge 24911876Shelge /* 25011876Shelge * Start the transfer 25111876Shelge */ 25212857Shelge uustart(ui) 25312857Shelge register struct uba_device *ui; 25411876Shelge { 25511876Shelge register struct buf *bp; 256*12937Shelge register struct tu *uuc; 25711896Shelge struct packet *cmd; 25812857Shelge int ctlr = ui->ui_unit; 25911876Shelge 26012857Shelge if ((bp = uitab[ctlr].b_actf) == NULL) 26111876Shelge return; 262*12937Shelge uuc = &uu_softc[ctlr]; 26312332Shelge cmd = &uucmd[ctlr]; 264*12937Shelge if (uuc->tu_state != TUS_IDLE) { 26512332Shelge uureset(ctlr); 26611876Shelge return; 26711876Shelge } 26812857Shelge uitab[ctlr].b_active++; 269*12937Shelge uitab[ctlr].b_errcnt = 0; 270*12937Shelge uuc->tu_addr = bp->b_un.b_addr; 271*12937Shelge uuc->tu_count = cmd->pk_count = bp->b_bcount; 272*12937Shelge cmd->pk_block = bp->b_blkno; 273*12937Shelge if (bp->b_flags&B_READ) { 274*12937Shelge cmd->pk_op = TUOP_READ; 275*12937Shelge cmd->pk_mod = 0; 276*12937Shelge uuc->tu_state = TUS_SENDR; 277*12937Shelge } else { 278*12937Shelge cmd->pk_op = TUOP_WRITE; 279*12937Shelge cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0; 280*12937Shelge uuc->tu_state = TUS_SENDW; 281*12937Shelge } 28212857Shelge cmd->pk_unit = UNIT(minor(bp->b_dev)); 28312332Shelge cmd->pk_sw = 0; 28411896Shelge cmd->pk_chksum = 285*12937Shelge tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount); 286*12937Shelge uuc->tu_wbptr = (u_char *)cmd; 287*12937Shelge uuc->tu_wcnt = sizeof (*cmd); 28812332Shelge uuxintr(ctlr); 28911876Shelge } 29011876Shelge 29111876Shelge /* 29211876Shelge * TU58 receiver interrupt 29311876Shelge */ 29412332Shelge uurintr(ctlr) 29512332Shelge int ctlr; 29611876Shelge { 29712857Shelge struct uba_device *ui = uudinfo[ctlr]; 298*12937Shelge register struct tu *uuc = &uu_softc[ctlr]; 29912857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 30012857Shelge register struct buf *uutab = &uitab[ctlr]; 30112332Shelge struct packet *data, *cmd; 302*12937Shelge struct buf *bp; 303*12937Shelge int c, unit; 30411876Shelge 30512857Shelge c = uuaddr->rdb; 306*12937Shelge data = &uudata[ctlr]; 307*12937Shelge if (c & UURDB_ERROR) { 308*12937Shelge if (c & UURDB_ORUN) 309*12937Shelge printf("uu(%d): data overrun, bytes left: %d", 310*12937Shelge ui->ui_unit, 311*12937Shelge uuc->tu_count + uuc->tu_rcnt - data->pk_mcount); 312*12937Shelge else 313*12937Shelge printf("uu(%d): break received", ui->ui_unit); 314*12937Shelge printf(", device reset, state="); 315*12937Shelge printstate(uuc->tu_state); 316*12937Shelge uureset(ctlr); 317*12937Shelge printf("\n"); 318*12937Shelge timeout(uustart, (caddr_t)ui, hz/2); /* start uustart when */ 319*12937Shelge /* reset is done */ 32012332Shelge return; 32111876Shelge } 32212332Shelge top: 323*12937Shelge c &= UUDB_DMASK; 324*12937Shelge if (uuc->tu_rcnt) { /* still waiting for data? */ 325*12937Shelge *uuc->tu_rbptr++ = c; /* yup, put it there */ 326*12937Shelge if (--uuc->tu_rcnt) /* decrement count, any left? */ 32711876Shelge return; /* get some more */ 32811876Shelge } 329*12937Shelge cmd = &uucmd[ctlr]; 33011876Shelge 33111876Shelge /* 33211876Shelge * We got all the data we were expecting for now, 333*12937Shelge * switch on the tu_state of the transfer. 33411876Shelge */ 335*12937Shelge switch(uuc->tu_state) { 33611876Shelge 33711876Shelge /* 33811876Shelge * If we get an unexpected "continue", 33911876Shelge * start all over again... 34011876Shelge */ 341*12937Shelge case TUS_INIT2: 342*12937Shelge uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; 343*12937Shelge uuc->tu_flag = 0; 34412332Shelge wakeup((caddr_t)uuc); 34512857Shelge uustart(ui); 34611876Shelge break; 34711876Shelge 34811876Shelge /* 34911876Shelge * Only transition from this state 35011876Shelge * is on a "continue", so if we don't 35111876Shelge * get it, reset the world. 35211876Shelge */ 353*12937Shelge case TUS_WAIT: /* waiting for continue */ 35412332Shelge switch(c) { 35512332Shelge case TUF_CONT: /* got the expected continue */ 356*12937Shelge uuc->tu_flag = 0; 35712332Shelge data->pk_flag = TUF_DATA; 358*12937Shelge data->pk_mcount = MIN(128, uuc->tu_count); 35912332Shelge data->pk_chksum = 360*12937Shelge tuchk(*((short *)data), (caddr_t)uuc->tu_addr, 36112332Shelge (int)data->pk_mcount); 362*12937Shelge uuc->tu_state = TUS_SENDH; 363*12937Shelge uuc->tu_wbptr = (u_char *)data; 364*12937Shelge uuc->tu_wcnt = 2; 36512857Shelge uuxintr(ctlr); 36611876Shelge break; 36712332Shelge 36812332Shelge case TUF_CMD: /* sending us an END packet...error */ 369*12937Shelge uuc->tu_state = TUS_GET; 370*12937Shelge uuc->tu_rbptr = (u_char *)data; 371*12937Shelge uuc->tu_rcnt = sizeof (*data); 372*12937Shelge uuc->tu_flag = 1; 37312332Shelge uuaddr->tcs = 0; 37412332Shelge goto top; 37512332Shelge 37612332Shelge case TUF_INITF: 37712857Shelge uureset(ctlr); 37812332Shelge break; 37912332Shelge 38012332Shelge default: /* something random...bad news */ 381*12937Shelge uuc->tu_state = TUS_INIT1; 38212332Shelge break; 38311876Shelge } 38411876Shelge break; 38511876Shelge 386*12937Shelge case TUS_SENDW: 387*12937Shelge if (c != TUF_CONT && c != TUF_INITF) 38811876Shelge goto bad; 38912332Shelge uureset(ctlr); 39011876Shelge break; 39111876Shelge 39211876Shelge /* 39311876Shelge * Got header, now get data; amount to 39411896Shelge * fetch is included in packet. 39511876Shelge */ 396*12937Shelge case TUS_GETH: 397*12937Shelge if (data->pk_flag == TUF_DATA) { 398*12937Shelge uu_getblk((u_char *)uuc->tu_addr, data, uuaddr); 399*12937Shelge goto getc; 400*12937Shelge } 401*12937Shelge uuc->tu_rcnt = data->pk_mcount; 402*12937Shelge uuc->tu_state = TUS_GETD; 40311876Shelge break; 40411876Shelge 40511876Shelge /* 40611876Shelge * Got the data, now fetch the checksum. 40711876Shelge */ 408*12937Shelge case TUS_GETD: 409*12937Shelge uuc->tu_rbptr = (u_char *)&data->pk_chksum; 410*12937Shelge uuc->tu_rcnt = sizeof (data->pk_chksum); 411*12937Shelge uuc->tu_state = TUS_GETC; 41211876Shelge break; 41311876Shelge 414*12937Shelge case TUS_GET: 415*12937Shelge case TUS_GETC: 416*12937Shelge getc: 41711876Shelge /* got entire packet */ 41811876Shelge #ifdef notdef 41912332Shelge if (data->pk_chksum != 420*12937Shelge tuchk(*((short *)data), (u_short *) 421*12937Shelge (data->pk_flag == TUF_DATA ? uuc->tu_addr : &data->pk_op), 42212332Shelge (int)data->pk_mcount)) 423*12937Shelge uuc->tu_cerrs++; 42411876Shelge #endif 42512332Shelge if (data->pk_flag == TUF_DATA) { 42611876Shelge /* data packet, advance to next */ 427*12937Shelge uuc->tu_addr += data->pk_mcount; 428*12937Shelge uuc->tu_count -= data->pk_mcount; 429*12937Shelge uuc->tu_state = TUS_GETH; 430*12937Shelge uuc->tu_rbptr = (u_char *)data; /* next packet */ 431*12937Shelge uuc->tu_rcnt = 2; 43212332Shelge } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { 43311876Shelge /* end packet, idle and reenable transmitter */ 434*12937Shelge uuc->tu_state = TUS_IDLE; 435*12937Shelge uuc->tu_flag = 0; 436*12937Shelge uuaddr->tcs = UUCS_INTR; 437*12937Shelge if ((bp = uutab->b_actf) == NULL) { 43812857Shelge printf("uu(%d): no bp, active %d\n", 439*12937Shelge ui->ui_unit, uitab[ctlr].b_active); 44012857Shelge uustart(ui); 44111876Shelge return; 44211876Shelge } 443*12937Shelge unit = UNIT(minor(bp->b_dev)); 44412332Shelge if (data->pk_mod > 1) { /* hard error */ 44511876Shelge bp->b_flags |= B_ERROR; 446*12937Shelge uuc->tu_herrs++; 44711896Shelge harderr(bp, "uu"); 44812332Shelge printf(" pk_mod %o\n", data->pk_mod&0xff); 44912332Shelge } else if (data->pk_mod != 0) /* soft error */ 450*12937Shelge uuc->tu_serrs++; 45112332Shelge uutab->b_active = NULL; 452*12937Shelge uutab->b_actf = bp->av_forw; 453*12937Shelge bp->b_resid = uuc->tu_count; 45411876Shelge if ((bp->b_flags&B_READ) == 0) 455*12937Shelge tu_vee(&pcnt[unit]); 45611876Shelge iodone(bp); 457*12937Shelge printf("."); 45812857Shelge uustart(ui); 45911876Shelge } else { 46011876Shelge printf("neither data nor end: %o %o\n", 46112332Shelge data->pk_flag&0xff, data->pk_op&0xff); 46212332Shelge uuaddr->rcs = 0; /* flush the rest */ 463*12937Shelge uuc->tu_state = TUS_INIT1; 46411876Shelge } 46511876Shelge break; 46611876Shelge 467*12937Shelge case TUS_IDLE: 468*12937Shelge case TUS_INIT1: 46911876Shelge break; 47011876Shelge 47111876Shelge default: 47211876Shelge bad: 47311876Shelge if (c == TUF_INITF) { 47412857Shelge printf("uu%d protocol error, state=", unit); 475*12937Shelge printstate(uuc->tu_state); 47611876Shelge printf(", op=%x, cnt=%d, block=%d\n", 47712332Shelge cmd->pk_op, cmd->pk_count, cmd->pk_block); 47812332Shelge uutab->b_active = NULL; 47912332Shelge if (bp = uutab->b_actf) { 48011876Shelge bp->b_flags |= B_ERROR; 481*12937Shelge uutab->b_actf = bp->av_forw; 48211876Shelge if ((bp->b_flags&B_READ) == 0) 483*12937Shelge tu_vee(&pcnt[unit]); 48411876Shelge iodone(bp); 48511876Shelge } 486*12937Shelge uuc->tu_state = TUS_INIT1; 48711876Shelge } else { 48812332Shelge printf("uu%d receive state error, state=", 48912857Shelge unit); 490*12937Shelge printstate(uuc->tu_state); 49111876Shelge printf(", byte=%x\n", c); 49211876Shelge #ifdef notdef 493*12937Shelge uuc->tu_state = TUS_INIT1; 49411876Shelge #endif 49512332Shelge wakeup((caddr_t)uuc); 49611876Shelge } 49711876Shelge } 49811876Shelge } 49911876Shelge 50011876Shelge /* 501*12937Shelge * Simulate DMA input from the TU58, 502*12937Shelge * usually 128 bytes plus the 2 byte checksum 503*12937Shelge * will be read, leaving the CPU `dead' for 504*12937Shelge * approximately 0.135 seconds @ 9600 baud 505*12937Shelge */ 506*12937Shelge uu_getblk(buffer, data, uuaddr) 507*12937Shelge register u_char *buffer; 508*12937Shelge register struct uudevice *uuaddr; 509*12937Shelge struct packet *data; 510*12937Shelge { 511*12937Shelge int s; 512*12937Shelge int count = (unsigned) data->pk_mcount + 2; 513*12937Shelge 514*12937Shelge s = spl5(); /* make sure we don't get interrupted by */ 515*12937Shelge /* disk i/o */ 516*12937Shelge uuaddr->rcs = 0; /* disable interrupts temporarily */ 517*12937Shelge while (count--) { 518*12937Shelge while ((uuaddr->rcs & UUCS_READY) == 0) 519*12937Shelge ; 520*12937Shelge *buffer++ = uuaddr->rdb & UUDB_DMASK; 521*12937Shelge if (count == 2) 522*12937Shelge buffer = (u_char *)&data->pk_chksum; 523*12937Shelge } 524*12937Shelge uuaddr->rcs = UUCS_INTR; 525*12937Shelge (void) splx(s); 526*12937Shelge } 527*12937Shelge 528*12937Shelge /* 52911876Shelge * TU58 transmitter interrupt 53011876Shelge */ 53112332Shelge uuxintr(ctlr) 53212332Shelge int ctlr; 53311876Shelge { 534*12937Shelge register struct tu *uuc = &uu_softc[ctlr]; 53512857Shelge register struct uudevice *uuaddr; 53612332Shelge register struct packet *data; 53712857Shelge struct uba_device *ui = uudinfo[ctlr]; 53812332Shelge int c; 53911876Shelge 54012857Shelge data = &uudata[ctlr]; 54112857Shelge uuaddr = (struct uudevice *) ui->ui_addr; 54211876Shelge top: 543*12937Shelge if (uuc->tu_wcnt) { 54411876Shelge /* still stuff to send, send one byte */ 54512332Shelge while ((uuaddr->tcs & UUCS_READY) == 0) 54611876Shelge ; 547*12937Shelge uuaddr->tdb = *uuc->tu_wbptr++; 548*12937Shelge uuc->tu_wcnt--; 54911876Shelge return; 55011876Shelge } 55111876Shelge 55211876Shelge /* 55311876Shelge * Last message byte was sent out. 554*12937Shelge * Switch on tu_state of transfer. 55511876Shelge */ 556*12937Shelge switch(uuc->tu_state) { 55711876Shelge 55811876Shelge /* 55911876Shelge * Two nulls have been sent, remove break, and send inits 56011876Shelge */ 561*12937Shelge case TUS_INIT1: 56212332Shelge uuaddr->tcs = UUCS_INTR; 563*12937Shelge uuc->tu_state = TUS_INIT2; 564*12937Shelge uuc->tu_wbptr = uuinit; 565*12937Shelge uuc->tu_wcnt = sizeof (uuinit); 56611876Shelge goto top; 56711876Shelge 56811876Shelge /* 56911876Shelge * Inits have been sent, wait for a continue msg. 57011876Shelge */ 571*12937Shelge case TUS_INIT2: 57212857Shelge c = uuaddr->rdb; /* prevent overrun error */ 57312332Shelge uuaddr->rcs = UUCS_INTR; 574*12937Shelge uuc->tu_flag = 1; 57511876Shelge break; 57611876Shelge 577*12937Shelge case TUS_IDLE: /* stray interrupt? */ 57811876Shelge break; 57911876Shelge 58011876Shelge /* 58111876Shelge * Read cmd packet sent, get ready for data 58211876Shelge */ 583*12937Shelge case TUS_SENDR: 584*12937Shelge uuc->tu_state = TUS_GETH; 585*12937Shelge uuc->tu_rbptr = (u_char *)data; 586*12937Shelge uuc->tu_rcnt = 2; 587*12937Shelge uuc->tu_flag = 1; 58812332Shelge uuaddr->tcs = 0; /* disable transmitter interrupts */ 589*12937Shelge uuaddr->rcs = UUCS_INTR; 59011876Shelge break; 59111876Shelge 59211876Shelge /* 59311876Shelge * Write cmd packet sent, wait for continue 59411876Shelge */ 595*12937Shelge case TUS_SENDW: 596*12937Shelge uuc->tu_state = TUS_WAIT; 597*12937Shelge uuc->tu_flag = 1; 59812332Shelge if ((uuaddr->rcs&UUCS_INTR) == 0) { 59911876Shelge printf("NO IE\n"); 60012332Shelge uuaddr->rcs = UUCS_INTR; 60111876Shelge } 60211876Shelge break; 60311876Shelge 60411876Shelge /* 60511876Shelge * Header sent, send data. 60611876Shelge */ 607*12937Shelge case TUS_SENDH: 608*12937Shelge uuc->tu_state = TUS_SENDD; 609*12937Shelge uuc->tu_wbptr = (u_char *)uuc->tu_addr; 610*12937Shelge uuc->tu_wcnt = data->pk_mcount; 61111876Shelge goto top; 61211876Shelge 61311876Shelge /* 61411876Shelge * Data sent, follow with checksum. 61511876Shelge */ 616*12937Shelge case TUS_SENDD: 617*12937Shelge uuc->tu_state = TUS_SENDC; 618*12937Shelge uuc->tu_wbptr = (u_char *)&data->pk_chksum; 619*12937Shelge uuc->tu_wcnt = sizeof (data->pk_chksum); 62011876Shelge goto top; 62111876Shelge 62211876Shelge /* 62311876Shelge * Checksum sent, wait for continue. 62411876Shelge */ 625*12937Shelge case TUS_SENDC: 62611876Shelge /* 627*12937Shelge * Update buffer address and count. 62811876Shelge */ 629*12937Shelge uuc->tu_addr += data->pk_mcount; 630*12937Shelge uuc->tu_count -= data->pk_mcount; 631*12937Shelge if (uuc->tu_count) { 632*12937Shelge uuc->tu_state = TUS_WAIT; 633*12937Shelge uuc->tu_flag = 1; 63411876Shelge break; 63511876Shelge } 63611876Shelge 63711876Shelge /* 63811876Shelge * End of transmission, get ready for end packet. 63911876Shelge */ 640*12937Shelge uuc->tu_state = TUS_GET; 641*12937Shelge uuc->tu_rbptr = (u_char *)data; 642*12937Shelge uuc->tu_rcnt = sizeof (*data); 643*12937Shelge uuc->tu_flag = 1; 64412332Shelge uuaddr->tcs = 0; /* disable transm. interrupts */ 64511876Shelge break; 64611876Shelge 64711876Shelge /* 64812332Shelge * Random interrupt 64911876Shelge */ 65011876Shelge default: 65111876Shelge break; 65211876Shelge } 653*12937Shelge } 654*12937Shelge 655*12937Shelge uuwatch() 656*12937Shelge { 657*12937Shelge register struct tu *uuc; 658*12937Shelge register struct uudevice *uuaddr; 659*12937Shelge struct uba_device *ui; 660*12937Shelge struct buf *bp, *uutab; 661*12937Shelge int s, ctlr, active = 0; 662*12937Shelge 663*12937Shelge for (ctlr=0; ctlr<NUU; ctlr++) { 664*12937Shelge int i; 665*12937Shelge 666*12937Shelge uuc = &uu_softc[ctlr]; 667*12937Shelge ui = uudinfo[ctlr]; 668*12937Shelge uuaddr = (struct uudevice *)ui->ui_addr; 669*12937Shelge uutab = &uitab[ctlr]; 670*12937Shelge if ((uuc->tu_dopen[0] == 0) && (uuc->tu_dopen[1] == 0) && 671*12937Shelge (uutab->b_active == 0)) { 672*12937Shelge uuc->tu_flag = 0; 673*12937Shelge uuaddr->rcs = 0; 674*12937Shelge continue; 675*12937Shelge } 676*12937Shelge active++; 677*12937Shelge if (uuc->tu_flag) 678*12937Shelge uuc->tu_flag++; 679*12937Shelge if (uuc->tu_flag <= 40) 680*12937Shelge continue; 681*12937Shelge printf("uu(%d): read stalled\n", ctlr); 682*12937Shelge printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt, 683*12937Shelge uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr, uuc->tu_count); 684*12937Shelge uuc->tu_flag = 0; 685*12937Shelge s = splx(UUIPL); 686*12937Shelge i = uuaddr->rdb; /* dummy */ 687*12937Shelge uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ 688*12937Shelge uuaddr->tcs = UUCS_INTR; 689*12937Shelge uuc->tu_state = TUS_IDLE; 690*12937Shelge if (!uutab->b_active) { 691*12937Shelge wakeup((caddr_t)uuc); 692*12937Shelge goto retry; 693*12937Shelge } 694*12937Shelge if (++uutab->b_errcnt <= 1) { 695*12937Shelge uustart(ui); 696*12937Shelge goto retry; 697*12937Shelge } 698*12937Shelge if (bp = uutab->b_actf) { 699*12937Shelge bp->b_flags |= B_ERROR; 700*12937Shelge if ((bp->b_flags&B_READ) == 0) 701*12937Shelge tu_vee(&pcnt[UNIT(minor(bp->b_dev))]); 702*12937Shelge iodone(bp); 703*12937Shelge } 704*12937Shelge retry: 705*12937Shelge (void) splx(s); 70611876Shelge } 707*12937Shelge if (active) 708*12937Shelge timeout(uuwatch, (caddr_t)0, hz); 709*12937Shelge else 710*12937Shelge uuwstart = 0; 711*12937Shelge return; 71211876Shelge } 71311876Shelge 714*12937Shelge #if !defined(VAX750) && !defined(VAX730) 71511876Shelge /* 71611876Shelge * Compute checksum TU58 fashion 71711876Shelge */ 71811876Shelge #ifdef lint 719*12937Shelge tuchk(word, cp, n) 72011876Shelge register word; 72111876Shelge register unsigned short *cp; 72211876Shelge int n; 72311876Shelge { 72411876Shelge register int c = n >> 1; 72511876Shelge register long temp; 72611876Shelge 72711876Shelge do { 72811876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 72911876Shelge word += temp; 73011876Shelge } while (--c > 0); 73111876Shelge if (n & 1) 73211876Shelge word += *(unsigned char *)cp; 73311876Shelge while (word & 0xffff0000) 73411876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 73511876Shelge return (word); 73611876Shelge } 73711876Shelge #else 738*12937Shelge tuchk(word0, wp, n) 73911896Shelge register int word0; /* r11 */ 74011896Shelge register char *wp; /* r10 */ 74111896Shelge register int n; /* r9 */ 74211876Shelge { 74311876Shelge asm("loop:"); 74411896Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 74511896Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 74611876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 74711896Shelge asm(" blbc r9,ok"); /* odd byte count? */ 74811896Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 74911896Shelge asm(" addw2 r10,r11"); /* add it in */ 75011896Shelge asm(" adwc $0,r11"); /* and the carry */ 75111876Shelge asm("ok:"); 75211896Shelge asm(" movl r11,r0"); /* return sum */ 75311876Shelge } 75411876Shelge #endif 75511876Shelge 756*12937Shelge tu_pee(cp) 75712332Shelge char *cp; 75812332Shelge { 75912332Shelge register int s; 76012332Shelge 76112857Shelge s = splx(UUIPL); 76212332Shelge if (++(*cp) > NTUQ) { 76312332Shelge sleep(cp, PRIBIO); 76411876Shelge } 76512332Shelge splx(s); 76612332Shelge } 76712332Shelge 768*12937Shelge tu_vee(cp) 76912332Shelge char *cp; 77012332Shelge { 77112332Shelge register int s; 77212332Shelge 77312857Shelge s = splx(UUIPL); 77412332Shelge if (--(*cp) <= NTUQ) { 77512332Shelge wakeup(cp); 77611876Shelge } 77711876Shelge splx(s); 77811876Shelge } 77911876Shelge #endif 78012332Shelge 781*12937Shelge uuioctl(dev, cmd, data, flag) 782*12937Shelge dev_t dev; 783*12937Shelge caddr_t data; 784*12937Shelge { 785*12937Shelge /* 786*12937Shelge * to be added later 787*12937Shelge */ 788*12937Shelge return (ENXIO); 789*12937Shelge } 790*12937Shelge 791*12937Shelge #endif 792*12937Shelge 793