1*11896Shelge /* uu.c 4.2 83/04/10 */ 211876Shelge 3*11896Shelge #include "uu->h" 4*11896Shelge #if NDL > 0 511876Shelge /* 6*11896Shelge * TU58 DECtape II/DL11 device driver 711876Shelge * 8*11896Shelge * 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 11*11896Shelge * errors are checked for. 1211876Shelge */ 13*11896Shelge 14*11896Shelge /* 15*11896Shelge * TODO: 16*11896Shelge * - Split the uu structure into a per controller 17*11896Shelge * part and a per drive part. 18*11896Shelge */ 19*11896Shelge 2011876Shelge #include "../h/param.h" 2111876Shelge #include "../h/systm.h" 2211876Shelge #include "../h/buf.h" 2311876Shelge #include "../h/conf.h" 2411876Shelge #include "../h/dir.h" 25*11896Shelge #include "../h/kernel.h" 26*11896Shelge #include "../h/errno.h" 27*11896Shelge #include "../h/uio.h" 2811876Shelge #include "../h/user.h" 29*11896Shelge #include "../h/file.h" 3011876Shelge 3111876Shelge #include "../vax/cpu.h" 3211876Shelge #include "../vax/mtpr.h" 33*11896Shelge #include "../vaxuba/ubavar.h" 34*11896Shelge #include "../vaxuba/ubareg.h" 35*11896Shelge #include "../vaxuba/uureg.h" 3611876Shelge 37*11896Shelge #define printd if(uudebug) printf 3811876Shelge #ifdef printd 39*11896Shelge int uudebug; /* printd */ 4011876Shelge #endif printd 4111876Shelge 42*11896Shelge #if !defined(MRSP) || lint 4311876Shelge #define MRSP (cpu != VAX_750) 4411876Shelge #endif 4511876Shelge #define NTUBLK 512 /* number of blocks on a TU58 cassette */ 46*11896Shelge #define WRV 02 /* bit in minor dev => write w. read verify */ 47*11896Shelge #define NDPC 02 /* # drives per controller */ 4811876Shelge 4911876Shelge /* 5011876Shelge * Structure of a command packet 5111876Shelge */ 5211876Shelge struct packet { 5311876Shelge u_char pk_flag; /* indicates packet type (cmd, data, etc.) */ 5411876Shelge u_char pk_mcount; /* length of packet (bytes) */ 5511876Shelge u_char pk_op; /* operation to perform (read, write, etc.) */ 5611876Shelge u_char pk_mod; /* modifier for op or returned status */ 5711876Shelge u_char pk_unit; /* unit number */ 5811876Shelge u_char pk_sw; /* switches */ 5911876Shelge u_short pk_seq; /* sequence number, always zero */ 6011876Shelge u_short pk_count; /* requested byte count for read or write */ 6111876Shelge u_short pk_block; /* block number for read, write, or seek */ 6211876Shelge u_short pk_chksum; /* checksum, by words with end around carry */ 6311876Shelge }; 6411876Shelge 65*11896Shelge struct packet uucmd[NDL]; /* a command sent to the TU58 */ 66*11896Shelge struct packet uudata[NDL]; /* a command or data returned from TU58 */ 6711876Shelge 6811876Shelge /* 69*11896Shelge * per controller state information 7011876Shelge */ 71*11896Shelge struct uu_ctlr { 72*11896Shelge u_char *uu_rbptr; /* pointer to buffer for read */ 73*11896Shelge int uu_rcnt; /* how much to read */ 74*11896Shelge u_char *uu_wbptr; /* pointer to buffer for write */ 75*11896Shelge int uu_wcnt; /* how much to write */ 76*11896Shelge int uu_state; /* current uu_state of tansfer operation */ 77*11896Shelge int uu_flag; /* read in progress flag */ 78*11896Shelge char *uu_addr; /* real buffer data address */ 79*11896Shelge int uu_count; /* real requested count */ 80*11896Shelge int uu_serrs; /* count of soft errors */ 81*11896Shelge int uu_cerrs; /* count of checksum errors */ 82*11896Shelge int uu_herrs; /* count of hard errors */ 83*11896Shelge char uu_dopen[NDPC]; /* drive is open */ 84*11896Shelge } uu_ctlr[NDL]; 8511876Shelge 8611876Shelge /* 87*11896Shelge * controller states 8811876Shelge */ 89*11896Shelge #define UUS_INIT1 0 /* sending nulls */ 90*11896Shelge #define UUS_INIT2 1 /* sending inits */ 91*11896Shelge #define UUS_IDLE 2 /* initialized, no transfer in progress */ 92*11896Shelge #define UUS_SENDH 3 /* sending header */ 93*11896Shelge #define UUS_SENDD 4 /* sending data */ 94*11896Shelge #define UUS_SENDC 5 /* sending checksum */ 95*11896Shelge #define UUS_SENDR 6 /* sending read command packet */ 96*11896Shelge #define UUS_SENDW 7 /* sending write command packet */ 97*11896Shelge #define UUS_GETH 8 /* reading header */ 98*11896Shelge #define UUS_GETD 9 /* reading data */ 99*11896Shelge #define UUS_GETC 10 /* reading checksum */ 100*11896Shelge #define UUS_GET 11 /* reading an entire packet */ 101*11896Shelge #define UUS_WAIT 12 /* waiting for continue */ 10211876Shelge 103*11896Shelge #define UUS_NSTATES 13 104*11896Shelge char *uustates[UUS_NSTATES] = { 10511876Shelge "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", 10611876Shelge "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT" 10711876Shelge }; 10811876Shelge #define printstate(state) \ 109*11896Shelge if ((state) < UUS_NSTATES) \ 110*11896Shelge printf("%s", uustates[(state)]); \ 11111876Shelge else \ 11211876Shelge printf("%d", (state)); 11311876Shelge 11411876Shelge /* 11511876Shelge * Packet Flags 11611876Shelge */ 11711876Shelge #define TUF_DATA 1 /* data packet */ 11811876Shelge #define TUF_CMD 2 /* command packet */ 11911876Shelge #define TUF_INITF 4 /* initialize */ 12011876Shelge #define TUF_CONT 020 /* continue */ 12111876Shelge #define TUF_XOFF 023 /* flow control */ 12211876Shelge 12311876Shelge /* 12411876Shelge * Op Codes 12511876Shelge */ 126*11896Shelge #define TUOP_NOOP 0 /* no operation */ 12711876Shelge #define TUOP_INIT 1 /* initialize */ 12811876Shelge #define TUOP_READ 2 /* read block */ 12911876Shelge #define TUOP_WRITE 3 /* write block */ 13011876Shelge #define TUOP_SEEK 5 /* seek to block */ 131*11896Shelge #define TUOP_DIAGNOSE 7 /* run micro-diagnostics */ 13211876Shelge #define TUOP_END 0100 /* end packet */ 13311876Shelge 13411876Shelge /* 13511876Shelge * Mod Flags 13611876Shelge */ 13711876Shelge #define TUMD_WRV 1 /* write with read verify */ 13811876Shelge 13911876Shelge /* 14011876Shelge * Switches 14111876Shelge */ 14211876Shelge #define TUSW_MRSP 010 /* use Modified RSP */ 14311876Shelge 144*11896Shelge u_char uunull[2] = { 0, 0 }; /* nulls to send for initialization */ 145*11896Shelge u_char uuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ 14611876Shelge 147*11896Shelge struct uba_device *uudinfo[NUU]; 148*11896Shelge struct uba_ctlr *uuminfo[NDL]; 149*11896Shelge 150*11896Shelge int uuprobe(), uuslave(), uuattach(), uurintr(), uuxintr(), uuwatch(); 151*11896Shelge u_short uustd[] = { 0176500, 0 }; 152*11896Shelge struct uba_driver dldriver = 153*11896Shelge { uuprobe, uuslave, uuattach, uudgo, uustd, "uu", uudinfo, "dl", uuminfo }; 154*11896Shelge 155*11896Shelge int uuwstart; 156*11896Shelge 15711876Shelge /*ARGSUSED*/ 158*11896Shelge uuprobe(reg) 159*11896Shelge caddr_t reg; 16011876Shelge { 161*11896Shelge register int br, cvec; /* value result */ 162*11896Shelge struct uudevice *uuaddr = (struct uudevice *)reg; 163*11896Shelge int i; 16411876Shelge 16511876Shelge #ifdef lint 166*11896Shelge br = 0; cvec = br; br = cvec; 167*11896Shelge uurintr(0); uuxintr(0); 16811876Shelge #endif 169*11896Shelge uuaddr->rcs = UUCS_INTR; 170*11896Shelge uuaddr->tdb = TUF_INITF; 171*11896Shelge DELAY(10000); 172*11896Shelge i = uuaddr->rdb; 173*11896Shelge uuaddr->rcs = 0; 174*11896Shelge return(sizeof (*uuaddr)); 175*11896Shelge } 176*11896Shelge 177*11896Shelge uuslave(ui, reg); 178*11896Shelge struct uba_device *ui; 179*11896Shelge caddr_t reg; 180*11896Shelge { 181*11896Shelge return (ui->ui_slave == 0 || ui->ui_slave == 1); 182*11896Shelge } 183*11896Shelge 184*11896Shelge /*ARGSUSED*/ 185*11896Shelge uuattach(ui) 186*11896Shelge struct uba_device *ui; 187*11896Shelge { 188*11896Shelge 189*11896Shelge } 190*11896Shelge 191*11896Shelge /*ARGSUSED1*/ 192*11896Shelge uuopen(dev, flag) 193*11896Shelge dev_t dev; 194*11896Shelge int flag; 195*11896Shelge { 196*11896Shelge register struct uba_device *ui; 197*11896Shelge register struct uu_ctlr *uuc; 198*11896Shelge register struct uudevice *uuaddr; 199*11896Shelge register struct uba_ctlr *um; 200*11896Shelge int ctlr, unit = minor(dev), s; 201*11896Shelge 202*11896Shelge if (unit >= NUU || (ui = uudinfo[unit]) == 0 || ui->ui_alive == 0) 20311876Shelge return (ENXIO); 204*11896Shelge um = ui->ui_mi; 205*11896Shelge ctlr = um->um_ctlr; 206*11896Shelge uuc = &uu_ctlr[ctlr]; 207*11896Shelge if (uuc->uu_dopen[unit%NDPC]) 208*11896Shelge return (EBUSY); 209*11896Shelge if (uuwstart++ == 0) 210*11896Shelge timeout(uuwatch, (caddr_t)0, hz); 211*11896Shelge 212*11896Shelge uuc->uu_dopen[unit%NDPC]++; 213*11896Shelge uuaddr = (struct uudevice *)ui->ui_mi->um_addr; 214*11896Shelge s = spl5(); 21511876Shelge /* 216*11896Shelge * If the unit already initialized, 21711876Shelge * just enable interrupts and return. 21811876Shelge */ 219*11896Shelge if (uu->uu_state == TUS_IDLE) { 220*11896Shelge uuaddr->rcs = UUCS_INTR; 22111876Shelge splx(s); 22211876Shelge return (0); 22311876Shelge } 22411876Shelge 22511876Shelge /* 22611876Shelge * Must initialize, reset the cassette 22711876Shelge * and wait for things to settle down. 22811876Shelge */ 229*11896Shelge uureset(ctlr); 230*11896Shelge sleep((caddr_t)uuc, PZERO+1); 231*11896Shelge um->um_tab.b_active = NULL; 232*11896Shelge if (uu->uu_state != TUS_IDLE) { 233*11896Shelge uu->uu_state = TUS_INIT1; 234*11896Shelge uu->uu_dopen[unit%NDPC] = 0; 235*11896Shelge uu->uu_rcnt = uu->uu_wcnt = 0; 236*11896Shelge uuaddr->rcs = 0; 237*11896Shelge uuaddr->tcs = 0; 238*11896Shelge splx(s); 239*11896Shelge return (ENXIO); 24011876Shelge } 24111876Shelge splx(s); 24211876Shelge return (0); 24311876Shelge } 24411876Shelge 245*11896Shelge uuclose(dev, flag) 246*11896Shelge dev_t dev; 247*11896Shelge int flag; 24811876Shelge { 249*11896Shelge register struct uba_ctlr *um = uudinfo[minor(dev)]->ui_mi; 250*11896Shelge register struct uudevice *uuaddr; 251*11896Shelge register struct uu_ctlr *uuc; 25211876Shelge 253*11896Shelge if (um->um_tab.b_active == 0) { 254*11896Shelge uuaddr = (struct uudevice *)um->um_addr; 255*11896Shelge uuaddr->rcs = 0; 256*11896Shelge uuwstart--; 25711876Shelge } 258*11896Shelge uuc = &uu_ctlr[um->um_ctlr]; 259*11896Shelge if (uuc->uu_serrs + uuc->uu_cerrs + uuc->uu_herrs != 0) { 26011876Shelge /* 26111876Shelge * A tu58 is like nothing ever seen before; 26211876Shelge * I guess this is appropriate then... 26311876Shelge */ 26411876Shelge uprintf( 265*11896Shelge "uu%d: %d soft errors, %d chksum errors, %d hard errors\n", 266*11896Shelge minor(dev), uuc->uu_serrs, uuc->uu_cerrs, uuc->uu_herrs); 267*11896Shelge uuc->uu_serrs = uuc->uu_cerrs = uuc->uu_herrs = 0; 26811876Shelge } 269*11896Shelge uuc->uu_dopen[minor(dev)%NDPC] = 0; 27011876Shelge } 27111876Shelge 272*11896Shelge uureset(ctlr) 273*11896Shelge int ctlr; 27411876Shelge { 275*11896Shelge register struct uu_ctlr *uuc = uu_ctlr[ctlr]; 276*11896Shelge register struct packet *cmd = uucmd[ctlr]; 277*11896Shelge register struct uudevice *uuaddr; 278*11896Shelge struct uba_ctlr *um = uuminfo[ctlr]; 27911876Shelge 280*11896Shelge um->um_tab.b_active++; 281*11896Shelge uuc->uu_state = TUS_INIT1; 282*11896Shelge uuc->uu_wbptr = uunull; 283*11896Shelge uuc->uu_wcnt = sizeof (uunull); 284*11896Shelge cmd->pk_flag = TUF_CMD; 285*11896Shelge cmd->pk_mcount = sizeof (uucmd) - 4; 286*11896Shelge cmd->pk_mod = 0; 287*11896Shelge cmd->pk_seq = 0; 288*11896Shelge cmd->pk_sw = MRSP ? TUSW_MRSP : 0; 289*11896Shelge uuaddr = (struct uudevice *)um->um_addr; 290*11896Shelge uuaddr->rcs = 0; 291*11896Shelge uuaddr->tcs = UUCS_INTR | UUCS_BREAK; 292*11896Shelge uuxintr(ctlr); /* start output */ 29311876Shelge } 29411876Shelge 29511876Shelge /* 29611876Shelge * Strategy routine for block I/O 29711876Shelge */ 298*11896Shelge uustrategy(bp) 29911876Shelge register struct buf *bp; 30011876Shelge { 301*11896Shelge register struct buf *dp; 302*11896Shelge struct uba_device *ui; 303*11896Shelge struct uu_ctlr *uuc; 304*11896Shelge int s, unit = minor(bp->b_dev); 30511876Shelge 306*11896Shelge if (unit > NUU) 307*11896Shelge goto bad; 308*11896Shelge if (bp->b_blkno >= NTUBLK) 309*11896Shelge goto bad; 310*11896Shelge ui = uudinfo[unit]; 311*11896Shelge if (ui == 0 || ui->ui_alive == 0) 312*11896Shelge goto bad; 313*11896Shelge uuc = &uu_ctlr[ui->ui_mi->um_ctlr]; 314*11896Shelge s = spl5(); 315*11896Shelge bp->b_cylin = bp->b_blkno; 316*11896Shelge dp = &uuutab[unit]; 317*11896Shelge disksort(dp, bp); 318*11896Shelge if (dp->b_active == 0) { 319*11896Shelge uuustart(ui); 320*11896Shelge bp = &ui->ui_mi->um_tab; 321*11896Shelge if (bp->b_actf && bp->b_active == 0) 322*11896Shelge uustart(ui->ui_mi); 32311876Shelge } 32411876Shelge splx(s); 325*11896Shelge return; 326*11896Shelge 327*11896Shelge bad: 328*11896Shelge bp->b_flags |= B_ERROR; 329*11896Shelge iodone(bp); 330*11896Shelge return; 33111876Shelge } 33211876Shelge 33311876Shelge /* 334*11896Shelge * Unit start routine. 335*11896Shelge * Put this unit on the ready queue for the controller 336*11896Shelge */ 337*11896Shelge uuustart(ui) 338*11896Shelge register struct uba_device *ui; 339*11896Shelge { 340*11896Shelge struct buf *dp = &uuutab[ui->ui_unit]; 341*11896Shelge struct uba_ctlr *um = ui->ui_mi; 342*11896Shelge 343*11896Shelge dp->b_forw = NULL; 344*11896Shelge if (um->um_tab.b_actf == NULL) 345*11896Shelge um->um_tab.b_actf = dp; 346*11896Shelge else 347*11896Shelge um->um_tab.b_actl->b_forw = dp; 348*11896Shelge um->um_tab.b_actl = dp; 349*11896Shelge dp->b_active++; 350*11896Shelge } 351*11896Shelge /* 35211876Shelge * Start the transfer 35311876Shelge */ 354*11896Shelge uustart(um) 355*11896Shelge register struct uba_ctlr *um; 35611876Shelge { 357*11896Shelge register struct uudevice *uuaddr; 35811876Shelge register struct buf *bp; 359*11896Shelge register struct uu_ctlr *uuc; 360*11896Shelge struct buf *dp; 361*11896Shelge struct packet *cmd; 362*11896Shelge int unit; 36311876Shelge 364*11896Shelge loop: 365*11896Shelge if ((dp = um->um_tab.b_actf) == NULL) 36611876Shelge return; 367*11896Shelge if ((bp = dp->b_actf) == NULL) { 368*11896Shelge um->um_tab.b_actf = dp->b_forw; 369*11896Shelge goto loop; 370*11896Shelge } 371*11896Shelge unit = minor(bp->b_dev); 372*11896Shelge uuc = &uu_ctlr[um->um_ctlr]; 373*11896Shelge cmd = &uucmd[um->um_ctlr]; 374*11896Shelge if (uuc->uu_state != TUS_IDLE) { 375*11896Shelge uureset(um->um_ctlr); 37611876Shelge return; 37711876Shelge } 378*11896Shelge um->um_tab.b_active++; 379*11896Shelge uuaddr = (struct uudevice *)um->um_addr; 380*11896Shelge cmd->pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE; 381*11896Shelge cmd->pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ? 38211876Shelge TUMD_WRV : 0; 383*11896Shelge cmd->pk_unit = (minor(bp->b_dev)&DNUM); 384*11896Shelge cmd->pk_sw = MRSP ? TUSW_MRSP : 0; 385*11896Shelge cmd->pk_count = uu->uu_count = bp->b_bcount; 386*11896Shelge cmd->pk_block = bp->b_blkno; 387*11896Shelge cmd->pk_chksum = 388*11896Shelge uuchk(*((short *)&cmd), (u_short *)&cmd.pk_op, 389*11896Shelge (int)cmd.pk_mcount); 390*11896Shelge uuc->uu_state = bp->b_flags&B_READ ? TUS_SENDR : TUS_SENDW; 391*11896Shelge uuc->uu_addr = bp->b_un.b_addr; 392*11896Shelge uuc->uu_count = bp->b_bcount; 393*11896Shelge uuc->uu_wbptr = (u_char *)&uucmd; 394*11896Shelge uuc->uu_wcnt = sizeof (uucmd); 395*11896Shelge uuxintr(um->um_ctlr); 39611876Shelge } 39711876Shelge 39811876Shelge /* 39911876Shelge * TU58 receiver interrupt 40011876Shelge */ 401*11896Shelge uurintr() 40211876Shelge { 40311876Shelge register struct buf *bp; 40411876Shelge register int c; 40511876Shelge 40611876Shelge c = mfpr(CSRD)&0xff; /* get the char, clear the interrupt */ 40711876Shelge if (MRSP) { 40811876Shelge while ((mfpr(CSTS)&READY) == 0) 40911876Shelge ; 41011876Shelge mtpr(CSTD, TUF_CONT); /* ACK */ 41111876Shelge } 412*11896Shelge if (uu->uu_rcnt) { /* still waiting for data? */ 413*11896Shelge *uu->uu_rbptr++ = c; /* yup, put it there */ 414*11896Shelge if (--uu->uu_rcnt) /* decrement count, any left? */ 41511876Shelge return; /* get some more */ 41611876Shelge } 41711876Shelge 41811876Shelge /* 41911876Shelge * We got all the data we were expecting for now, 420*11896Shelge * switch on the uu_state of the transfer. 42111876Shelge */ 422*11896Shelge switch(uu->uu_state) { 42311876Shelge 42411876Shelge /* 42511876Shelge * If we get an unexpected "continue", 42611876Shelge * start all over again... 42711876Shelge */ 42811876Shelge case TUS_INIT2: 429*11896Shelge uu->uu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; 430*11896Shelge uu->uu_flag = 0; 431*11896Shelge wakeup((caddr_t)&uu); 432*11896Shelge uustart(); 43311876Shelge break; 43411876Shelge 43511876Shelge /* 43611876Shelge * Only transition from this state 43711876Shelge * is on a "continue", so if we don't 43811876Shelge * get it, reset the world. 43911876Shelge */ 44011876Shelge case TUS_WAIT: /* waiting for continue */ 44111876Shelge if (c != TUF_CONT) { 442*11896Shelge uu->uu_state = TUS_INIT1; 44311876Shelge break; 44411876Shelge } 445*11896Shelge uu->uu_flag = 0; 446*11896Shelge uudata.pk_flag = TUF_DATA; 447*11896Shelge uudata.pk_mcount = MIN(128, uu->uu_count); 448*11896Shelge uudata.pk_chksum = 449*11896Shelge uuchk(*((short *)&uudata), (u_short *)uu->uu_addr, 450*11896Shelge (int)uudata.pk_mcount); 451*11896Shelge uu->uu_state = TUS_SENDH; 452*11896Shelge uu->uu_wbptr = (u_char *)&uudata; 453*11896Shelge uu->uu_wcnt = 2; 454*11896Shelge uuxintr(); 45511876Shelge break; 45611876Shelge 45711876Shelge case TUS_SENDW: 45811876Shelge if (c != TUF_CONT) 45911876Shelge goto bad; 460*11896Shelge uureset(); 46111876Shelge break; 46211876Shelge 46311876Shelge /* 46411876Shelge * Got header, now get data; amount to 465*11896Shelge * fetch is included in packet. 46611876Shelge */ 46711876Shelge case TUS_GETH: 468*11896Shelge if (uudata.pk_flag == TUF_DATA) 469*11896Shelge uu->uu_rbptr = (u_char *)uu->uu_addr; 470*11896Shelge uu->uu_rcnt = uudata.pk_mcount; 471*11896Shelge uu->uu_state = TUS_GETD; 47211876Shelge break; 47311876Shelge 47411876Shelge /* 47511876Shelge * Got the data, now fetch the checksum. 47611876Shelge */ 47711876Shelge case TUS_GETD: 478*11896Shelge uu->uu_rbptr = (u_char *)&uudata.pk_chksum; 479*11896Shelge uu->uu_rcnt = sizeof (uudata.pk_chksum); 480*11896Shelge uu->uu_state = TUS_GETC; 48111876Shelge break; 48211876Shelge 48311876Shelge case TUS_GET: 48411876Shelge case TUS_GETC: 48511876Shelge /* got entire packet */ 48611876Shelge #ifdef notdef 487*11896Shelge if (uudata.pk_chksum != 488*11896Shelge uuchk(*((short *)&uudata), (u_short *) 489*11896Shelge (uudata.pk_flag == TUF_DATA ? uu->uu_addr : &uudata.pk_op), 490*11896Shelge (int)uudata.pk_mcount)) 491*11896Shelge uu->uu_cerrs++; 49211876Shelge #endif 493*11896Shelge if (uudata.pk_flag == TUF_DATA) { 49411876Shelge /* data packet, advance to next */ 495*11896Shelge uu->uu_addr += uudata.pk_mcount; 496*11896Shelge uu->uu_count -= uudata.pk_mcount; 497*11896Shelge uu->uu_state = TUS_GETH; 498*11896Shelge uu->uu_rbptr = (u_char *)&uudata; /* next packet */ 499*11896Shelge uu->uu_rcnt = 2; 500*11896Shelge } else if (uudata.pk_flag==TUF_CMD && uudata.pk_op==TUOP_END) { 50111876Shelge /* end packet, idle and reenable transmitter */ 502*11896Shelge uu->uu_state = TUS_IDLE; 503*11896Shelge uu->uu_flag = 0; 50411876Shelge mtpr(CSTS, IE); 50511876Shelge printd("ON "); 506*11896Shelge if ((bp = uutab.b_actf) == NULL) { 507*11896Shelge printf("uu: no bp, active %d\n",uutab.b_active); 508*11896Shelge uustart(); 50911876Shelge return; 51011876Shelge } 511*11896Shelge if (uudata.pk_mod > 1) { /* hard error */ 51211876Shelge bp->b_flags |= B_ERROR; 513*11896Shelge uu->uu_herrs++; 514*11896Shelge harderr(bp, "uu"); 515*11896Shelge printf(" pk_mod %o\n", uudata.pk_mod&0377); 516*11896Shelge } else if (uudata.pk_mod != 0) /* soft error */ 517*11896Shelge uu->uu_serrs++; 518*11896Shelge uutab.b_active = NULL; 519*11896Shelge uutab.b_actf = bp->av_forw; 520*11896Shelge bp->b_resid = uu->uu_count; 52111876Shelge if ((bp->b_flags&B_READ) == 0) 522*11896Shelge uu_vee(&pcnt[minor(bp->b_dev)&DNUM]); 52311876Shelge iodone(bp); 524*11896Shelge uustart(); 52511876Shelge } else { 52611876Shelge printf("neither data nor end: %o %o\n", 527*11896Shelge uudata.pk_flag&0xff, uudata.pk_op&0xff); 52811876Shelge mtpr(CSRS, 0); /* flush the rest */ 529*11896Shelge uu->uu_state = TUS_INIT1; 53011876Shelge } 53111876Shelge break; 53211876Shelge 53311876Shelge case TUS_IDLE: 53411876Shelge case TUS_INIT1: 53511876Shelge break; 53611876Shelge 53711876Shelge default: 53811876Shelge bad: 53911876Shelge if (c == TUF_INITF) { 540*11896Shelge printf("uu protocol error, state="); 541*11896Shelge printstate(uu->uu_state); 54211876Shelge printf(", op=%x, cnt=%d, block=%d\n", 543*11896Shelge uucmd.pk_op, uucmd.pk_count, uucmd.pk_block); 544*11896Shelge uutab.b_active = NULL; 545*11896Shelge if (bp = uutab.b_actf) { 54611876Shelge bp->b_flags |= B_ERROR; 547*11896Shelge uutab.b_actf = bp->av_forw; 54811876Shelge if ((bp->b_flags&B_READ) == 0) 549*11896Shelge uu_vee(&pcnt[minor(bp->b_dev)&DNUM]); 55011876Shelge iodone(bp); 55111876Shelge } 552*11896Shelge uu->uu_state = TUS_INIT1; 55311876Shelge } else { 554*11896Shelge printf("uu receive state error, state="); 55511876Shelge printf(", byte=%x\n", c); 55611876Shelge #ifdef notdef 557*11896Shelge uu->uu_state = TUS_INIT1; */ 55811876Shelge #endif 559*11896Shelge wakeup((caddr_t)&uu); 56011876Shelge } 56111876Shelge } 56211876Shelge } 56311876Shelge 56411876Shelge /* 56511876Shelge * TU58 transmitter interrupt 56611876Shelge */ 567*11896Shelge uuxintr() 56811876Shelge { 56911876Shelge 57011876Shelge top: 571*11896Shelge if (uu->uu_wcnt) { 57211876Shelge /* still stuff to send, send one byte */ 57311876Shelge while ((mfpr(CSTS) & READY) == 0) 57411876Shelge ; 575*11896Shelge mtpr(CSTD, *uu->uu_wbptr++); 576*11896Shelge uu->uu_wcnt--; 57711876Shelge return; 57811876Shelge } 57911876Shelge 58011876Shelge /* 58111876Shelge * Last message byte was sent out. 582*11896Shelge * Switch on uu_state of transfer. 58311876Shelge */ 584*11896Shelge if (uudebug) { 585*11896Shelge printf("uuxintr: state="); 586*11896Shelge printstate(uu->uu_state); 58711876Shelge } 588*11896Shelge switch(uu->uu_state) { 58911876Shelge 59011876Shelge /* 59111876Shelge * Two nulls have been sent, remove break, and send inits 59211876Shelge */ 59311876Shelge case TUS_INIT1: 59411876Shelge mtpr(CSTS, IE); 59511876Shelge printd("ON2 "); 596*11896Shelge uu->uu_state = TUS_INIT2; 597*11896Shelge uu->uu_wbptr = uuinit; 598*11896Shelge uu->uu_wcnt = sizeof (uuinit); 59911876Shelge goto top; 60011876Shelge 60111876Shelge /* 60211876Shelge * Inits have been sent, wait for a continue msg. 60311876Shelge */ 60411876Shelge case TUS_INIT2: 60511876Shelge (void) mfpr(CSRD); 60611876Shelge mtpr(CSRS, IE); 607*11896Shelge uu->uu_flag = 1; 60811876Shelge break; 60911876Shelge 61011876Shelge case TUS_IDLE: /* stray interrupt? */ 61111876Shelge break; 61211876Shelge 61311876Shelge /* 61411876Shelge * Read cmd packet sent, get ready for data 61511876Shelge */ 61611876Shelge case TUS_SENDR: 617*11896Shelge uu->uu_state = TUS_GETH; 618*11896Shelge uu->uu_rbptr = (u_char *)&uudata; 619*11896Shelge uu->uu_rcnt = 2; 620*11896Shelge uu->uu_flag = 1; 62111876Shelge mtpr(CSTS, 0); /* disable transmitter interrupts */ 62211876Shelge printd("OFF "); 62311876Shelge break; 62411876Shelge 62511876Shelge /* 62611876Shelge * Write cmd packet sent, wait for continue 62711876Shelge */ 62811876Shelge case TUS_SENDW: 629*11896Shelge uu->uu_state = TUS_WAIT; 630*11896Shelge uu->uu_flag = 1; 63111876Shelge if ((mfpr(CSRS)&IE) == 0) { 63211876Shelge printf("NO IE\n"); 63311876Shelge mtpr(CSRS, IE); 63411876Shelge } 63511876Shelge break; 63611876Shelge 63711876Shelge /* 63811876Shelge * Header sent, send data. 63911876Shelge */ 64011876Shelge case TUS_SENDH: 641*11896Shelge uu->uu_state = TUS_SENDD; 642*11896Shelge uu->uu_wbptr = (u_char *)uu->uu_addr; 643*11896Shelge uu->uu_wcnt = uudata.pk_mcount; 64411876Shelge goto top; 64511876Shelge 64611876Shelge /* 64711876Shelge * Data sent, follow with checksum. 64811876Shelge */ 64911876Shelge case TUS_SENDD: 650*11896Shelge uu->uu_state = TUS_SENDC; 651*11896Shelge uu->uu_wbptr = (u_char *)&uudata.pk_chksum; 652*11896Shelge uu->uu_wcnt = sizeof uudata.pk_chksum; 65311876Shelge goto top; 65411876Shelge 65511876Shelge /* 65611876Shelge * Checksum sent, wait for continue. 65711876Shelge */ 65811876Shelge case TUS_SENDC: 65911876Shelge /* 66011876Shelge * Updata buffer address and count. 66111876Shelge */ 662*11896Shelge uu->uu_addr += uudata.pk_mcount; 663*11896Shelge uu->uu_count -= uudata.pk_mcount; 664*11896Shelge if (uu->uu_count) { 665*11896Shelge uu->uu_state = TUS_WAIT; 666*11896Shelge uu->uu_flag = 1; 66711876Shelge break; 66811876Shelge } 66911876Shelge 67011876Shelge /* 67111876Shelge * End of transmission, get ready for end packet. 67211876Shelge */ 673*11896Shelge uu->uu_state = TUS_GET; 674*11896Shelge uu->uu_rbptr = (u_char *)&uudata; 675*11896Shelge uu->uu_rcnt = sizeof (uudata); 676*11896Shelge uu->uu_flag = 1; 67711876Shelge mtpr(CSTS, 0); 67811876Shelge printd("OFF2 "); 67911876Shelge break; 68011876Shelge 68111876Shelge /* 68211876Shelge * Random interrupt, probably from MRSP ACK 68311876Shelge */ 68411876Shelge default: 68511876Shelge break; 68611876Shelge } 687*11896Shelge if (uudebug) { 688*11896Shelge printd(" new uu_state="); 689*11896Shelge printstate(uu->uu_state); 69011876Shelge } 69111876Shelge } 69211876Shelge 69311876Shelge /* 69411876Shelge * Compute checksum TU58 fashion 69511876Shelge */ 69611876Shelge #ifdef lint 697*11896Shelge uuchk(word, cp, n) 69811876Shelge register word; 69911876Shelge register unsigned short *cp; 70011876Shelge int n; 70111876Shelge { 70211876Shelge register int c = n >> 1; 70311876Shelge register long temp; 70411876Shelge 70511876Shelge do { 70611876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 70711876Shelge word += temp; 70811876Shelge } while (--c > 0); 70911876Shelge if (n & 1) 71011876Shelge word += *(unsigned char *)cp; 71111876Shelge while (word & 0xffff0000) 71211876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 71311876Shelge return (word); 71411876Shelge } 71511876Shelge #else 716*11896Shelge uuchk(word0, wp, n) 717*11896Shelge register int word0; /* r11 */ 718*11896Shelge register char *wp; /* r10 */ 719*11896Shelge register int n; /* r9 */ 72011876Shelge { 72111876Shelge asm("loop:"); 722*11896Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 723*11896Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 72411876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 725*11896Shelge asm(" blbc r9,ok"); /* odd byte count? */ 726*11896Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 727*11896Shelge asm(" addw2 r10,r11"); /* add it in */ 728*11896Shelge asm(" adwc $0,r11"); /* and the carry */ 72911876Shelge asm("ok:"); 730*11896Shelge asm(" movl r11,r0"); /* return sum */ 73111876Shelge } 73211876Shelge #endif 73311876Shelge 734*11896Shelge uuwatch() 73511876Shelge { 73611876Shelge register int s; 73711876Shelge register struct buf *bp; 73811876Shelge 739*11896Shelge if (uutimer == 0) { 740*11896Shelge uu->uu_flag = 0; 74111876Shelge return; 74211876Shelge } 743*11896Shelge if (uu->uu_flag) 744*11896Shelge uu->uu_flag++; 745*11896Shelge if (uu->uu_flag <= 40) { 746*11896Shelge timeout(uuwatch, (caddr_t)0, hz); 74711876Shelge return; 74811876Shelge } 749*11896Shelge printf("uu: read stalled\n"); 750*11896Shelge printf("%X %X %X %X %X %X %X %X\n", uu->uu_rbptr, uu->uu_rcnt, 751*11896Shelge uu->uu_wbptr, uu->uu_wcnt, uu->uu_state, uu->uu_flag, 752*11896Shelge uu->uu_addr, uu->uu_count); 753*11896Shelge uu->uu_flag = 0; 75411876Shelge s = splx(TUIPL); 75511876Shelge (void) mfpr(CSRD); 75611876Shelge mtpr(CSRS, IE); /* in case we were flushing */ 75711876Shelge mtpr(CSTS, IE); 758*11896Shelge uu->uu_state = TUS_IDLE; 759*11896Shelge if (!uutab.b_active) { 760*11896Shelge wakeup((caddr_t)&uu); 76111876Shelge goto retry; 76211876Shelge } 763*11896Shelge if (++uutab.b_errcnt <= 1) { 764*11896Shelge uustart(); 76511876Shelge goto retry; 76611876Shelge } 767*11896Shelge if (bp = uutab.b_actf) { 76811876Shelge bp->b_flags |= B_ERROR; 76911876Shelge if ((bp->b_flags&B_READ) == 0) 770*11896Shelge uu_vee(&pcnt[minor(bp->b_dev)&DNUM]); 77111876Shelge iodone(bp); 77211876Shelge } 77311876Shelge retry: 77411876Shelge splx(s); 775*11896Shelge timeout(uuwatch, (caddr_t)0, hz); 77611876Shelge } 77711876Shelge #endif 778