1*12857Shelge /* uu.c 4.4 83/06/01 */ 211876Shelge 312332Shelge #include "uu.h" 4*12857Shelge #if NUU > 0 511876Shelge /* 611896Shelge * TU58 DECtape II/DL11 device driver 711876Shelge * 8*12857Shelge * ****** Warning: untested ****** 9*12857Shelge * 1011896Shelge * The TU58 * is treated as a block device (only). Error detection and 1111876Shelge * recovery is almost non-existant. It is assumed that the 1211876Shelge * TU58 will follow the RSP protocol exactly, very few protocol 1311896Shelge * errors are checked for. 1411876Shelge */ 1511896Shelge 1612332Shelge #include "../machine/pte.h" 1711896Shelge 1811876Shelge #include "../h/param.h" 1911876Shelge #include "../h/systm.h" 2011876Shelge #include "../h/buf.h" 2111876Shelge #include "../h/conf.h" 2212332Shelge #include "../h/time.h" 2311896Shelge #include "../h/kernel.h" 2411896Shelge #include "../h/errno.h" 2511896Shelge #include "../h/uio.h" 2611896Shelge #include "../h/file.h" 2711876Shelge 2811876Shelge #include "../vax/cpu.h" 2912332Shelge #include "../vax/nexus.h" 3012332Shelge 3111896Shelge #include "../vaxuba/ubavar.h" 3211896Shelge #include "../vaxuba/ubareg.h" 3311896Shelge #include "../vaxuba/uureg.h" 3411876Shelge 3512332Shelge #define printd if (uudebug) printf 3611876Shelge #ifdef printd 37*12857Shelge int uudebug = 0; /* printd */ 3811876Shelge #endif printd 3911876Shelge 4011876Shelge #define NTUBLK 512 /* number of blocks on a TU58 cassette */ 41*12857Shelge #define WRV 01 /* bit in minor dev => write w. read verify */ 4212332Shelge #define NDPC 02 /* drives per controller */ 43*12857Shelge #define NUX NDPC * NUU /* number of drives */ 4412332Shelge #define NTUQ 02 /* # of block which can be queued up */ 45*12857Shelge #define UMASK 01 /* unit number mask */ 46*12857Shelge #define UUIPL 04 /* ipl level to use */ 4711876Shelge 4811876Shelge /* 4911876Shelge * Structure of a command packet 5011876Shelge */ 5111876Shelge struct packet { 5211876Shelge u_char pk_flag; /* indicates packet type (cmd, data, etc.) */ 5311876Shelge u_char pk_mcount; /* length of packet (bytes) */ 5411876Shelge u_char pk_op; /* operation to perform (read, write, etc.) */ 5511876Shelge u_char pk_mod; /* modifier for op or returned status */ 5611876Shelge u_char pk_unit; /* unit number */ 5711876Shelge u_char pk_sw; /* switches */ 5811876Shelge u_short pk_seq; /* sequence number, always zero */ 5911876Shelge u_short pk_count; /* requested byte count for read or write */ 6011876Shelge u_short pk_block; /* block number for read, write, or seek */ 6111876Shelge u_short pk_chksum; /* checksum, by words with end around carry */ 6211876Shelge }; 6311876Shelge 64*12857Shelge struct packet uucmd[NUU]; /* a command sent to the TU58 */ 65*12857Shelge struct packet uudata[NUU]; /* a command or data returned from TU58 */ 66*12857Shelge struct buf uitab[NUU]; /* buffer queue headers */ 6711876Shelge 6811876Shelge /* 6911896Shelge * per controller state information 7011876Shelge */ 7111896Shelge struct uu_ctlr { 7211896Shelge u_char *uu_rbptr; /* pointer to buffer for read */ 7311896Shelge int uu_rcnt; /* how much to read */ 7411896Shelge u_char *uu_wbptr; /* pointer to buffer for write */ 7511896Shelge int uu_wcnt; /* how much to write */ 7611896Shelge int uu_state; /* current uu_state of tansfer operation */ 7711896Shelge int uu_flag; /* read in progress flag */ 7811896Shelge char *uu_addr; /* real buffer data address */ 7911896Shelge int uu_count; /* real requested count */ 8011896Shelge int uu_serrs; /* count of soft errors */ 8111896Shelge int uu_cerrs; /* count of checksum errors */ 8211896Shelge int uu_herrs; /* count of hard errors */ 8311896Shelge char uu_dopen[NDPC]; /* drive is open */ 84*12857Shelge } uu_ctlr[NUU]; 8511876Shelge 8611876Shelge /* 8711896Shelge * controller states 8811876Shelge */ 8911896Shelge #define UUS_INIT1 0 /* sending nulls */ 9011896Shelge #define UUS_INIT2 1 /* sending inits */ 9111896Shelge #define UUS_IDLE 2 /* initialized, no transfer in progress */ 9211896Shelge #define UUS_SENDH 3 /* sending header */ 9311896Shelge #define UUS_SENDD 4 /* sending data */ 9411896Shelge #define UUS_SENDC 5 /* sending checksum */ 9511896Shelge #define UUS_SENDR 6 /* sending read command packet */ 9611896Shelge #define UUS_SENDW 7 /* sending write command packet */ 9711896Shelge #define UUS_GETH 8 /* reading header */ 9811896Shelge #define UUS_GETD 9 /* reading data */ 9911896Shelge #define UUS_GETC 10 /* reading checksum */ 10011896Shelge #define UUS_GET 11 /* reading an entire packet */ 10111896Shelge #define UUS_WAIT 12 /* waiting for continue */ 10211876Shelge 10311896Shelge #define UUS_NSTATES 13 10411896Shelge char *uustates[UUS_NSTATES] = { 10511876Shelge "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", 10611876Shelge "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT" 10711876Shelge }; 10812332Shelge 109*12857Shelge #define UNIT(dev) (minor(dev)>>1) 11011876Shelge #define printstate(state) \ 11111896Shelge if ((state) < UUS_NSTATES) \ 11211896Shelge printf("%s", uustates[(state)]); \ 11311876Shelge else \ 11411876Shelge printf("%d", (state)); 11511876Shelge 11611876Shelge /* 11711876Shelge * Packet Flags 11811876Shelge */ 11911876Shelge #define TUF_DATA 1 /* data packet */ 12011876Shelge #define TUF_CMD 2 /* command packet */ 12111876Shelge #define TUF_INITF 4 /* initialize */ 12211876Shelge #define TUF_CONT 020 /* continue */ 12311876Shelge #define TUF_XOFF 023 /* flow control */ 12411876Shelge 12511876Shelge /* 12611876Shelge * Op Codes 12711876Shelge */ 12811896Shelge #define TUOP_NOOP 0 /* no operation */ 12911876Shelge #define TUOP_INIT 1 /* initialize */ 13011876Shelge #define TUOP_READ 2 /* read block */ 13111876Shelge #define TUOP_WRITE 3 /* write block */ 13211876Shelge #define TUOP_SEEK 5 /* seek to block */ 13311896Shelge #define TUOP_DIAGNOSE 7 /* run micro-diagnostics */ 13411876Shelge #define TUOP_END 0100 /* end packet */ 13511876Shelge 13611876Shelge /* 13711876Shelge * Mod Flags 13811876Shelge */ 13911876Shelge #define TUMD_WRV 1 /* write with read verify */ 14011876Shelge 14111876Shelge /* 14211876Shelge * Switches 14311876Shelge */ 14411876Shelge 14511896Shelge u_char uunull[2] = { 0, 0 }; /* nulls to send for initialization */ 14611896Shelge u_char uuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ 14711876Shelge 14811896Shelge struct uba_device *uudinfo[NUU]; 14911896Shelge 150*12857Shelge int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch(); 151*12857Shelge u_short uustd[] = { 0176500 }; 152*12857Shelge struct uba_driver uudriver = 153*12857Shelge { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo }; 15411896Shelge 15511896Shelge int uuwstart; 156*12857Shelge static char pcnt[NUX]; /* pee/vee counters */ 15711896Shelge 15811876Shelge /*ARGSUSED*/ 15911896Shelge uuprobe(reg) 16011896Shelge caddr_t reg; 16111876Shelge { 16211896Shelge register int br, cvec; /* value result */ 16311896Shelge struct uudevice *uuaddr = (struct uudevice *)reg; 16411896Shelge int i; 16511876Shelge 16611876Shelge #ifdef lint 16711896Shelge br = 0; cvec = br; br = cvec; 16811896Shelge uurintr(0); uuxintr(0); 16911876Shelge #endif 170*12857Shelge uuaddr->tcs = UUCS_INTR; 171*12857Shelge DELAY(1000); 172*12857Shelge uuaddr->tcs = 0; 173*12857Shelge cvec -= 4; /* since we are using the xmitter intrpt */ 17411896Shelge return(sizeof (*uuaddr)); 17511896Shelge } 17611896Shelge 17711896Shelge uuattach(ui) 178*12857Shelge register struct uba_device *ui; 17911896Shelge { 18011896Shelge } 18111896Shelge 18211896Shelge /*ARGSUSED1*/ 18311896Shelge uuopen(dev, flag) 18411896Shelge dev_t dev; 18511896Shelge int flag; 18611896Shelge { 18711896Shelge register struct uba_device *ui; 18811896Shelge register struct uu_ctlr *uuc; 18911896Shelge register struct uudevice *uuaddr; 19012332Shelge int ctlr, unit = UNIT(dev), s; 19111896Shelge 192*12857Shelge ctlr = unit / NDPC; 193*12857Shelge if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0) 19411876Shelge return (ENXIO); 19511896Shelge uuc = &uu_ctlr[ctlr]; 196*12857Shelge if (uuc->uu_dopen[unit&UMASK]) 19711896Shelge return (EBUSY); 19811896Shelge if (uuwstart++ == 0) 19911896Shelge timeout(uuwatch, (caddr_t)0, hz); 20011896Shelge 201*12857Shelge uuc->uu_dopen[unit&UMASK]++; 202*12857Shelge uuaddr = (struct uudevice *)ui->ui_addr; 203*12857Shelge s = splx(UUIPL); 20411876Shelge /* 20511896Shelge * If the unit already initialized, 20611876Shelge * just enable interrupts and return. 20711876Shelge */ 20812332Shelge if (uuc->uu_state == UUS_IDLE) { 20911896Shelge uuaddr->rcs = UUCS_INTR; 210*12857Shelge (void) splx(s); 21111876Shelge return (0); 21211876Shelge } 21311876Shelge 21411876Shelge /* 21511876Shelge * Must initialize, reset the cassette 21611876Shelge * and wait for things to settle down. 21711876Shelge */ 21811896Shelge uureset(ctlr); 21911896Shelge sleep((caddr_t)uuc, PZERO+1); 220*12857Shelge uitab[ctlr].b_active = NULL; 22112332Shelge if (uuc->uu_state != UUS_IDLE) { 22212332Shelge uuc->uu_state = UUS_INIT1; 223*12857Shelge uuc->uu_dopen[unit&UMASK] = 0; 22412332Shelge uuc->uu_rcnt = uuc->uu_wcnt = 0; 22511896Shelge uuaddr->rcs = 0; 22611896Shelge uuaddr->tcs = 0; 22711896Shelge splx(s); 22811896Shelge return (ENXIO); 22911876Shelge } 23011876Shelge splx(s); 23111876Shelge return (0); 23211876Shelge } 23311876Shelge 23411896Shelge uuclose(dev, flag) 23511896Shelge dev_t dev; 23611896Shelge int flag; 23711876Shelge { 23811896Shelge register struct uu_ctlr *uuc; 239*12857Shelge int unit = UNIT(dev); 24011876Shelge 24112332Shelge uuwstart--; 242*12857Shelge uuc = &uu_ctlr[unit%NDPC]; 24311896Shelge if (uuc->uu_serrs + uuc->uu_cerrs + uuc->uu_herrs != 0) { 24411876Shelge /* 24511876Shelge * A tu58 is like nothing ever seen before; 24611876Shelge * I guess this is appropriate then... 24711876Shelge */ 24811876Shelge uprintf( 249*12857Shelge "uu%d: %d soft errors, %d checksum errors, %d hard errors\n", 250*12857Shelge unit, uuc->uu_serrs, uuc->uu_cerrs, uuc->uu_herrs); 25111896Shelge uuc->uu_serrs = uuc->uu_cerrs = uuc->uu_herrs = 0; 25211876Shelge } 253*12857Shelge uuc->uu_dopen[unit%NDPC] = 0; 25411876Shelge } 25511876Shelge 25611896Shelge uureset(ctlr) 25711896Shelge int ctlr; 25811876Shelge { 25912332Shelge register struct uu_ctlr *uuc = &uu_ctlr[ctlr]; 26012332Shelge register struct packet *cmd = &uucmd[ctlr]; 261*12857Shelge struct uba_device *ui = uudinfo[ctlr]; 262*12857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 26311876Shelge 264*12857Shelge printf ("uureset\n"); 265*12857Shelge uitab[ctlr].b_active++; 26612332Shelge uuc->uu_state = UUS_INIT1; 26711896Shelge uuc->uu_wbptr = uunull; 26811896Shelge uuc->uu_wcnt = sizeof (uunull); 26911896Shelge cmd->pk_flag = TUF_CMD; 27012332Shelge cmd->pk_mcount = sizeof (*cmd) - 4; 27111896Shelge cmd->pk_mod = 0; 27211896Shelge cmd->pk_seq = 0; 27312332Shelge cmd->pk_sw = 0; 27411896Shelge uuaddr->rcs = 0; 27511896Shelge uuaddr->tcs = UUCS_INTR | UUCS_BREAK; 27611896Shelge uuxintr(ctlr); /* start output */ 27711876Shelge } 27811876Shelge 27911876Shelge /* 28011876Shelge * Strategy routine for block I/O 28111876Shelge */ 28211896Shelge uustrategy(bp) 28311876Shelge register struct buf *bp; 28411876Shelge { 28512332Shelge register struct buf *uutab; 28611896Shelge struct uba_device *ui; 287*12857Shelge int s, unit = UNIT(minor(bp->b_dev)); 28811876Shelge 289*12857Shelge if (unit > NUX) 29011896Shelge goto bad; 29111896Shelge if (bp->b_blkno >= NTUBLK) 29211896Shelge goto bad; 293*12857Shelge ui = uudinfo[unit/NDPC]; 29411896Shelge if (ui == 0 || ui->ui_alive == 0) 29511896Shelge goto bad; 296*12857Shelge uutab = &uitab[unit/NDPC]; /* one request queue per controller */ 29712332Shelge if ((bp->b_flags&B_READ) == 0) 298*12857Shelge uu_pee(&pcnt[unit]); 299*12857Shelge printf("uustrat: unit=%d, bp=%x\n", unit, bp); 300*12857Shelge s = splx(UUIPL); 301*12857Shelge bp->b_forw = NULL; 30212332Shelge if (uutab->b_actf == NULL) 30312332Shelge uutab->b_actf = bp; 30412332Shelge else 305*12857Shelge uutab->b_actl->b_forw = bp; 30612332Shelge uutab->b_actl = bp; 30712332Shelge if (uutab->b_active == 0) 308*12857Shelge uustart(ui); 30911876Shelge splx(s); 31011896Shelge return; 31111896Shelge 31211896Shelge bad: 31311896Shelge bp->b_flags |= B_ERROR; 31412332Shelge bp->b_error = ENXIO; 31511896Shelge iodone(bp); 31611896Shelge return; 31711876Shelge } 31811876Shelge 31911876Shelge /* 32011876Shelge * Start the transfer 32111876Shelge */ 322*12857Shelge uustart(ui) 323*12857Shelge register struct uba_device *ui; 32411876Shelge { 32511876Shelge register struct buf *bp; 32611896Shelge register struct uu_ctlr *uuc; 32711896Shelge struct packet *cmd; 328*12857Shelge int ctlr = ui->ui_unit; 32911876Shelge 330*12857Shelge if ((bp = uitab[ctlr].b_actf) == NULL) 33111876Shelge return; 33212332Shelge uuc = &uu_ctlr[ctlr]; 33312332Shelge cmd = &uucmd[ctlr]; 33412332Shelge if (uuc->uu_state != UUS_IDLE) { 33512332Shelge uureset(ctlr); 33611876Shelge return; 33711876Shelge } 338*12857Shelge uitab[ctlr].b_active++; 33911896Shelge cmd->pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE; 34011896Shelge cmd->pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ? 34111876Shelge TUMD_WRV : 0; 342*12857Shelge cmd->pk_unit = UNIT(minor(bp->b_dev)); 34312332Shelge cmd->pk_sw = 0; 34412332Shelge cmd->pk_count = uuc->uu_count = bp->b_bcount; 34511896Shelge cmd->pk_block = bp->b_blkno; 34611896Shelge cmd->pk_chksum = 34712332Shelge uuchk(*((short *)cmd), (u_short *)&cmd->pk_op, 34812332Shelge (int)cmd->pk_mcount); 34912332Shelge uuc->uu_state = bp->b_flags&B_READ ? UUS_SENDR : UUS_SENDW; 35011896Shelge uuc->uu_addr = bp->b_un.b_addr; 35111896Shelge uuc->uu_count = bp->b_bcount; 35212332Shelge uuc->uu_wbptr = (u_char *)cmd; 35312332Shelge uuc->uu_wcnt = sizeof (*cmd); 35412332Shelge uuxintr(ctlr); 35511876Shelge } 35611876Shelge 35711876Shelge /* 35811876Shelge * TU58 receiver interrupt 35911876Shelge */ 36012332Shelge uurintr(ctlr) 36112332Shelge int ctlr; 36211876Shelge { 363*12857Shelge struct uba_device *ui = uudinfo[ctlr]; 36412332Shelge register struct uu_ctlr *uuc = &uu_ctlr[ctlr]; 365*12857Shelge register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; 366*12857Shelge register struct buf *uutab = &uitab[ctlr]; 367*12857Shelge register struct buf *bp = uutab->b_actf; 36812332Shelge struct packet *data, *cmd; 369*12857Shelge int c, unit = UNIT(minor(bp->b_dev)); 37011876Shelge 371*12857Shelge c = uuaddr->rdb; 372*12857Shelge /* 373*12857Shelge * We may have a stray interrupt, but read 374*12857Shelge * the data anyway, otherwise we'll get an overrun 375*12857Shelge * next time 376*12857Shelge */ 377*12857Shelge if (uutab->b_active == 0) 37812332Shelge return; 37912332Shelge cmd = &uucmd[ctlr]; 38012332Shelge if (c & UURDB_ERROR) { 38112332Shelge if (c & UURDB_ORUN) { 382*12857Shelge printf("uu%d: data overrun (ignored)\n", unit); 38312332Shelge } else { 38412332Shelge printf("uu%d: break received, device reset, state=", 385*12857Shelge unit); 38612332Shelge printstate(uuc->uu_state); 38712332Shelge uureset(ctlr); 38812332Shelge printf("\n"); 38912332Shelge return; 39012332Shelge } 39111876Shelge } 392*12857Shelge data = &uudata[ctlr]; 39312332Shelge top: 39412332Shelge c &= 0xff; 39512332Shelge if (uuc->uu_rcnt) { /* still waiting for data? */ 39612332Shelge *uuc->uu_rbptr++ = c; /* yup, put it there */ 39712332Shelge if (--uuc->uu_rcnt) /* decrement count, any left? */ 39811876Shelge return; /* get some more */ 39911876Shelge } 40011876Shelge 40111876Shelge /* 40211876Shelge * We got all the data we were expecting for now, 40311896Shelge * switch on the uu_state of the transfer. 40411876Shelge */ 40512332Shelge switch(uuc->uu_state) { 40611876Shelge 40711876Shelge /* 40811876Shelge * If we get an unexpected "continue", 40911876Shelge * start all over again... 41011876Shelge */ 41112332Shelge case UUS_INIT2: 41212332Shelge uuc->uu_state = c == TUF_CONT ? UUS_IDLE : UUS_INIT1; 41312332Shelge uuc->uu_flag = 0; 41412332Shelge wakeup((caddr_t)uuc); 415*12857Shelge uustart(ui); 41611876Shelge break; 41711876Shelge 41811876Shelge /* 41911876Shelge * Only transition from this state 42011876Shelge * is on a "continue", so if we don't 42111876Shelge * get it, reset the world. 42211876Shelge */ 42312332Shelge case UUS_WAIT: /* waiting for continue */ 42412332Shelge switch(c) { 42512332Shelge case TUF_CONT: /* got the expected continue */ 42612332Shelge uuc->uu_flag = 0; 42712332Shelge data->pk_flag = TUF_DATA; 42812332Shelge data->pk_mcount = MIN(128, uuc->uu_count); 42912332Shelge data->pk_chksum = 43012332Shelge tuchk(*((short *)data), (caddr_t)uuc->uu_addr, 43112332Shelge (int)data->pk_mcount); 43212332Shelge uuc->uu_state = UUS_SENDH; 43312332Shelge uuc->uu_wbptr = (u_char *)data; 43412332Shelge uuc->uu_wcnt = 2; 435*12857Shelge uuxintr(ctlr); 43611876Shelge break; 43712332Shelge 43812332Shelge case TUF_CMD: /* sending us an END packet...error */ 43912332Shelge uuc->uu_state = UUS_GET; 44012332Shelge uuc->uu_rbptr = (u_char *) data; 44112332Shelge uuc->uu_rcnt = sizeof (*data); 44212332Shelge uuc->uu_flag = 1; 44312332Shelge uuaddr->tcs = 0; 44412332Shelge goto top; 44512332Shelge 44612332Shelge case TUF_INITF: 447*12857Shelge uureset(ctlr); 44812332Shelge break; 44912332Shelge 45012332Shelge default: /* something random...bad news */ 45112332Shelge uuc->uu_state = UUS_INIT1; 45212332Shelge break; 45311876Shelge } 45411876Shelge break; 45511876Shelge 45612332Shelge case UUS_SENDW: 45711876Shelge if (c != TUF_CONT) 45811876Shelge goto bad; 45912332Shelge uureset(ctlr); 46011876Shelge break; 46111876Shelge 46211876Shelge /* 46311876Shelge * Got header, now get data; amount to 46411896Shelge * fetch is included in packet. 46511876Shelge */ 46612332Shelge case UUS_GETH: 46712332Shelge if (data->pk_flag == TUF_DATA) 46812332Shelge uuc->uu_rbptr = (u_char *)uuc->uu_addr; 46912332Shelge uuc->uu_rcnt = data->pk_mcount; 47012332Shelge uuc->uu_state = UUS_GETD; 47111876Shelge break; 47211876Shelge 47311876Shelge /* 47411876Shelge * Got the data, now fetch the checksum. 47511876Shelge */ 47612332Shelge case UUS_GETD: 47712332Shelge uuc->uu_rbptr = (u_char *)&data->pk_chksum; 47812332Shelge uuc->uu_rcnt = sizeof (data->pk_chksum); 47912332Shelge uuc->uu_state = UUS_GETC; 48011876Shelge break; 48111876Shelge 48212332Shelge case UUS_GET: 48312332Shelge case UUS_GETC: 48411876Shelge /* got entire packet */ 48511876Shelge #ifdef notdef 48612332Shelge if (data->pk_chksum != 48712332Shelge uuchk(*((short *)data), (u_short *) 48812332Shelge (data->pk_flag == TUF_DATA ? uuc->uu_addr : &data->pk_op), 48912332Shelge (int)data->pk_mcount)) 49012332Shelge uuc->uu_cerrs++; 49111876Shelge #endif 49212332Shelge if (data->pk_flag == TUF_DATA) { 49311876Shelge /* data packet, advance to next */ 49412332Shelge uuc->uu_addr += data->pk_mcount; 49512332Shelge uuc->uu_count -= data->pk_mcount; 49612332Shelge uuc->uu_state = UUS_GETH; 49712332Shelge uuc->uu_rbptr = (u_char *)data; /* next packet */ 49812332Shelge uuc->uu_rcnt = 2; 49912332Shelge } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { 50011876Shelge /* end packet, idle and reenable transmitter */ 50112332Shelge uuc->uu_state = UUS_IDLE; 50212332Shelge uuc->uu_flag = 0; 50312332Shelge uuaddr->rcs = UUCS_INTR; 50411876Shelge printd("ON "); 50512332Shelge if (bp == NULL) { 506*12857Shelge printf("uu(%d): no bp, active %d\n", 507*12857Shelge uitab[ctlr].b_active); 508*12857Shelge uustart(ui); 50911876Shelge return; 51011876Shelge } 51112332Shelge if (data->pk_mod > 1) { /* hard error */ 51211876Shelge bp->b_flags |= B_ERROR; 51312332Shelge uuc->uu_herrs++; 51411896Shelge harderr(bp, "uu"); 51512332Shelge printf(" pk_mod %o\n", data->pk_mod&0xff); 51612332Shelge } else if (data->pk_mod != 0) /* soft error */ 51712332Shelge uuc->uu_serrs++; 51812332Shelge uutab->b_active = NULL; 519*12857Shelge uutab->b_actf = bp->b_forw; 52012332Shelge bp->b_resid = uuc->uu_count; 52111876Shelge if ((bp->b_flags&B_READ) == 0) 522*12857Shelge uu_vee(&pcnt[unit]); 52311876Shelge iodone(bp); 524*12857Shelge uustart(ui); 52511876Shelge } else { 52611876Shelge printf("neither data nor end: %o %o\n", 52712332Shelge data->pk_flag&0xff, data->pk_op&0xff); 52812332Shelge uuaddr->rcs = 0; /* flush the rest */ 52912332Shelge uuc->uu_state = UUS_INIT1; 53011876Shelge } 53111876Shelge break; 53211876Shelge 53312332Shelge case UUS_IDLE: 53412332Shelge case UUS_INIT1: 53511876Shelge break; 53611876Shelge 53711876Shelge default: 53811876Shelge bad: 53911876Shelge if (c == TUF_INITF) { 540*12857Shelge printf("uu%d protocol error, state=", unit); 54112332Shelge printstate(uuc->uu_state); 54211876Shelge printf(", op=%x, cnt=%d, block=%d\n", 54312332Shelge cmd->pk_op, cmd->pk_count, cmd->pk_block); 54412332Shelge uutab->b_active = NULL; 54512332Shelge if (bp = uutab->b_actf) { 54611876Shelge bp->b_flags |= B_ERROR; 547*12857Shelge uutab->b_actf = bp->b_forw; 54811876Shelge if ((bp->b_flags&B_READ) == 0) 549*12857Shelge uu_vee(&pcnt[unit]); 55011876Shelge iodone(bp); 55111876Shelge } 55212332Shelge uuc->uu_state = UUS_INIT1; 55311876Shelge } else { 55412332Shelge printf("uu%d receive state error, state=", 555*12857Shelge unit); 55612332Shelge printstate(uuc->uu_state); 55711876Shelge printf(", byte=%x\n", c); 55811876Shelge #ifdef notdef 559*12857Shelge uuc->uu_state = UUS_INIT1; 56011876Shelge #endif 56112332Shelge wakeup((caddr_t)uuc); 56211876Shelge } 56311876Shelge } 56411876Shelge } 56511876Shelge 56611876Shelge /* 56711876Shelge * TU58 transmitter interrupt 56811876Shelge */ 56912332Shelge uuxintr(ctlr) 57012332Shelge int ctlr; 57111876Shelge { 57212332Shelge register struct uu_ctlr *uuc = &uu_ctlr[ctlr]; 573*12857Shelge register struct uudevice *uuaddr; 57412332Shelge register struct packet *data; 575*12857Shelge struct uba_device *ui = uudinfo[ctlr]; 57612332Shelge int c; 57711876Shelge 578*12857Shelge data = &uudata[ctlr]; 579*12857Shelge uuaddr = (struct uudevice *) ui->ui_addr; 58011876Shelge top: 58112332Shelge if (uuc->uu_wcnt) { 58211876Shelge /* still stuff to send, send one byte */ 58312332Shelge while ((uuaddr->tcs & UUCS_READY) == 0) 58411876Shelge ; 58512332Shelge uuaddr->tdb = *uuc->uu_wbptr++; 58612332Shelge uuc->uu_wcnt--; 58711876Shelge return; 58811876Shelge } 58911876Shelge 59011876Shelge /* 59111876Shelge * Last message byte was sent out. 59211896Shelge * Switch on uu_state of transfer. 59311876Shelge */ 59411896Shelge if (uudebug) { 59511896Shelge printf("uuxintr: state="); 59612332Shelge printstate(uuc->uu_state); 59711876Shelge } 59812332Shelge switch(uuc->uu_state) { 59911876Shelge 60011876Shelge /* 60111876Shelge * Two nulls have been sent, remove break, and send inits 60211876Shelge */ 60312332Shelge case UUS_INIT1: 60412332Shelge uuaddr->tcs = UUCS_INTR; 60511876Shelge printd("ON2 "); 60612332Shelge uuc->uu_state = UUS_INIT2; 60712332Shelge uuc->uu_wbptr = uuinit; 60812332Shelge uuc->uu_wcnt = sizeof (uuinit); 60911876Shelge goto top; 61011876Shelge 61111876Shelge /* 61211876Shelge * Inits have been sent, wait for a continue msg. 61311876Shelge */ 61412332Shelge case UUS_INIT2: 615*12857Shelge c = uuaddr->rdb; /* prevent overrun error */ 61612332Shelge uuaddr->rcs = UUCS_INTR; 61712332Shelge uuc->uu_flag = 1; 61811876Shelge break; 61911876Shelge 62012332Shelge case UUS_IDLE: /* stray interrupt? */ 62111876Shelge break; 62211876Shelge 62311876Shelge /* 62411876Shelge * Read cmd packet sent, get ready for data 62511876Shelge */ 62612332Shelge case UUS_SENDR: 62712332Shelge uuc->uu_state = UUS_GETH; 62812332Shelge uuc->uu_rbptr = (u_char *)data; 62912332Shelge uuc->uu_rcnt = 2; 63012332Shelge uuc->uu_flag = 1; 63112332Shelge uuaddr->tcs = 0; /* disable transmitter interrupts */ 63211876Shelge printd("OFF "); 63311876Shelge break; 63411876Shelge 63511876Shelge /* 63611876Shelge * Write cmd packet sent, wait for continue 63711876Shelge */ 63812332Shelge case UUS_SENDW: 63912332Shelge uuc->uu_state = UUS_WAIT; 64012332Shelge uuc->uu_flag = 1; 64112332Shelge if ((uuaddr->rcs&UUCS_INTR) == 0) { 64211876Shelge printf("NO IE\n"); 64312332Shelge uuaddr->rcs = UUCS_INTR; 64411876Shelge } 64511876Shelge break; 64611876Shelge 64711876Shelge /* 64811876Shelge * Header sent, send data. 64911876Shelge */ 65012332Shelge case UUS_SENDH: 65112332Shelge uuc->uu_state = UUS_SENDD; 65212332Shelge uuc->uu_wbptr = (u_char *)uuc->uu_addr; 65312332Shelge uuc->uu_wcnt = data->pk_mcount; 65411876Shelge goto top; 65511876Shelge 65611876Shelge /* 65711876Shelge * Data sent, follow with checksum. 65811876Shelge */ 65912332Shelge case UUS_SENDD: 66012332Shelge uuc->uu_state = UUS_SENDC; 66112332Shelge uuc->uu_wbptr = (u_char *)&data->pk_chksum; 66212332Shelge uuc->uu_wcnt = sizeof (data->pk_chksum); 66311876Shelge goto top; 66411876Shelge 66511876Shelge /* 66611876Shelge * Checksum sent, wait for continue. 66711876Shelge */ 66812332Shelge case UUS_SENDC: 66911876Shelge /* 67011876Shelge * Updata buffer address and count. 67111876Shelge */ 67212332Shelge uuc->uu_addr += data->pk_mcount; 67312332Shelge uuc->uu_count -= data->pk_mcount; 67412332Shelge if (uuc->uu_count) { 67512332Shelge uuc->uu_state = UUS_WAIT; 67612332Shelge uuc->uu_flag = 1; 67711876Shelge break; 67811876Shelge } 67911876Shelge 68011876Shelge /* 68111876Shelge * End of transmission, get ready for end packet. 68211876Shelge */ 68312332Shelge uuc->uu_state = UUS_GET; 68412332Shelge uuc->uu_rbptr = (u_char *)data; 68512332Shelge uuc->uu_rcnt = sizeof (*data); 68612332Shelge uuc->uu_flag = 1; 68712332Shelge uuaddr->tcs = 0; /* disable transm. interrupts */ 68811876Shelge printd("OFF2 "); 68911876Shelge break; 69011876Shelge 69111876Shelge /* 69212332Shelge * Random interrupt 69311876Shelge */ 69411876Shelge default: 69511876Shelge break; 69611876Shelge } 69711896Shelge if (uudebug) { 69811896Shelge printd(" new uu_state="); 69912332Shelge printstate(uuc->uu_state); 700*12857Shelge printf("\n"); 70111876Shelge } 70211876Shelge } 70311876Shelge 70411876Shelge /* 70511876Shelge * Compute checksum TU58 fashion 70611876Shelge */ 70711876Shelge #ifdef lint 70811896Shelge uuchk(word, cp, n) 70911876Shelge register word; 71011876Shelge register unsigned short *cp; 71111876Shelge int n; 71211876Shelge { 71311876Shelge register int c = n >> 1; 71411876Shelge register long temp; 71511876Shelge 71611876Shelge do { 71711876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 71811876Shelge word += temp; 71911876Shelge } while (--c > 0); 72011876Shelge if (n & 1) 72111876Shelge word += *(unsigned char *)cp; 72211876Shelge while (word & 0xffff0000) 72311876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 72411876Shelge return (word); 72511876Shelge } 72611876Shelge #else 72711896Shelge uuchk(word0, wp, n) 72811896Shelge register int word0; /* r11 */ 72911896Shelge register char *wp; /* r10 */ 73011896Shelge register int n; /* r9 */ 73111876Shelge { 73211876Shelge asm("loop:"); 73311896Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 73411896Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 73511876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 73611896Shelge asm(" blbc r9,ok"); /* odd byte count? */ 73711896Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 73811896Shelge asm(" addw2 r10,r11"); /* add it in */ 73911896Shelge asm(" adwc $0,r11"); /* and the carry */ 74011876Shelge asm("ok:"); 74111896Shelge asm(" movl r11,r0"); /* return sum */ 74211876Shelge } 74311876Shelge #endif 74411876Shelge 74511896Shelge uuwatch() 74611876Shelge { 74712332Shelge register struct uu_ctlr *uuc; 74812332Shelge register struct uudevice *uuaddr; 749*12857Shelge struct uba_device *ui; 75012332Shelge struct buf *bp, *uutab; 75112332Shelge int s; 75211876Shelge 75312332Shelge if (uuwstart == 0) 75411876Shelge return; 755*12857Shelge for (s=0; s<NUU; s++) { 75612332Shelge int i; 75712332Shelge 75812332Shelge uuc = &uu_ctlr[s]; 759*12857Shelge ui = uudinfo[s]; 76012332Shelge if (uuc->uu_flag) 76112332Shelge uuc->uu_flag++; 76212332Shelge if (uuc->uu_flag <= 40) 76312332Shelge continue; 76412332Shelge printf("uu%d: read stalled\n", s); 76512332Shelge printf("%X %X %X %X %X %X %X %X\n", uuc->uu_rbptr, uuc->uu_rcnt, 76612332Shelge uuc->uu_wbptr, uuc->uu_wcnt, uuc->uu_state, uuc->uu_flag, 76712332Shelge uuc->uu_addr, uuc->uu_count); 76812332Shelge uuc->uu_flag = 0; 769*12857Shelge uuaddr = (struct uudevice *)ui->ui_addr; 770*12857Shelge uutab = &uitab[s]; 77112332Shelge i = uuaddr->rdb; /* dummy */ 77212332Shelge uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ 77312332Shelge uuaddr->tcs = UUCS_INTR; 77412332Shelge uuc->uu_state = UUS_IDLE; 77512332Shelge if (!uutab->b_active) { 77612332Shelge wakeup((caddr_t)uuc); 77712332Shelge continue; 77812332Shelge } 77912332Shelge if (++uutab->b_errcnt <= 1) { 780*12857Shelge uustart(ui); 78112332Shelge continue; 78212332Shelge } 78312332Shelge if (bp = uutab->b_actf) { 78412332Shelge bp->b_flags |= B_ERROR; 78512332Shelge if ((bp->b_flags&B_READ) == 0) 786*12857Shelge uu_vee(&pcnt[UNIT(minor(bp->b_dev))]); 78712332Shelge iodone(bp); 78812332Shelge } 78911876Shelge } 79012332Shelge timeout(uuwatch, (caddr_t)0, hz); 79112332Shelge return; 79212332Shelge } 79312332Shelge 794*12857Shelge 795*12857Shelge uuioctl(dev, cmd, data, flag) 796*12857Shelge dev_t dev; 797*12857Shelge caddr_t data; 798*12857Shelge { 799*12857Shelge /* 800*12857Shelge * to be added later 801*12857Shelge */ 802*12857Shelge return (ENXIO); 803*12857Shelge } 804*12857Shelge 80512332Shelge uu_pee(cp) 80612332Shelge char *cp; 80712332Shelge { 80812332Shelge register int s; 80912332Shelge 810*12857Shelge s = splx(UUIPL); 81112332Shelge if (++(*cp) > NTUQ) { 81212332Shelge sleep(cp, PRIBIO); 81311876Shelge } 81412332Shelge splx(s); 81512332Shelge } 81612332Shelge 81712332Shelge uu_vee(cp) 81812332Shelge char *cp; 81912332Shelge { 82012332Shelge register int s; 82112332Shelge 822*12857Shelge s = splx(UUIPL); 82312332Shelge if (--(*cp) <= NTUQ) { 82412332Shelge wakeup(cp); 82511876Shelge } 82611876Shelge splx(s); 82711876Shelge } 82811876Shelge #endif 82912332Shelge 830