1*12332Shelge /* uu.c 4.3 83/05/08 */ 211876Shelge 3*12332Shelge #include "uu.h" 411896Shelge #if NDL > 0 511876Shelge /* 611896Shelge * TU58 DECtape II/DL11 device driver 7*12332Shelge * (based on a driver written by Mike Obrien @ RAND) 811876Shelge * 911896Shelge * The TU58 * is treated as a block device (only). Error detection and 1011876Shelge * recovery is almost non-existant. It is assumed that the 1111876Shelge * TU58 will follow the RSP protocol exactly, very few protocol 1211896Shelge * errors are checked for. 1311876Shelge */ 1411896Shelge 15*12332Shelge #include "../machine/pte.h" 1611896Shelge 1711876Shelge #include "../h/param.h" 1811876Shelge #include "../h/systm.h" 1911876Shelge #include "../h/buf.h" 2011876Shelge #include "../h/conf.h" 21*12332Shelge #include "../h/time.h" 2211896Shelge #include "../h/kernel.h" 2311896Shelge #include "../h/errno.h" 2411896Shelge #include "../h/uio.h" 2511896Shelge #include "../h/file.h" 2611876Shelge 2711876Shelge #include "../vax/cpu.h" 28*12332Shelge #include "../vax/nexus.h" 29*12332Shelge 3011896Shelge #include "../vaxuba/ubavar.h" 3111896Shelge #include "../vaxuba/ubareg.h" 3211896Shelge #include "../vaxuba/uureg.h" 3311876Shelge 34*12332Shelge #define printd if (uudebug) printf 3511876Shelge #ifdef printd 36*12332Shelge int uudebug; /* printd */ 3711876Shelge #endif printd 3811876Shelge 3911876Shelge #define NTUBLK 512 /* number of blocks on a TU58 cassette */ 4011896Shelge #define WRV 02 /* bit in minor dev => write w. read verify */ 41*12332Shelge #define NDPC 02 /* drives per controller */ 42*12332Shelge #define NUU NDPC * NDL /* number of drives */ 43*12332Shelge #define DNUM 01 /* mask for drive number */ 44*12332Shelge #define NTUQ 02 /* # of block which can be queued up */ 4511876Shelge 4611876Shelge /* 4711876Shelge * Structure of a command packet 4811876Shelge */ 4911876Shelge struct packet { 5011876Shelge u_char pk_flag; /* indicates packet type (cmd, data, etc.) */ 5111876Shelge u_char pk_mcount; /* length of packet (bytes) */ 5211876Shelge u_char pk_op; /* operation to perform (read, write, etc.) */ 5311876Shelge u_char pk_mod; /* modifier for op or returned status */ 5411876Shelge u_char pk_unit; /* unit number */ 5511876Shelge u_char pk_sw; /* switches */ 5611876Shelge u_short pk_seq; /* sequence number, always zero */ 5711876Shelge u_short pk_count; /* requested byte count for read or write */ 5811876Shelge u_short pk_block; /* block number for read, write, or seek */ 5911876Shelge u_short pk_chksum; /* checksum, by words with end around carry */ 6011876Shelge }; 6111876Shelge 6211896Shelge struct packet uucmd[NDL]; /* a command sent to the TU58 */ 6311896Shelge struct packet uudata[NDL]; /* a command or data returned from TU58 */ 6411876Shelge 6511876Shelge /* 6611896Shelge * per controller state information 6711876Shelge */ 6811896Shelge struct uu_ctlr { 6911896Shelge u_char *uu_rbptr; /* pointer to buffer for read */ 7011896Shelge int uu_rcnt; /* how much to read */ 7111896Shelge u_char *uu_wbptr; /* pointer to buffer for write */ 7211896Shelge int uu_wcnt; /* how much to write */ 7311896Shelge int uu_state; /* current uu_state of tansfer operation */ 7411896Shelge int uu_flag; /* read in progress flag */ 7511896Shelge char *uu_addr; /* real buffer data address */ 7611896Shelge int uu_count; /* real requested count */ 7711896Shelge int uu_serrs; /* count of soft errors */ 7811896Shelge int uu_cerrs; /* count of checksum errors */ 7911896Shelge int uu_herrs; /* count of hard errors */ 8011896Shelge char uu_dopen[NDPC]; /* drive is open */ 8111896Shelge } uu_ctlr[NDL]; 8211876Shelge 8311876Shelge /* 8411896Shelge * controller states 8511876Shelge */ 8611896Shelge #define UUS_INIT1 0 /* sending nulls */ 8711896Shelge #define UUS_INIT2 1 /* sending inits */ 8811896Shelge #define UUS_IDLE 2 /* initialized, no transfer in progress */ 8911896Shelge #define UUS_SENDH 3 /* sending header */ 9011896Shelge #define UUS_SENDD 4 /* sending data */ 9111896Shelge #define UUS_SENDC 5 /* sending checksum */ 9211896Shelge #define UUS_SENDR 6 /* sending read command packet */ 9311896Shelge #define UUS_SENDW 7 /* sending write command packet */ 9411896Shelge #define UUS_GETH 8 /* reading header */ 9511896Shelge #define UUS_GETD 9 /* reading data */ 9611896Shelge #define UUS_GETC 10 /* reading checksum */ 9711896Shelge #define UUS_GET 11 /* reading an entire packet */ 9811896Shelge #define UUS_WAIT 12 /* waiting for continue */ 9911876Shelge 10011896Shelge #define UUS_NSTATES 13 10111896Shelge char *uustates[UUS_NSTATES] = { 10211876Shelge "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", 10311876Shelge "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT" 10411876Shelge }; 105*12332Shelge 106*12332Shelge #define UNIT(dev) (minor(dev)&DNUM) 10711876Shelge #define printstate(state) \ 10811896Shelge if ((state) < UUS_NSTATES) \ 10911896Shelge printf("%s", uustates[(state)]); \ 11011876Shelge else \ 11111876Shelge printf("%d", (state)); 11211876Shelge 11311876Shelge /* 11411876Shelge * Packet Flags 11511876Shelge */ 11611876Shelge #define TUF_DATA 1 /* data packet */ 11711876Shelge #define TUF_CMD 2 /* command packet */ 11811876Shelge #define TUF_INITF 4 /* initialize */ 11911876Shelge #define TUF_CONT 020 /* continue */ 12011876Shelge #define TUF_XOFF 023 /* flow control */ 12111876Shelge 12211876Shelge /* 12311876Shelge * Op Codes 12411876Shelge */ 12511896Shelge #define TUOP_NOOP 0 /* no operation */ 12611876Shelge #define TUOP_INIT 1 /* initialize */ 12711876Shelge #define TUOP_READ 2 /* read block */ 12811876Shelge #define TUOP_WRITE 3 /* write block */ 12911876Shelge #define TUOP_SEEK 5 /* seek to block */ 13011896Shelge #define TUOP_DIAGNOSE 7 /* run micro-diagnostics */ 13111876Shelge #define TUOP_END 0100 /* end packet */ 13211876Shelge 13311876Shelge /* 13411876Shelge * Mod Flags 13511876Shelge */ 13611876Shelge #define TUMD_WRV 1 /* write with read verify */ 13711876Shelge 13811876Shelge /* 13911876Shelge * Switches 14011876Shelge */ 14111876Shelge 14211896Shelge u_char uunull[2] = { 0, 0 }; /* nulls to send for initialization */ 14311896Shelge u_char uuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ 14411876Shelge 14511896Shelge struct uba_device *uudinfo[NUU]; 14611896Shelge struct uba_ctlr *uuminfo[NDL]; 14711896Shelge 148*12332Shelge int uuprobe(), uuslave(), uuattach(), uudgo(), uurintr(), uuxintr(), uuwatch(); 14911896Shelge u_short uustd[] = { 0176500, 0 }; 15011896Shelge struct uba_driver dldriver = 151*12332Shelge { uuprobe, uuslave, uuattach, uudgo, uustd, "uu", uudinfo, "uu", uuminfo }; 15211896Shelge 15311896Shelge int uuwstart; 154*12332Shelge static char pcnt[2]; /* pee/vee counters */ 15511896Shelge 15611876Shelge /*ARGSUSED*/ 15711896Shelge uuprobe(reg) 15811896Shelge caddr_t reg; 15911876Shelge { 16011896Shelge register int br, cvec; /* value result */ 16111896Shelge struct uudevice *uuaddr = (struct uudevice *)reg; 16211896Shelge int i; 16311876Shelge 16411876Shelge #ifdef lint 16511896Shelge br = 0; cvec = br; br = cvec; 16611896Shelge uurintr(0); uuxintr(0); 16711876Shelge #endif 16811896Shelge uuaddr->rcs = UUCS_INTR; 16911896Shelge uuaddr->tdb = TUF_INITF; 17011896Shelge DELAY(10000); 17111896Shelge i = uuaddr->rdb; 17211896Shelge uuaddr->rcs = 0; 17311896Shelge return(sizeof (*uuaddr)); 17411896Shelge } 17511896Shelge 176*12332Shelge uuslave(ui, reg) 17711896Shelge struct uba_device *ui; 17811896Shelge caddr_t reg; 17911896Shelge { 18011896Shelge return (ui->ui_slave == 0 || ui->ui_slave == 1); 18111896Shelge } 18211896Shelge 18311896Shelge /*ARGSUSED*/ 18411896Shelge uuattach(ui) 18511896Shelge struct uba_device *ui; 18611896Shelge { 187*12332Shelge /* no local state to set up */ 18811896Shelge } 18911896Shelge 19011896Shelge /*ARGSUSED1*/ 19111896Shelge uuopen(dev, flag) 19211896Shelge dev_t dev; 19311896Shelge int flag; 19411896Shelge { 19511896Shelge register struct uba_device *ui; 19611896Shelge register struct uu_ctlr *uuc; 19711896Shelge register struct uudevice *uuaddr; 19811896Shelge register struct uba_ctlr *um; 199*12332Shelge int ctlr, unit = UNIT(dev), s; 20011896Shelge 20111896Shelge if (unit >= NUU || (ui = uudinfo[unit]) == 0 || ui->ui_alive == 0) 20211876Shelge return (ENXIO); 20311896Shelge um = ui->ui_mi; 20411896Shelge ctlr = um->um_ctlr; 20511896Shelge uuc = &uu_ctlr[ctlr]; 206*12332Shelge if (uuc->uu_dopen[unit&DNUM]) 20711896Shelge return (EBUSY); 20811896Shelge if (uuwstart++ == 0) 20911896Shelge timeout(uuwatch, (caddr_t)0, hz); 21011896Shelge 211*12332Shelge uuc->uu_dopen[unit&DNUM]++; 212*12332Shelge uuaddr = (struct uudevice *)um->um_addr; 21311896Shelge s = spl5(); 21411876Shelge /* 21511896Shelge * If the unit already initialized, 21611876Shelge * just enable interrupts and return. 21711876Shelge */ 218*12332Shelge if (uuc->uu_state == UUS_IDLE) { 21911896Shelge uuaddr->rcs = UUCS_INTR; 22011876Shelge splx(s); 22111876Shelge return (0); 22211876Shelge } 22311876Shelge 22411876Shelge /* 22511876Shelge * Must initialize, reset the cassette 22611876Shelge * and wait for things to settle down. 22711876Shelge */ 22811896Shelge uureset(ctlr); 22911896Shelge sleep((caddr_t)uuc, PZERO+1); 23011896Shelge um->um_tab.b_active = NULL; 231*12332Shelge if (uuc->uu_state != UUS_IDLE) { 232*12332Shelge uuc->uu_state = UUS_INIT1; 233*12332Shelge uuc->uu_dopen[unit&DNUM] = 0; 234*12332Shelge uuc->uu_rcnt = uuc->uu_wcnt = 0; 23511896Shelge uuaddr->rcs = 0; 23611896Shelge uuaddr->tcs = 0; 23711896Shelge splx(s); 23811896Shelge return (ENXIO); 23911876Shelge } 24011876Shelge splx(s); 24111876Shelge return (0); 24211876Shelge } 24311876Shelge 24411896Shelge uuclose(dev, flag) 24511896Shelge dev_t dev; 24611896Shelge int flag; 24711876Shelge { 248*12332Shelge register struct uba_ctlr *um = uudinfo[UNIT(dev)]->ui_mi; 24911896Shelge register struct uu_ctlr *uuc; 25011876Shelge 251*12332Shelge uuwstart--; 25211896Shelge uuc = &uu_ctlr[um->um_ctlr]; 25311896Shelge if (uuc->uu_serrs + uuc->uu_cerrs + uuc->uu_herrs != 0) { 25411876Shelge /* 25511876Shelge * A tu58 is like nothing ever seen before; 25611876Shelge * I guess this is appropriate then... 25711876Shelge */ 25811876Shelge uprintf( 25911896Shelge "uu%d: %d soft errors, %d chksum errors, %d hard errors\n", 260*12332Shelge UNIT(dev), uuc->uu_serrs, uuc->uu_cerrs, uuc->uu_herrs); 26111896Shelge uuc->uu_serrs = uuc->uu_cerrs = uuc->uu_herrs = 0; 26211876Shelge } 263*12332Shelge uuc->uu_dopen[UNIT(dev)] = 0; 26411876Shelge } 26511876Shelge 26611896Shelge uureset(ctlr) 26711896Shelge int ctlr; 26811876Shelge { 269*12332Shelge register struct uu_ctlr *uuc = &uu_ctlr[ctlr]; 270*12332Shelge register struct packet *cmd = &uucmd[ctlr]; 27111896Shelge struct uba_ctlr *um = uuminfo[ctlr]; 272*12332Shelge register struct uudevice *uuaddr = (struct uudevice *)um->um_addr; 27311876Shelge 27411896Shelge um->um_tab.b_active++; 275*12332Shelge uuc->uu_state = UUS_INIT1; 27611896Shelge uuc->uu_wbptr = uunull; 27711896Shelge uuc->uu_wcnt = sizeof (uunull); 27811896Shelge cmd->pk_flag = TUF_CMD; 279*12332Shelge cmd->pk_mcount = sizeof (*cmd) - 4; 28011896Shelge cmd->pk_mod = 0; 28111896Shelge cmd->pk_seq = 0; 282*12332Shelge cmd->pk_sw = 0; 28311896Shelge uuaddr->rcs = 0; 28411896Shelge uuaddr->tcs = UUCS_INTR | UUCS_BREAK; 28511896Shelge uuxintr(ctlr); /* start output */ 28611876Shelge } 28711876Shelge 288*12332Shelge uudgo() 289*12332Shelge { 290*12332Shelge } 291*12332Shelge 29211876Shelge /* 29311876Shelge * Strategy routine for block I/O 29411876Shelge */ 29511896Shelge uustrategy(bp) 29611876Shelge register struct buf *bp; 29711876Shelge { 298*12332Shelge register struct buf *uutab; 29911896Shelge struct uba_device *ui; 300*12332Shelge int s, unit = UNIT(bp->b_dev); 30111876Shelge 30211896Shelge if (unit > NUU) 30311896Shelge goto bad; 30411896Shelge if (bp->b_blkno >= NTUBLK) 30511896Shelge goto bad; 30611896Shelge ui = uudinfo[unit]; 30711896Shelge if (ui == 0 || ui->ui_alive == 0) 30811896Shelge goto bad; 309*12332Shelge uutab = &ui->ui_mi->um_tab; /* one request queue per controller */ 310*12332Shelge if ((bp->b_flags&B_READ) == 0) 311*12332Shelge uu_pee(&pcnt[UNIT(bp->b_dev)]); 31211896Shelge s = spl5(); 313*12332Shelge bp->av_forw = NULL; 314*12332Shelge if (uutab->b_actf == NULL) 315*12332Shelge uutab->b_actf = bp; 316*12332Shelge else 317*12332Shelge uutab->b_actl->av_forw = bp; 318*12332Shelge uutab->b_actl = bp; 319*12332Shelge if (uutab->b_active == 0) 320*12332Shelge uustart(ui->ui_mi); 32111876Shelge splx(s); 32211896Shelge return; 32311896Shelge 32411896Shelge bad: 32511896Shelge bp->b_flags |= B_ERROR; 326*12332Shelge bp->b_error = ENXIO; 32711896Shelge iodone(bp); 32811896Shelge return; 32911876Shelge } 33011876Shelge 33111876Shelge /* 33211876Shelge * Start the transfer 33311876Shelge */ 33411896Shelge uustart(um) 33511896Shelge register struct uba_ctlr *um; 33611876Shelge { 33711876Shelge register struct buf *bp; 33811896Shelge register struct uu_ctlr *uuc; 33911896Shelge struct packet *cmd; 340*12332Shelge int ctlr; 34111876Shelge 342*12332Shelge bp = um->um_tab.b_actf; 343*12332Shelge if (bp == NULL) 34411876Shelge return; 345*12332Shelge ctlr = um->um_ctlr; 346*12332Shelge uuc = &uu_ctlr[ctlr]; 347*12332Shelge cmd = &uucmd[ctlr]; 348*12332Shelge if (uuc->uu_state != UUS_IDLE) { 349*12332Shelge uureset(ctlr); 35011876Shelge return; 35111876Shelge } 35211896Shelge um->um_tab.b_active++; 35311896Shelge cmd->pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE; 35411896Shelge cmd->pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ? 35511876Shelge TUMD_WRV : 0; 356*12332Shelge cmd->pk_unit = UNIT(bp->b_dev); 357*12332Shelge cmd->pk_sw = 0; 358*12332Shelge cmd->pk_count = uuc->uu_count = bp->b_bcount; 35911896Shelge cmd->pk_block = bp->b_blkno; 36011896Shelge cmd->pk_chksum = 361*12332Shelge uuchk(*((short *)cmd), (u_short *)&cmd->pk_op, 362*12332Shelge (int)cmd->pk_mcount); 363*12332Shelge uuc->uu_state = bp->b_flags&B_READ ? UUS_SENDR : UUS_SENDW; 36411896Shelge uuc->uu_addr = bp->b_un.b_addr; 36511896Shelge uuc->uu_count = bp->b_bcount; 366*12332Shelge uuc->uu_wbptr = (u_char *)cmd; 367*12332Shelge uuc->uu_wcnt = sizeof (*cmd); 368*12332Shelge uuxintr(ctlr); 36911876Shelge } 37011876Shelge 37111876Shelge /* 37211876Shelge * TU58 receiver interrupt 37311876Shelge */ 374*12332Shelge uurintr(ctlr) 375*12332Shelge int ctlr; 37611876Shelge { 377*12332Shelge struct uba_ctlr *um = uuminfo[ctlr]; 378*12332Shelge register struct buf *bp = um->um_tab.b_actf; 379*12332Shelge register struct uu_ctlr *uuc = &uu_ctlr[ctlr]; 380*12332Shelge register struct uudevice *uuaddr = (struct uudevice *)um->um_addr; 381*12332Shelge register struct buf *uutab = &um->um_tab; 382*12332Shelge struct packet *data, *cmd; 383*12332Shelge int c; 38411876Shelge 385*12332Shelge if (!uutab->b_active) 386*12332Shelge return; 387*12332Shelge cmd = &uucmd[ctlr]; 388*12332Shelge c = uuaddr->rdb; 389*12332Shelge if (c & UURDB_ERROR) { 390*12332Shelge if (c & UURDB_ORUN) { 391*12332Shelge printf("data overrun, "); 392*12332Shelge goto bad; 393*12332Shelge } else { 394*12332Shelge printf("uu%d: break received, device reset, state=", 395*12332Shelge UNIT(bp->b_dev)); 396*12332Shelge printstate(uuc->uu_state); 397*12332Shelge uureset(ctlr); 398*12332Shelge printf("\n"); 399*12332Shelge return; 400*12332Shelge } 40111876Shelge } 402*12332Shelge top: 403*12332Shelge c &= 0xff; 404*12332Shelge if (uuc->uu_rcnt) { /* still waiting for data? */ 405*12332Shelge *uuc->uu_rbptr++ = c; /* yup, put it there */ 406*12332Shelge if (--uuc->uu_rcnt) /* decrement count, any left? */ 40711876Shelge return; /* get some more */ 40811876Shelge } 409*12332Shelge data = &uudata[ctlr]; 41011876Shelge 41111876Shelge /* 41211876Shelge * We got all the data we were expecting for now, 41311896Shelge * switch on the uu_state of the transfer. 41411876Shelge */ 415*12332Shelge switch(uuc->uu_state) { 41611876Shelge 41711876Shelge /* 41811876Shelge * If we get an unexpected "continue", 41911876Shelge * start all over again... 42011876Shelge */ 421*12332Shelge case UUS_INIT2: 422*12332Shelge uuc->uu_state = c == TUF_CONT ? UUS_IDLE : UUS_INIT1; 423*12332Shelge uuc->uu_flag = 0; 424*12332Shelge wakeup((caddr_t)uuc); 425*12332Shelge uustart(um); 42611876Shelge break; 42711876Shelge 42811876Shelge /* 42911876Shelge * Only transition from this state 43011876Shelge * is on a "continue", so if we don't 43111876Shelge * get it, reset the world. 43211876Shelge */ 433*12332Shelge case UUS_WAIT: /* waiting for continue */ 434*12332Shelge switch(c) { 435*12332Shelge case TUF_CONT: /* got the expected continue */ 436*12332Shelge uuc->uu_flag = 0; 437*12332Shelge data->pk_flag = TUF_DATA; 438*12332Shelge data->pk_mcount = MIN(128, uuc->uu_count); 439*12332Shelge data->pk_chksum = 440*12332Shelge tuchk(*((short *)data), (caddr_t)uuc->uu_addr, 441*12332Shelge (int)data->pk_mcount); 442*12332Shelge uuc->uu_state = UUS_SENDH; 443*12332Shelge uuc->uu_wbptr = (u_char *)data; 444*12332Shelge uuc->uu_wcnt = 2; 445*12332Shelge tuxintr(); 44611876Shelge break; 447*12332Shelge 448*12332Shelge case TUF_CMD: /* sending us an END packet...error */ 449*12332Shelge uuc->uu_state = UUS_GET; 450*12332Shelge uuc->uu_rbptr = (u_char *) data; 451*12332Shelge uuc->uu_rcnt = sizeof (*data); 452*12332Shelge uuc->uu_flag = 1; 453*12332Shelge uuaddr->tcs = 0; 454*12332Shelge goto top; 455*12332Shelge 456*12332Shelge case TUF_INITF: 457*12332Shelge tureset(); 458*12332Shelge break; 459*12332Shelge 460*12332Shelge default: /* something random...bad news */ 461*12332Shelge uuc->uu_state = UUS_INIT1; 462*12332Shelge break; 46311876Shelge } 46411876Shelge break; 46511876Shelge 466*12332Shelge case UUS_SENDW: 46711876Shelge if (c != TUF_CONT) 46811876Shelge goto bad; 469*12332Shelge uureset(ctlr); 47011876Shelge break; 47111876Shelge 47211876Shelge /* 47311876Shelge * Got header, now get data; amount to 47411896Shelge * fetch is included in packet. 47511876Shelge */ 476*12332Shelge case UUS_GETH: 477*12332Shelge if (data->pk_flag == TUF_DATA) 478*12332Shelge uuc->uu_rbptr = (u_char *)uuc->uu_addr; 479*12332Shelge uuc->uu_rcnt = data->pk_mcount; 480*12332Shelge uuc->uu_state = UUS_GETD; 48111876Shelge break; 48211876Shelge 48311876Shelge /* 48411876Shelge * Got the data, now fetch the checksum. 48511876Shelge */ 486*12332Shelge case UUS_GETD: 487*12332Shelge uuc->uu_rbptr = (u_char *)&data->pk_chksum; 488*12332Shelge uuc->uu_rcnt = sizeof (data->pk_chksum); 489*12332Shelge uuc->uu_state = UUS_GETC; 49011876Shelge break; 49111876Shelge 492*12332Shelge case UUS_GET: 493*12332Shelge case UUS_GETC: 49411876Shelge /* got entire packet */ 49511876Shelge #ifdef notdef 496*12332Shelge if (data->pk_chksum != 497*12332Shelge uuchk(*((short *)data), (u_short *) 498*12332Shelge (data->pk_flag == TUF_DATA ? uuc->uu_addr : &data->pk_op), 499*12332Shelge (int)data->pk_mcount)) 500*12332Shelge uuc->uu_cerrs++; 50111876Shelge #endif 502*12332Shelge if (data->pk_flag == TUF_DATA) { 50311876Shelge /* data packet, advance to next */ 504*12332Shelge uuc->uu_addr += data->pk_mcount; 505*12332Shelge uuc->uu_count -= data->pk_mcount; 506*12332Shelge uuc->uu_state = UUS_GETH; 507*12332Shelge uuc->uu_rbptr = (u_char *)data; /* next packet */ 508*12332Shelge uuc->uu_rcnt = 2; 509*12332Shelge } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { 51011876Shelge /* end packet, idle and reenable transmitter */ 511*12332Shelge uuc->uu_state = UUS_IDLE; 512*12332Shelge uuc->uu_flag = 0; 513*12332Shelge uuaddr->rcs = UUCS_INTR; 51411876Shelge printd("ON "); 515*12332Shelge if (bp == NULL) { 516*12332Shelge printf("uu: no bp active\n"); 517*12332Shelge uustart(um); 51811876Shelge return; 51911876Shelge } 520*12332Shelge if (data->pk_mod > 1) { /* hard error */ 52111876Shelge bp->b_flags |= B_ERROR; 522*12332Shelge uuc->uu_herrs++; 52311896Shelge harderr(bp, "uu"); 524*12332Shelge printf(" pk_mod %o\n", data->pk_mod&0xff); 525*12332Shelge } else if (data->pk_mod != 0) /* soft error */ 526*12332Shelge uuc->uu_serrs++; 527*12332Shelge uutab->b_active = NULL; 528*12332Shelge uutab->b_actf = bp->av_forw; 529*12332Shelge bp->b_resid = uuc->uu_count; 53011876Shelge if ((bp->b_flags&B_READ) == 0) 531*12332Shelge uu_vee(&pcnt[UNIT(bp->b_dev)]); 53211876Shelge iodone(bp); 533*12332Shelge uustart(um); 53411876Shelge } else { 53511876Shelge printf("neither data nor end: %o %o\n", 536*12332Shelge data->pk_flag&0xff, data->pk_op&0xff); 537*12332Shelge uuaddr->rcs = 0; /* flush the rest */ 538*12332Shelge uuc->uu_state = UUS_INIT1; 53911876Shelge } 54011876Shelge break; 54111876Shelge 542*12332Shelge case UUS_IDLE: 543*12332Shelge case UUS_INIT1: 54411876Shelge break; 54511876Shelge 54611876Shelge default: 54711876Shelge bad: 54811876Shelge if (c == TUF_INITF) { 549*12332Shelge printf("uu%d protocol error, state=", UNIT(bp->b_dev)); 550*12332Shelge printstate(uuc->uu_state); 55111876Shelge printf(", op=%x, cnt=%d, block=%d\n", 552*12332Shelge cmd->pk_op, cmd->pk_count, cmd->pk_block); 553*12332Shelge uutab->b_active = NULL; 554*12332Shelge if (bp = uutab->b_actf) { 55511876Shelge bp->b_flags |= B_ERROR; 556*12332Shelge uutab->b_actf = bp->av_forw; 55711876Shelge if ((bp->b_flags&B_READ) == 0) 558*12332Shelge uu_vee(&pcnt[UNIT(bp->b_dev)]); 55911876Shelge iodone(bp); 56011876Shelge } 561*12332Shelge uuc->uu_state = UUS_INIT1; 56211876Shelge } else { 563*12332Shelge printf("uu%d receive state error, state=", 564*12332Shelge UNIT(bp->b_dev)); 565*12332Shelge printstate(uuc->uu_state); 56611876Shelge printf(", byte=%x\n", c); 56711876Shelge #ifdef notdef 568*12332Shelge uuc->uu_state = UUS_INIT1; */ 56911876Shelge #endif 570*12332Shelge wakeup((caddr_t)uuc); 57111876Shelge } 57211876Shelge } 57311876Shelge } 57411876Shelge 57511876Shelge /* 57611876Shelge * TU58 transmitter interrupt 57711876Shelge */ 578*12332Shelge uuxintr(ctlr) 579*12332Shelge int ctlr; 58011876Shelge { 581*12332Shelge register struct uu_ctlr *uuc = &uu_ctlr[ctlr]; 582*12332Shelge register struct uudevice *uuaddr = 583*12332Shelge (struct uudevice *) uuminfo[ctlr]->um_addr; 584*12332Shelge register struct packet *data; 585*12332Shelge int c; 58611876Shelge 58711876Shelge top: 588*12332Shelge if (uuc->uu_wcnt) { 58911876Shelge /* still stuff to send, send one byte */ 590*12332Shelge while ((uuaddr->tcs & UUCS_READY) == 0) 59111876Shelge ; 592*12332Shelge uuaddr->tdb = *uuc->uu_wbptr++; 593*12332Shelge uuc->uu_wcnt--; 59411876Shelge return; 59511876Shelge } 596*12332Shelge data = &uudata[ctlr]; 59711876Shelge 59811876Shelge /* 59911876Shelge * Last message byte was sent out. 60011896Shelge * Switch on uu_state of transfer. 60111876Shelge */ 60211896Shelge if (uudebug) { 60311896Shelge printf("uuxintr: state="); 604*12332Shelge printstate(uuc->uu_state); 60511876Shelge } 606*12332Shelge switch(uuc->uu_state) { 60711876Shelge 60811876Shelge /* 60911876Shelge * Two nulls have been sent, remove break, and send inits 61011876Shelge */ 611*12332Shelge case UUS_INIT1: 612*12332Shelge uuaddr->tcs = UUCS_INTR; 61311876Shelge printd("ON2 "); 614*12332Shelge uuc->uu_state = UUS_INIT2; 615*12332Shelge uuc->uu_wbptr = uuinit; 616*12332Shelge uuc->uu_wcnt = sizeof (uuinit); 61711876Shelge goto top; 61811876Shelge 61911876Shelge /* 62011876Shelge * Inits have been sent, wait for a continue msg. 62111876Shelge */ 622*12332Shelge case UUS_INIT2: 623*12332Shelge c = uuaddr->rdb; /* not used */ 624*12332Shelge uuaddr->rcs = UUCS_INTR; 625*12332Shelge uuc->uu_flag = 1; 62611876Shelge break; 62711876Shelge 628*12332Shelge case UUS_IDLE: /* stray interrupt? */ 62911876Shelge break; 63011876Shelge 63111876Shelge /* 63211876Shelge * Read cmd packet sent, get ready for data 63311876Shelge */ 634*12332Shelge case UUS_SENDR: 635*12332Shelge uuc->uu_state = UUS_GETH; 636*12332Shelge uuc->uu_rbptr = (u_char *)data; 637*12332Shelge uuc->uu_rcnt = 2; 638*12332Shelge uuc->uu_flag = 1; 639*12332Shelge uuaddr->tcs = 0; /* disable transmitter interrupts */ 64011876Shelge printd("OFF "); 64111876Shelge break; 64211876Shelge 64311876Shelge /* 64411876Shelge * Write cmd packet sent, wait for continue 64511876Shelge */ 646*12332Shelge case UUS_SENDW: 647*12332Shelge uuc->uu_state = UUS_WAIT; 648*12332Shelge uuc->uu_flag = 1; 649*12332Shelge if ((uuaddr->rcs&UUCS_INTR) == 0) { 65011876Shelge printf("NO IE\n"); 651*12332Shelge uuaddr->rcs = UUCS_INTR; 65211876Shelge } 65311876Shelge break; 65411876Shelge 65511876Shelge /* 65611876Shelge * Header sent, send data. 65711876Shelge */ 658*12332Shelge case UUS_SENDH: 659*12332Shelge uuc->uu_state = UUS_SENDD; 660*12332Shelge uuc->uu_wbptr = (u_char *)uuc->uu_addr; 661*12332Shelge uuc->uu_wcnt = data->pk_mcount; 66211876Shelge goto top; 66311876Shelge 66411876Shelge /* 66511876Shelge * Data sent, follow with checksum. 66611876Shelge */ 667*12332Shelge case UUS_SENDD: 668*12332Shelge uuc->uu_state = UUS_SENDC; 669*12332Shelge uuc->uu_wbptr = (u_char *)&data->pk_chksum; 670*12332Shelge uuc->uu_wcnt = sizeof (data->pk_chksum); 67111876Shelge goto top; 67211876Shelge 67311876Shelge /* 67411876Shelge * Checksum sent, wait for continue. 67511876Shelge */ 676*12332Shelge case UUS_SENDC: 67711876Shelge /* 67811876Shelge * Updata buffer address and count. 67911876Shelge */ 680*12332Shelge uuc->uu_addr += data->pk_mcount; 681*12332Shelge uuc->uu_count -= data->pk_mcount; 682*12332Shelge if (uuc->uu_count) { 683*12332Shelge uuc->uu_state = UUS_WAIT; 684*12332Shelge uuc->uu_flag = 1; 68511876Shelge break; 68611876Shelge } 68711876Shelge 68811876Shelge /* 68911876Shelge * End of transmission, get ready for end packet. 69011876Shelge */ 691*12332Shelge uuc->uu_state = UUS_GET; 692*12332Shelge uuc->uu_rbptr = (u_char *)data; 693*12332Shelge uuc->uu_rcnt = sizeof (*data); 694*12332Shelge uuc->uu_flag = 1; 695*12332Shelge uuaddr->tcs = 0; /* disable transm. interrupts */ 69611876Shelge printd("OFF2 "); 69711876Shelge break; 69811876Shelge 69911876Shelge /* 700*12332Shelge * Random interrupt 70111876Shelge */ 70211876Shelge default: 70311876Shelge break; 70411876Shelge } 70511896Shelge if (uudebug) { 70611896Shelge printd(" new uu_state="); 707*12332Shelge printstate(uuc->uu_state); 70811876Shelge } 70911876Shelge } 71011876Shelge 71111876Shelge /* 71211876Shelge * Compute checksum TU58 fashion 71311876Shelge */ 71411876Shelge #ifdef lint 71511896Shelge uuchk(word, cp, n) 71611876Shelge register word; 71711876Shelge register unsigned short *cp; 71811876Shelge int n; 71911876Shelge { 72011876Shelge register int c = n >> 1; 72111876Shelge register long temp; 72211876Shelge 72311876Shelge do { 72411876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 72511876Shelge word += temp; 72611876Shelge } while (--c > 0); 72711876Shelge if (n & 1) 72811876Shelge word += *(unsigned char *)cp; 72911876Shelge while (word & 0xffff0000) 73011876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 73111876Shelge return (word); 73211876Shelge } 73311876Shelge #else 73411896Shelge uuchk(word0, wp, n) 73511896Shelge register int word0; /* r11 */ 73611896Shelge register char *wp; /* r10 */ 73711896Shelge register int n; /* r9 */ 73811876Shelge { 73911876Shelge asm("loop:"); 74011896Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 74111896Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 74211876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 74311896Shelge asm(" blbc r9,ok"); /* odd byte count? */ 74411896Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 74511896Shelge asm(" addw2 r10,r11"); /* add it in */ 74611896Shelge asm(" adwc $0,r11"); /* and the carry */ 74711876Shelge asm("ok:"); 74811896Shelge asm(" movl r11,r0"); /* return sum */ 74911876Shelge } 75011876Shelge #endif 75111876Shelge 75211896Shelge uuwatch() 75311876Shelge { 754*12332Shelge register struct uu_ctlr *uuc; 755*12332Shelge register struct uudevice *uuaddr; 756*12332Shelge struct uba_ctlr *um; 757*12332Shelge struct buf *bp, *uutab; 758*12332Shelge int s; 75911876Shelge 760*12332Shelge if (uuwstart == 0) 76111876Shelge return; 762*12332Shelge for (s=0; s<NDL; s++) { 763*12332Shelge int i; 764*12332Shelge 765*12332Shelge uuc = &uu_ctlr[s]; 766*12332Shelge um = uuminfo[s]; 767*12332Shelge if (uuc->uu_flag) 768*12332Shelge uuc->uu_flag++; 769*12332Shelge if (uuc->uu_flag <= 40) 770*12332Shelge continue; 771*12332Shelge printf("uu%d: read stalled\n", s); 772*12332Shelge printf("%X %X %X %X %X %X %X %X\n", uuc->uu_rbptr, uuc->uu_rcnt, 773*12332Shelge uuc->uu_wbptr, uuc->uu_wcnt, uuc->uu_state, uuc->uu_flag, 774*12332Shelge uuc->uu_addr, uuc->uu_count); 775*12332Shelge uuc->uu_flag = 0; 776*12332Shelge uuaddr = (struct uudevice *)um->um_addr; 777*12332Shelge uutab = &um->um_tab; 778*12332Shelge i = uuaddr->rdb; /* dummy */ 779*12332Shelge uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ 780*12332Shelge uuaddr->tcs = UUCS_INTR; 781*12332Shelge uuc->uu_state = UUS_IDLE; 782*12332Shelge if (!uutab->b_active) { 783*12332Shelge wakeup((caddr_t)uuc); 784*12332Shelge continue; 785*12332Shelge } 786*12332Shelge if (++uutab->b_errcnt <= 1) { 787*12332Shelge uustart(um); 788*12332Shelge continue; 789*12332Shelge } 790*12332Shelge if (bp = uutab->b_actf) { 791*12332Shelge bp->b_flags |= B_ERROR; 792*12332Shelge if ((bp->b_flags&B_READ) == 0) 793*12332Shelge uu_vee(&pcnt[UNIT(bp->b_dev)]); 794*12332Shelge iodone(bp); 795*12332Shelge } 79611876Shelge } 797*12332Shelge timeout(uuwatch, (caddr_t)0, hz); 798*12332Shelge return; 799*12332Shelge } 800*12332Shelge 801*12332Shelge uu_pee(cp) 802*12332Shelge char *cp; 803*12332Shelge { 804*12332Shelge register int s; 805*12332Shelge 806*12332Shelge s = spl5(); 807*12332Shelge if (++(*cp) > NTUQ) { 808*12332Shelge sleep(cp, PRIBIO); 80911876Shelge } 810*12332Shelge splx(s); 811*12332Shelge } 812*12332Shelge 813*12332Shelge uu_vee(cp) 814*12332Shelge char *cp; 815*12332Shelge { 816*12332Shelge register int s; 817*12332Shelge 818*12332Shelge s = spl5(); 819*12332Shelge if (--(*cp) <= NTUQ) { 820*12332Shelge wakeup(cp); 82111876Shelge } 82211876Shelge splx(s); 82311876Shelge } 82411876Shelge #endif 825*12332Shelge 826