1*11876Shelge /* tu.c 4.13 83/02/10 */ 2*11876Shelge 3*11876Shelge #if defined(VAX750) || defined(VAX730) 4*11876Shelge /* 5*11876Shelge * TU58 DECtape II device driver 6*11876Shelge * 7*11876Shelge * This driver controls the console TU58s on a VAX-11/750 or VAX-11/730. 8*11876Shelge * It could be easily modified for a Unibus TU58. The TU58 9*11876Shelge * is treated as a block device (only). Error detection and 10*11876Shelge * recovery is almost non-existant. It is assumed that the 11*11876Shelge * TU58 will follow the RSP protocol exactly, very few protocol 12*11876Shelge * errors are checked for. It is assumed that the 750 uses standard 13*11876Shelge * RSP while the 730 uses Modified RSP (MRSP). At the time when 750's 14*11876Shelge * are converted to MRSP (by replacing EPROMS in the TU58), the tests 15*11876Shelge * based on MRSP can be removed. 16*11876Shelge */ 17*11876Shelge #include "../h/param.h" 18*11876Shelge #include "../h/systm.h" 19*11876Shelge #include "../h/buf.h" 20*11876Shelge #include "../h/conf.h" 21*11876Shelge #include "../h/dir.h" 22*11876Shelge #include "../h/user.h" 23*11876Shelge #include "../h/kernel.h" 24*11876Shelge 25*11876Shelge #include "../vax/cpu.h" 26*11876Shelge #include "../vax/mtpr.h" 27*11876Shelge 28*11876Shelge #define printd if(tudebug) printf 29*11876Shelge #ifdef printd 30*11876Shelge int tudebug; /* printd */ 31*11876Shelge #endif printd 32*11876Shelge 33*11876Shelge #define NTU ((cpu == VAX_750) ? 1 : 2) 34*11876Shelge #define DNUM 01 /* mask for drive number (should match NTU) */ 35*11876Shelge #if !defined(MRSP) || lint 36*11876Shelge #define MRSP (cpu != VAX_750) 37*11876Shelge #endif 38*11876Shelge #define NTUBLK 512 /* number of blocks on a TU58 cassette */ 39*11876Shelge #define WRV 02 /* bit in minor dev => write w. read verify */ 40*11876Shelge #define NTUQ 2 /* # of blocks which can be queued up */ 41*11876Shelge #define TUIPL ((cpu == VAX_750) ? 0x17 : 0x14) 42*11876Shelge 43*11876Shelge /* 44*11876Shelge * Device register bits 45*11876Shelge */ 46*11876Shelge #define READY 0200 /* transmitter ready */ 47*11876Shelge #define DONE 0200 /* receiver done */ 48*11876Shelge #define IE 0100 /* interrupt enable */ 49*11876Shelge #define BREAK 1 /* send break */ 50*11876Shelge 51*11876Shelge /* 52*11876Shelge * Structure of a command packet 53*11876Shelge */ 54*11876Shelge struct packet { 55*11876Shelge u_char pk_flag; /* indicates packet type (cmd, data, etc.) */ 56*11876Shelge u_char pk_mcount; /* length of packet (bytes) */ 57*11876Shelge u_char pk_op; /* operation to perform (read, write, etc.) */ 58*11876Shelge u_char pk_mod; /* modifier for op or returned status */ 59*11876Shelge u_char pk_unit; /* unit number */ 60*11876Shelge u_char pk_sw; /* switches */ 61*11876Shelge u_short pk_seq; /* sequence number, always zero */ 62*11876Shelge u_short pk_count; /* requested byte count for read or write */ 63*11876Shelge u_short pk_block; /* block number for read, write, or seek */ 64*11876Shelge u_short pk_chksum; /* checksum, by words with end around carry */ 65*11876Shelge }; 66*11876Shelge 67*11876Shelge struct packet tucmd; /* a command sent to the TU58 */ 68*11876Shelge struct packet tudata; /* a command or data returned from TU58 */ 69*11876Shelge 70*11876Shelge /* 71*11876Shelge * State information 72*11876Shelge */ 73*11876Shelge struct tu { 74*11876Shelge u_char *tu_rbptr; /* pointer to buffer for read */ 75*11876Shelge int tu_rcnt; /* how much to read */ 76*11876Shelge u_char *tu_wbptr; /* pointer to buffer for write */ 77*11876Shelge int tu_wcnt; /* how much to write */ 78*11876Shelge int tu_state; /* current tu_state of tansfer operation */ 79*11876Shelge int tu_flag; /* read in progress flag */ 80*11876Shelge char *tu_addr; /* real buffer data address */ 81*11876Shelge int tu_count; /* real requested count */ 82*11876Shelge int tu_serrs; /* count of soft errors */ 83*11876Shelge int tu_cerrs; /* count of checksum errors */ 84*11876Shelge int tu_herrs; /* count of hard errors */ 85*11876Shelge char tu_dopen[2]; /* drive is open */ 86*11876Shelge } tu; 87*11876Shelge 88*11876Shelge /* 89*11876Shelge * States 90*11876Shelge */ 91*11876Shelge #define TUS_INIT1 0 /* sending nulls */ 92*11876Shelge #define TUS_INIT2 1 /* sending inits */ 93*11876Shelge #define TUS_IDLE 2 /* initialized, no transfer in progress */ 94*11876Shelge #define TUS_SENDH 3 /* sending header */ 95*11876Shelge #define TUS_SENDD 4 /* sending data */ 96*11876Shelge #define TUS_SENDC 5 /* sending checksum */ 97*11876Shelge #define TUS_SENDR 6 /* sending read command packet */ 98*11876Shelge #define TUS_SENDW 7 /* sending write command packet */ 99*11876Shelge #define TUS_GETH 8 /* reading header */ 100*11876Shelge #define TUS_GETD 9 /* reading data */ 101*11876Shelge #define TUS_GETC 10 /* reading checksum */ 102*11876Shelge #define TUS_GET 11 /* reading an entire packet */ 103*11876Shelge #define TUS_WAIT 12 /* waiting for continue */ 104*11876Shelge 105*11876Shelge #define TUS_NSTATES 13 106*11876Shelge char *tustates[TUS_NSTATES] = { 107*11876Shelge "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", 108*11876Shelge "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT" 109*11876Shelge }; 110*11876Shelge #define printstate(state) \ 111*11876Shelge if ((state) < TUS_NSTATES) \ 112*11876Shelge printf("%s", tustates[(state)]); \ 113*11876Shelge else \ 114*11876Shelge printf("%d", (state)); 115*11876Shelge 116*11876Shelge /* 117*11876Shelge * Packet Flags 118*11876Shelge */ 119*11876Shelge #define TUF_DATA 1 /* data packet */ 120*11876Shelge #define TUF_CMD 2 /* command packet */ 121*11876Shelge #define TUF_INITF 4 /* initialize */ 122*11876Shelge #define TUF_CONT 020 /* continue */ 123*11876Shelge #define TUF_XOFF 023 /* flow control */ 124*11876Shelge 125*11876Shelge /* 126*11876Shelge * Op Codes 127*11876Shelge */ 128*11876Shelge #define TUOP_INIT 1 /* initialize */ 129*11876Shelge #define TUOP_READ 2 /* read block */ 130*11876Shelge #define TUOP_WRITE 3 /* write block */ 131*11876Shelge #define TUOP_SEEK 5 /* seek to block */ 132*11876Shelge #define TUOP_DIAGNOSE 7 /* run micro-diagnostics */ 133*11876Shelge #define TUOP_END 0100 /* end packet */ 134*11876Shelge 135*11876Shelge /* 136*11876Shelge * Mod Flags 137*11876Shelge */ 138*11876Shelge #define TUMD_WRV 1 /* write with read verify */ 139*11876Shelge 140*11876Shelge /* 141*11876Shelge * Switches 142*11876Shelge */ 143*11876Shelge #define TUSW_MRSP 010 /* use Modified RSP */ 144*11876Shelge 145*11876Shelge u_char tunull[2] = { 0, 0 }; /* nulls to send for initialization */ 146*11876Shelge u_char tuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ 147*11876Shelge static char pcnt[2]; /* pee/vee counters */ 148*11876Shelge int tutimer = 0; 149*11876Shelge struct buf tutab; /* I/O queue header */ 150*11876Shelge 151*11876Shelge /* 152*11876Shelge * Open the TU58 153*11876Shelge */ 154*11876Shelge /*ARGSUSED*/ 155*11876Shelge tuopen(dev, flag) 156*11876Shelge { 157*11876Shelge extern int tuwatch(); 158*11876Shelge register s; 159*11876Shelge 160*11876Shelge #ifdef lint 161*11876Shelge turintr(); tuwintr(); 162*11876Shelge #endif 163*11876Shelge if ((minor(dev)&DNUM) >= NTU || tu.tu_dopen[minor(dev)&DNUM]) 164*11876Shelge return (ENXIO); 165*11876Shelge if (tutimer == 0) { 166*11876Shelge tutimer++; 167*11876Shelge timeout(tuwatch, (caddr_t)0, hz); 168*11876Shelge } 169*11876Shelge tu.tu_dopen[minor(dev)&DNUM]++; 170*11876Shelge s = splx(TUIPL); 171*11876Shelge /* 172*11876Shelge * If the cassette's already initialized, 173*11876Shelge * just enable interrupts and return. 174*11876Shelge */ 175*11876Shelge if (tu.tu_state == TUS_IDLE) { 176*11876Shelge mtpr(CSRS, IE); 177*11876Shelge splx(s); 178*11876Shelge return (0); 179*11876Shelge } 180*11876Shelge 181*11876Shelge /* 182*11876Shelge * Must initialize, reset the cassette 183*11876Shelge * and wait for things to settle down. 184*11876Shelge */ 185*11876Shelge tureset(); 186*11876Shelge sleep((caddr_t)&tu, PZERO+1); 187*11876Shelge tutab.b_active = NULL; 188*11876Shelge if (tu.tu_state != TUS_IDLE) { 189*11876Shelge u.u_error = ENXIO; 190*11876Shelge tu.tu_state = TUS_INIT1; 191*11876Shelge tu.tu_dopen[minor(dev)&DNUM] = 0; 192*11876Shelge tu.tu_rcnt = tu.tu_wcnt = 0; 193*11876Shelge mtpr(CSTS, 0); 194*11876Shelge mtpr(CSRS, 0); 195*11876Shelge } 196*11876Shelge splx(s); 197*11876Shelge return (0); 198*11876Shelge } 199*11876Shelge 200*11876Shelge /* 201*11876Shelge * Close the TU58 202*11876Shelge */ 203*11876Shelge tuclose(dev) 204*11876Shelge { 205*11876Shelge 206*11876Shelge if (tutab.b_active == 0) { 207*11876Shelge mtpr(CSRS, 0); 208*11876Shelge tutimer = 0; 209*11876Shelge } 210*11876Shelge if (tu.tu_serrs + tu.tu_cerrs + tu.tu_herrs != 0) { 211*11876Shelge /* 212*11876Shelge * A tu58 is like nothing ever seen before; 213*11876Shelge * I guess this is appropriate then... 214*11876Shelge */ 215*11876Shelge uprintf( 216*11876Shelge "tu%d: %d soft errors, %d chksum errors, %d hard errors\n", 217*11876Shelge minor(dev), tu.tu_serrs, tu.tu_cerrs, tu.tu_herrs); 218*11876Shelge tu.tu_serrs = tu.tu_cerrs = tu.tu_herrs = 0; 219*11876Shelge } 220*11876Shelge tu.tu_dopen[minor(dev)&DNUM] = 0; 221*11876Shelge } 222*11876Shelge 223*11876Shelge /* 224*11876Shelge * Reset the TU58 225*11876Shelge */ 226*11876Shelge tureset() 227*11876Shelge { 228*11876Shelge 229*11876Shelge tu.tu_state = TUS_INIT1; 230*11876Shelge tu.tu_wbptr = tunull; 231*11876Shelge tu.tu_wcnt = sizeof (tunull); 232*11876Shelge tucmd.pk_flag = TUF_CMD; 233*11876Shelge tucmd.pk_mcount = sizeof (tucmd) - 4; 234*11876Shelge tucmd.pk_mod = 0; 235*11876Shelge tucmd.pk_seq = 0; 236*11876Shelge tucmd.pk_sw = MRSP ? TUSW_MRSP : 0; 237*11876Shelge tutab.b_active++; 238*11876Shelge mtpr(CSRS, 0); 239*11876Shelge mtpr(CSTS, IE|BREAK); 240*11876Shelge tuxintr(); /* start output */ 241*11876Shelge } 242*11876Shelge 243*11876Shelge /* 244*11876Shelge * Strategy routine for block I/O 245*11876Shelge */ 246*11876Shelge tustrategy(bp) 247*11876Shelge register struct buf *bp; 248*11876Shelge { 249*11876Shelge register int s; 250*11876Shelge 251*11876Shelge if (bp->b_blkno >= NTUBLK) { 252*11876Shelge bp->b_flags |= B_ERROR; 253*11876Shelge iodone(bp); 254*11876Shelge return; 255*11876Shelge } 256*11876Shelge if ((bp->b_flags&B_READ) == 0) 257*11876Shelge tu_pee(&pcnt[minor(bp->b_dev)&DNUM]); 258*11876Shelge bp->av_forw = NULL; 259*11876Shelge s = splx(TUIPL); 260*11876Shelge if (tutab.b_actf == NULL) 261*11876Shelge tutab.b_actf = bp; 262*11876Shelge else 263*11876Shelge tutab.b_actl->av_forw = bp; 264*11876Shelge tutab.b_actl = bp; 265*11876Shelge if (tutab.b_active == NULL) 266*11876Shelge tustart(); 267*11876Shelge splx(s); 268*11876Shelge } 269*11876Shelge 270*11876Shelge /* 271*11876Shelge * Start the transfer 272*11876Shelge */ 273*11876Shelge tustart() 274*11876Shelge { 275*11876Shelge register struct buf *bp; 276*11876Shelge 277*11876Shelge if ((bp = tutab.b_actf) == NULL) 278*11876Shelge return; 279*11876Shelge if (tu.tu_state != TUS_IDLE) { 280*11876Shelge tureset(); 281*11876Shelge return; 282*11876Shelge } 283*11876Shelge tutab.b_active++; 284*11876Shelge tutab.b_errcnt = 0; 285*11876Shelge tucmd.pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE; 286*11876Shelge tucmd.pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ? 287*11876Shelge TUMD_WRV : 0; 288*11876Shelge tucmd.pk_unit = (minor(bp->b_dev)&DNUM); 289*11876Shelge tucmd.pk_sw = MRSP ? TUSW_MRSP : 0; 290*11876Shelge tucmd.pk_count = tu.tu_count = bp->b_bcount; 291*11876Shelge tucmd.pk_block = bp->b_blkno; 292*11876Shelge tucmd.pk_chksum = 293*11876Shelge tuchk(*((short *)&tucmd), (u_short *)&tucmd.pk_op, 294*11876Shelge (int)tucmd.pk_mcount); 295*11876Shelge tu.tu_state = bp->b_flags&B_READ ? TUS_SENDR : TUS_SENDW; 296*11876Shelge tu.tu_addr = bp->b_un.b_addr; 297*11876Shelge tu.tu_count = bp->b_bcount; 298*11876Shelge tu.tu_wbptr = (u_char *)&tucmd; 299*11876Shelge tu.tu_wcnt = sizeof (tucmd); 300*11876Shelge tuxintr(); 301*11876Shelge } 302*11876Shelge 303*11876Shelge /* 304*11876Shelge * TU58 receiver interrupt 305*11876Shelge */ 306*11876Shelge turintr() 307*11876Shelge { 308*11876Shelge register struct buf *bp; 309*11876Shelge register int c; 310*11876Shelge 311*11876Shelge c = mfpr(CSRD)&0xff; /* get the char, clear the interrupt */ 312*11876Shelge if (MRSP) { 313*11876Shelge while ((mfpr(CSTS)&READY) == 0) 314*11876Shelge ; 315*11876Shelge mtpr(CSTD, TUF_CONT); /* ACK */ 316*11876Shelge } 317*11876Shelge if (tu.tu_rcnt) { /* still waiting for data? */ 318*11876Shelge *tu.tu_rbptr++ = c; /* yup, put it there */ 319*11876Shelge if (--tu.tu_rcnt) /* decrement count, any left? */ 320*11876Shelge return; /* get some more */ 321*11876Shelge } 322*11876Shelge 323*11876Shelge /* 324*11876Shelge * We got all the data we were expecting for now, 325*11876Shelge * switch on the tu_state of the transfer. 326*11876Shelge */ 327*11876Shelge switch(tu.tu_state) { 328*11876Shelge 329*11876Shelge /* 330*11876Shelge * If we get an unexpected "continue", 331*11876Shelge * start all over again... 332*11876Shelge */ 333*11876Shelge case TUS_INIT2: 334*11876Shelge tu.tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; 335*11876Shelge tu.tu_flag = 0; 336*11876Shelge wakeup((caddr_t)&tu); 337*11876Shelge tustart(); 338*11876Shelge break; 339*11876Shelge 340*11876Shelge /* 341*11876Shelge * Only transition from this state 342*11876Shelge * is on a "continue", so if we don't 343*11876Shelge * get it, reset the world. 344*11876Shelge */ 345*11876Shelge case TUS_WAIT: /* waiting for continue */ 346*11876Shelge if (c != TUF_CONT) { 347*11876Shelge tu.tu_state = TUS_INIT1; 348*11876Shelge break; 349*11876Shelge } 350*11876Shelge tu.tu_flag = 0; 351*11876Shelge tudata.pk_flag = TUF_DATA; 352*11876Shelge tudata.pk_mcount = MIN(128, tu.tu_count); 353*11876Shelge tudata.pk_chksum = 354*11876Shelge tuchk(*((short *)&tudata), (u_short *)tu.tu_addr, 355*11876Shelge (int)tudata.pk_mcount); 356*11876Shelge tu.tu_state = TUS_SENDH; 357*11876Shelge tu.tu_wbptr = (u_char *)&tudata; 358*11876Shelge tu.tu_wcnt = 2; 359*11876Shelge tuxintr(); 360*11876Shelge break; 361*11876Shelge 362*11876Shelge case TUS_SENDW: 363*11876Shelge if (c != TUF_CONT) 364*11876Shelge goto bad; 365*11876Shelge tureset(); 366*11876Shelge break; 367*11876Shelge 368*11876Shelge /* 369*11876Shelge * Got header, now get data; amount to 370*11876Shelge * fetch is include in packet. 371*11876Shelge */ 372*11876Shelge case TUS_GETH: 373*11876Shelge if (tudata.pk_flag == TUF_DATA) 374*11876Shelge tu.tu_rbptr = (u_char *)tu.tu_addr; 375*11876Shelge tu.tu_rcnt = tudata.pk_mcount; 376*11876Shelge tu.tu_state = TUS_GETD; 377*11876Shelge break; 378*11876Shelge 379*11876Shelge /* 380*11876Shelge * Got the data, now fetch the checksum. 381*11876Shelge */ 382*11876Shelge case TUS_GETD: 383*11876Shelge tu.tu_rbptr = (u_char *)&tudata.pk_chksum; 384*11876Shelge tu.tu_rcnt = sizeof (tudata.pk_chksum); 385*11876Shelge tu.tu_state = TUS_GETC; 386*11876Shelge break; 387*11876Shelge 388*11876Shelge case TUS_GET: 389*11876Shelge case TUS_GETC: 390*11876Shelge /* got entire packet */ 391*11876Shelge #ifdef notdef 392*11876Shelge if (tudata.pk_chksum != 393*11876Shelge tuchk(*((short *)&tudata), (u_short *) 394*11876Shelge (tudata.pk_flag == TUF_DATA ? tu.tu_addr : &tudata.pk_op), 395*11876Shelge (int)tudata.pk_mcount)) 396*11876Shelge tu.tu_cerrs++; 397*11876Shelge #endif 398*11876Shelge if (tudata.pk_flag == TUF_DATA) { 399*11876Shelge /* data packet, advance to next */ 400*11876Shelge tu.tu_addr += tudata.pk_mcount; 401*11876Shelge tu.tu_count -= tudata.pk_mcount; 402*11876Shelge tu.tu_state = TUS_GETH; 403*11876Shelge tu.tu_rbptr = (u_char *)&tudata; /* next packet */ 404*11876Shelge tu.tu_rcnt = 2; 405*11876Shelge } else if (tudata.pk_flag==TUF_CMD && tudata.pk_op==TUOP_END) { 406*11876Shelge /* end packet, idle and reenable transmitter */ 407*11876Shelge tu.tu_state = TUS_IDLE; 408*11876Shelge tu.tu_flag = 0; 409*11876Shelge mtpr(CSTS, IE); 410*11876Shelge printd("ON "); 411*11876Shelge if ((bp = tutab.b_actf) == NULL) { 412*11876Shelge printf("tu: no bp, active %d\n",tutab.b_active); 413*11876Shelge tustart(); 414*11876Shelge return; 415*11876Shelge } 416*11876Shelge if (tudata.pk_mod > 1) { /* hard error */ 417*11876Shelge bp->b_flags |= B_ERROR; 418*11876Shelge tu.tu_herrs++; 419*11876Shelge harderr(bp, "tu"); 420*11876Shelge printf(" pk_mod %o\n", tudata.pk_mod&0377); 421*11876Shelge } else if (tudata.pk_mod != 0) /* soft error */ 422*11876Shelge tu.tu_serrs++; 423*11876Shelge tutab.b_active = NULL; 424*11876Shelge tutab.b_actf = bp->av_forw; 425*11876Shelge bp->b_resid = tu.tu_count; 426*11876Shelge if ((bp->b_flags&B_READ) == 0) 427*11876Shelge tu_vee(&pcnt[minor(bp->b_dev)&DNUM]); 428*11876Shelge iodone(bp); 429*11876Shelge tustart(); 430*11876Shelge } else { 431*11876Shelge printf("neither data nor end: %o %o\n", 432*11876Shelge tudata.pk_flag&0xff, tudata.pk_op&0xff); 433*11876Shelge mtpr(CSRS, 0); /* flush the rest */ 434*11876Shelge tu.tu_state = TUS_INIT1; 435*11876Shelge } 436*11876Shelge break; 437*11876Shelge 438*11876Shelge case TUS_IDLE: 439*11876Shelge case TUS_INIT1: 440*11876Shelge break; 441*11876Shelge 442*11876Shelge default: 443*11876Shelge bad: 444*11876Shelge if (c == TUF_INITF) { 445*11876Shelge printf("tu protocol error, state="); 446*11876Shelge printstate(tu.tu_state); 447*11876Shelge printf(", op=%x, cnt=%d, block=%d\n", 448*11876Shelge tucmd.pk_op, tucmd.pk_count, tucmd.pk_block); 449*11876Shelge tutab.b_active = NULL; 450*11876Shelge if (bp = tutab.b_actf) { 451*11876Shelge bp->b_flags |= B_ERROR; 452*11876Shelge tutab.b_actf = bp->av_forw; 453*11876Shelge if ((bp->b_flags&B_READ) == 0) 454*11876Shelge tu_vee(&pcnt[minor(bp->b_dev)&DNUM]); 455*11876Shelge iodone(bp); 456*11876Shelge } 457*11876Shelge tu.tu_state = TUS_INIT1; 458*11876Shelge } else { 459*11876Shelge printf("tu receive state error, state="); 460*11876Shelge printf(", byte=%x\n", c); 461*11876Shelge #ifdef notdef 462*11876Shelge tu.tu_state = TUS_INIT1; */ 463*11876Shelge #endif 464*11876Shelge wakeup((caddr_t)&tu); 465*11876Shelge } 466*11876Shelge } 467*11876Shelge } 468*11876Shelge 469*11876Shelge /* 470*11876Shelge * TU58 transmitter interrupt 471*11876Shelge */ 472*11876Shelge tuxintr() 473*11876Shelge { 474*11876Shelge 475*11876Shelge top: 476*11876Shelge if (tu.tu_wcnt) { 477*11876Shelge /* still stuff to send, send one byte */ 478*11876Shelge while ((mfpr(CSTS) & READY) == 0) 479*11876Shelge ; 480*11876Shelge mtpr(CSTD, *tu.tu_wbptr++); 481*11876Shelge tu.tu_wcnt--; 482*11876Shelge return; 483*11876Shelge } 484*11876Shelge 485*11876Shelge /* 486*11876Shelge * Last message byte was sent out. 487*11876Shelge * Switch on tu_state of transfer. 488*11876Shelge */ 489*11876Shelge if (tudebug) { 490*11876Shelge printf("tuxintr: state="); 491*11876Shelge printstate(tu.tu_state); 492*11876Shelge } 493*11876Shelge switch(tu.tu_state) { 494*11876Shelge 495*11876Shelge /* 496*11876Shelge * Two nulls have been sent, remove break, and send inits 497*11876Shelge */ 498*11876Shelge case TUS_INIT1: 499*11876Shelge mtpr(CSTS, IE); 500*11876Shelge printd("ON2 "); 501*11876Shelge tu.tu_state = TUS_INIT2; 502*11876Shelge tu.tu_wbptr = tuinit; 503*11876Shelge tu.tu_wcnt = sizeof (tuinit); 504*11876Shelge goto top; 505*11876Shelge 506*11876Shelge /* 507*11876Shelge * Inits have been sent, wait for a continue msg. 508*11876Shelge */ 509*11876Shelge case TUS_INIT2: 510*11876Shelge (void) mfpr(CSRD); 511*11876Shelge mtpr(CSRS, IE); 512*11876Shelge tu.tu_flag = 1; 513*11876Shelge break; 514*11876Shelge 515*11876Shelge case TUS_IDLE: /* stray interrupt? */ 516*11876Shelge break; 517*11876Shelge 518*11876Shelge /* 519*11876Shelge * Read cmd packet sent, get ready for data 520*11876Shelge */ 521*11876Shelge case TUS_SENDR: 522*11876Shelge tu.tu_state = TUS_GETH; 523*11876Shelge tu.tu_rbptr = (u_char *)&tudata; 524*11876Shelge tu.tu_rcnt = 2; 525*11876Shelge tu.tu_flag = 1; 526*11876Shelge mtpr(CSTS, 0); /* disable transmitter interrupts */ 527*11876Shelge printd("OFF "); 528*11876Shelge break; 529*11876Shelge 530*11876Shelge /* 531*11876Shelge * Write cmd packet sent, wait for continue 532*11876Shelge */ 533*11876Shelge case TUS_SENDW: 534*11876Shelge tu.tu_state = TUS_WAIT; 535*11876Shelge tu.tu_flag = 1; 536*11876Shelge if ((mfpr(CSRS)&IE) == 0) { 537*11876Shelge printf("NO IE\n"); 538*11876Shelge mtpr(CSRS, IE); 539*11876Shelge } 540*11876Shelge break; 541*11876Shelge 542*11876Shelge /* 543*11876Shelge * Header sent, send data. 544*11876Shelge */ 545*11876Shelge case TUS_SENDH: 546*11876Shelge tu.tu_state = TUS_SENDD; 547*11876Shelge tu.tu_wbptr = (u_char *)tu.tu_addr; 548*11876Shelge tu.tu_wcnt = tudata.pk_mcount; 549*11876Shelge goto top; 550*11876Shelge 551*11876Shelge /* 552*11876Shelge * Data sent, follow with checksum. 553*11876Shelge */ 554*11876Shelge case TUS_SENDD: 555*11876Shelge tu.tu_state = TUS_SENDC; 556*11876Shelge tu.tu_wbptr = (u_char *)&tudata.pk_chksum; 557*11876Shelge tu.tu_wcnt = sizeof tudata.pk_chksum; 558*11876Shelge goto top; 559*11876Shelge 560*11876Shelge /* 561*11876Shelge * Checksum sent, wait for continue. 562*11876Shelge */ 563*11876Shelge case TUS_SENDC: 564*11876Shelge /* 565*11876Shelge * Updata buffer address and count. 566*11876Shelge */ 567*11876Shelge tu.tu_addr += tudata.pk_mcount; 568*11876Shelge tu.tu_count -= tudata.pk_mcount; 569*11876Shelge if (tu.tu_count) { 570*11876Shelge tu.tu_state = TUS_WAIT; 571*11876Shelge tu.tu_flag = 1; 572*11876Shelge break; 573*11876Shelge } 574*11876Shelge 575*11876Shelge /* 576*11876Shelge * End of transmission, get ready for end packet. 577*11876Shelge */ 578*11876Shelge tu.tu_state = TUS_GET; 579*11876Shelge tu.tu_rbptr = (u_char *)&tudata; 580*11876Shelge tu.tu_rcnt = sizeof (tudata); 581*11876Shelge tu.tu_flag = 1; 582*11876Shelge mtpr(CSTS, 0); 583*11876Shelge printd("OFF2 "); 584*11876Shelge break; 585*11876Shelge 586*11876Shelge /* 587*11876Shelge * Random interrupt, probably from MRSP ACK 588*11876Shelge */ 589*11876Shelge default: 590*11876Shelge break; 591*11876Shelge } 592*11876Shelge if (tudebug) { 593*11876Shelge printd(" new tu_state="); 594*11876Shelge printstate(tu.tu_state); 595*11876Shelge } 596*11876Shelge } 597*11876Shelge 598*11876Shelge /* 599*11876Shelge * Compute checksum TU58 fashion 600*11876Shelge */ 601*11876Shelge #ifdef lint 602*11876Shelge tuchk(word, cp, n) 603*11876Shelge register word; 604*11876Shelge register unsigned short *cp; 605*11876Shelge int n; 606*11876Shelge { 607*11876Shelge register int c = n >> 1; 608*11876Shelge register long temp; 609*11876Shelge 610*11876Shelge do { 611*11876Shelge temp = *cp++; /* temp, only because vax cc won't *r++ */ 612*11876Shelge word += temp; 613*11876Shelge } while (--c > 0); 614*11876Shelge if (n & 1) 615*11876Shelge word += *(unsigned char *)cp; 616*11876Shelge while (word & 0xffff0000) 617*11876Shelge word = (word & 0xffff) + ((word >> 16) & 0xffff); 618*11876Shelge return (word); 619*11876Shelge } 620*11876Shelge #else 621*11876Shelge tuchk(word0, wp, n) 622*11876Shelge register int word0; /* r11 */ 623*11876Shelge register char *wp; /* r10 */ 624*11876Shelge register int n; /* r9 */ 625*11876Shelge { 626*11876Shelge asm("loop:"); 627*11876Shelge asm(" addw2 (r10)+,r11"); /* add a word to sum */ 628*11876Shelge asm(" adwc $0,r11"); /* add in carry, end-around */ 629*11876Shelge asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 630*11876Shelge asm(" blbc r9,ok"); /* odd byte count? */ 631*11876Shelge asm(" movzbw (r10),r10"); /* yes, get last byte */ 632*11876Shelge asm(" addw2 r10,r11"); /* add it in */ 633*11876Shelge asm(" adwc $0,r11"); /* and the carry */ 634*11876Shelge asm("ok:"); 635*11876Shelge asm(" movl r11,r0"); /* return sum */ 636*11876Shelge } 637*11876Shelge #endif 638*11876Shelge 639*11876Shelge tuwatch() 640*11876Shelge { 641*11876Shelge register int s; 642*11876Shelge register struct buf *bp; 643*11876Shelge 644*11876Shelge if (tutimer == 0) { 645*11876Shelge tu.tu_flag = 0; 646*11876Shelge return; 647*11876Shelge } 648*11876Shelge if (tu.tu_flag) 649*11876Shelge tu.tu_flag++; 650*11876Shelge if (tu.tu_flag <= 40) { 651*11876Shelge timeout(tuwatch, (caddr_t)0, hz); 652*11876Shelge return; 653*11876Shelge } 654*11876Shelge printf("tu: read stalled\n"); 655*11876Shelge printf("%X %X %X %X %X %X %X %X\n", tu.tu_rbptr, tu.tu_rcnt, 656*11876Shelge tu.tu_wbptr, tu.tu_wcnt, tu.tu_state, tu.tu_flag, 657*11876Shelge tu.tu_addr, tu.tu_count); 658*11876Shelge tu.tu_flag = 0; 659*11876Shelge s = splx(TUIPL); 660*11876Shelge (void) mfpr(CSRD); 661*11876Shelge mtpr(CSRS, IE); /* in case we were flushing */ 662*11876Shelge mtpr(CSTS, IE); 663*11876Shelge tu.tu_state = TUS_IDLE; 664*11876Shelge if (!tutab.b_active) { 665*11876Shelge wakeup((caddr_t)&tu); 666*11876Shelge goto retry; 667*11876Shelge } 668*11876Shelge if (++tutab.b_errcnt <= 1) { 669*11876Shelge tustart(); 670*11876Shelge goto retry; 671*11876Shelge } 672*11876Shelge if (bp = tutab.b_actf) { 673*11876Shelge bp->b_flags |= B_ERROR; 674*11876Shelge if ((bp->b_flags&B_READ) == 0) 675*11876Shelge tu_vee(&pcnt[minor(bp->b_dev)&DNUM]); 676*11876Shelge iodone(bp); 677*11876Shelge } 678*11876Shelge retry: 679*11876Shelge splx(s); 680*11876Shelge timeout(tuwatch, (caddr_t)0, hz); 681*11876Shelge } 682*11876Shelge 683*11876Shelge tu_pee(cp) 684*11876Shelge char *cp; 685*11876Shelge { 686*11876Shelge register int s; 687*11876Shelge 688*11876Shelge s = splx(TUIPL); 689*11876Shelge if (++(*cp) > NTUQ) 690*11876Shelge sleep(cp, PRIBIO); 691*11876Shelge splx(s); 692*11876Shelge } 693*11876Shelge 694*11876Shelge tu_vee(cp) 695*11876Shelge char *cp; 696*11876Shelge { 697*11876Shelge register int s; 698*11876Shelge 699*11876Shelge s = splx(TUIPL); 700*11876Shelge if (--(*cp) <= NTUQ) 701*11876Shelge wakeup(cp); 702*11876Shelge splx(s); 703*11876Shelge } 704*11876Shelge #endif 705