1*22Sbill /* ht.c 3.1 10/14/12 */ 2*22Sbill 3*22Sbill /* 4*22Sbill * TJU16 tape driver 5*22Sbill */ 6*22Sbill 7*22Sbill #include "../h/param.h" 8*22Sbill #include "../h/systm.h" 9*22Sbill #include "../h/buf.h" 10*22Sbill #include "../h/conf.h" 11*22Sbill #include "../h/dir.h" 12*22Sbill #include "../h/file.h" 13*22Sbill #include "../h/user.h" 14*22Sbill #include "../h/map.h" 15*22Sbill #include "../h/mba.h" 16*22Sbill 17*22Sbill struct device 18*22Sbill { 19*22Sbill int htcs1; 20*22Sbill int htds; 21*22Sbill int hter; 22*22Sbill int htmr; 23*22Sbill int htas; 24*22Sbill int htfc; 25*22Sbill int htdt; 26*22Sbill int htck; 27*22Sbill int htsn; 28*22Sbill int httc; 29*22Sbill }; 30*22Sbill 31*22Sbill struct buf httab; 32*22Sbill struct buf rhtbuf; 33*22Sbill struct buf chtbuf; 34*22Sbill 35*22Sbill #define NUNIT 1 36*22Sbill #define BUNIT 2 37*22Sbill #define INF 1000000 38*22Sbill 39*22Sbill char h_openf[NUNIT]; 40*22Sbill daddr_t h_blkno[NUNIT]; 41*22Sbill char h_flags[NUNIT]; 42*22Sbill daddr_t h_nxrec[NUNIT]; 43*22Sbill 44*22Sbill #define HTADDR ((struct device *)(MBA1 + MBA_ERB)) 45*22Sbill 46*22Sbill #define GO 01 47*22Sbill #define WCOM 060 48*22Sbill #define RCOM 070 49*22Sbill #define NOP 0 50*22Sbill #define WEOF 026 51*22Sbill #define SFORW 030 52*22Sbill #define SREV 032 53*22Sbill #define ERASE 024 54*22Sbill #define REW 06 55*22Sbill #define DCLR 010 56*22Sbill #define P800 01700 /* 800 + pdp11 mode */ 57*22Sbill #define P1600 02300 /* 1600 + pdp11 mode */ 58*22Sbill #define IENABLE 0100 59*22Sbill #define RDY 0200 60*22Sbill #define TM 04 61*22Sbill #define DRY 0200 62*22Sbill #define EOT 02000 63*22Sbill #define CS 02000 64*22Sbill #define COR 0100000 65*22Sbill #define PES 040 66*22Sbill #define WRL 04000 67*22Sbill #define MOL 010000 68*22Sbill #define ERR 040000 69*22Sbill #define FCE 01000 70*22Sbill #define TRE 040000 71*22Sbill #define HARD 064023 /* UNS|OPI|NEF|FMT|RMR|ILR|ILF */ 72*22Sbill 73*22Sbill #define SIO 1 74*22Sbill #define SSFOR 2 75*22Sbill #define SSREV 3 76*22Sbill #define SRETRY 4 77*22Sbill #define SCOM 5 78*22Sbill #define SOK 6 79*22Sbill 80*22Sbill #define H_WRITTEN 1 81*22Sbill 82*22Sbill htopen(dev, flag) 83*22Sbill { 84*22Sbill register unit, ds; 85*22Sbill 86*22Sbill httab.b_flags |= B_TAPE; 87*22Sbill unit = minor(dev) & 03; 88*22Sbill if (unit >= NUNIT || h_openf[unit]) { 89*22Sbill u.u_error = ENXIO; 90*22Sbill return; 91*22Sbill } 92*22Sbill h_blkno[unit] = 0; 93*22Sbill h_nxrec[unit] = INF; 94*22Sbill h_flags[unit] = 0; 95*22Sbill ds = hcommand(dev, NOP); 96*22Sbill if ((ds&MOL)==0 || (flag && (ds&WRL))) 97*22Sbill u.u_error = ENXIO; 98*22Sbill if (u.u_error==0) 99*22Sbill h_openf[unit]++; 100*22Sbill } 101*22Sbill 102*22Sbill htclose(dev, flag) 103*22Sbill { 104*22Sbill register int unit; 105*22Sbill 106*22Sbill unit = minor(dev) & 03; 107*22Sbill if (flag == FWRITE || ((flag&FWRITE) && (h_flags[unit]&H_WRITTEN))) { 108*22Sbill VOID hcommand(dev, WEOF); 109*22Sbill VOID hcommand(dev, WEOF); 110*22Sbill VOID hcommand(dev, SREV); 111*22Sbill } 112*22Sbill /* VOID hcommand(dev, REW); */ 113*22Sbill /* for 'mtm' file positioning */ 114*22Sbill if((minor(dev)&4) == 0) /* no 4 -> rewind */ 115*22Sbill VOID hcommand(dev, REW); 116*22Sbill h_openf[unit] = 0; 117*22Sbill } 118*22Sbill 119*22Sbill hcommand(dev, com) 120*22Sbill { 121*22Sbill register struct buf *bp; 122*22Sbill 123*22Sbill bp = &chtbuf; 124*22Sbill VOID spl5(); 125*22Sbill while(bp->b_flags&B_BUSY) { 126*22Sbill bp->b_flags |= B_WANTED; 127*22Sbill sleep((caddr_t)bp, PRIBIO); 128*22Sbill } 129*22Sbill VOID spl0(); 130*22Sbill bp->b_dev = dev; 131*22Sbill bp->b_resid = com; 132*22Sbill bp->b_blkno = 0; 133*22Sbill bp->b_flags = B_BUSY|B_READ; 134*22Sbill htstrategy(bp); 135*22Sbill iowait(bp); 136*22Sbill if(bp->b_flags&B_WANTED) 137*22Sbill wakeup((caddr_t)bp); 138*22Sbill bp->b_flags = 0; 139*22Sbill return(bp->b_resid); 140*22Sbill } 141*22Sbill 142*22Sbill htstrategy(bp) 143*22Sbill register struct buf *bp; 144*22Sbill { 145*22Sbill register daddr_t *p; 146*22Sbill 147*22Sbill if(bp != &chtbuf) { 148*22Sbill p = &h_nxrec[minor(bp->b_dev)&03]; 149*22Sbill if(dbtofsb(bp->b_blkno) > *p) { 150*22Sbill bp->b_flags |= B_ERROR; 151*22Sbill bp->b_error = ENXIO; 152*22Sbill iodone(bp); 153*22Sbill return; 154*22Sbill } 155*22Sbill if(dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) { 156*22Sbill bp->b_resid = bp->b_bcount; 157*22Sbill clrbuf(bp); 158*22Sbill iodone(bp); 159*22Sbill return; 160*22Sbill } 161*22Sbill if ((bp->b_flags&B_READ)==0) { 162*22Sbill *p = dbtofsb(bp->b_blkno) + 1; 163*22Sbill h_flags[minor(bp->b_dev)&03] |= H_WRITTEN; 164*22Sbill } 165*22Sbill } 166*22Sbill bp->av_forw = NULL; 167*22Sbill VOID spl5(); 168*22Sbill if (httab.b_actf == NULL) 169*22Sbill httab.b_actf = bp; 170*22Sbill else 171*22Sbill httab.b_actl->av_forw = bp; 172*22Sbill httab.b_actl = bp; 173*22Sbill if (httab.b_active==0) 174*22Sbill htstart(); 175*22Sbill VOID spl0(); 176*22Sbill } 177*22Sbill 178*22Sbill htstart() 179*22Sbill { 180*22Sbill register struct buf *bp; 181*22Sbill register unit, den; 182*22Sbill daddr_t blkno; 183*22Sbill 184*22Sbill loop: 185*22Sbill if ((bp = httab.b_actf) == NULL) 186*22Sbill return; 187*22Sbill unit = minor(bp->b_dev); 188*22Sbill den = P800 | (unit&03); 189*22Sbill if(unit >= 8) 190*22Sbill den = P1600 | (unit&03); 191*22Sbill if((HTADDR->httc&03777) != den) 192*22Sbill HTADDR->httc = den; 193*22Sbill unit &= 03; 194*22Sbill blkno = h_blkno[unit]; 195*22Sbill if (bp == &chtbuf) { 196*22Sbill if (bp->b_resid==NOP) { 197*22Sbill bp->b_resid = HTADDR->htds & 0xffff; 198*22Sbill goto next; 199*22Sbill } 200*22Sbill httab.b_active = SCOM; 201*22Sbill HTADDR->htfc = 0; 202*22Sbill HTADDR->htcs1 = bp->b_resid|GO; 203*22Sbill return; 204*22Sbill } 205*22Sbill if (h_openf[unit] < 0 || dbtofsb(bp->b_blkno) > h_nxrec[unit]) 206*22Sbill goto abort; 207*22Sbill if (blkno == dbtofsb(bp->b_blkno)) { 208*22Sbill httab.b_active = SIO; 209*22Sbill HTADDR->htfc = -bp->b_bcount; 210*22Sbill mbastart(bp, (int *)HTADDR); 211*22Sbill } else { 212*22Sbill if (blkno < dbtofsb(bp->b_blkno)) { 213*22Sbill httab.b_active = SSFOR; 214*22Sbill HTADDR->htfc = blkno - dbtofsb(bp->b_blkno); 215*22Sbill HTADDR->htcs1 = SFORW|GO; 216*22Sbill } else { 217*22Sbill httab.b_active = SSREV; 218*22Sbill HTADDR->htfc = dbtofsb(bp->b_blkno) - blkno; 219*22Sbill HTADDR->htcs1 = SREV|GO; 220*22Sbill } 221*22Sbill } 222*22Sbill return; 223*22Sbill 224*22Sbill abort: 225*22Sbill bp->b_flags |= B_ERROR; 226*22Sbill 227*22Sbill next: 228*22Sbill httab.b_actf = bp->av_forw; 229*22Sbill iodone(bp); 230*22Sbill goto loop; 231*22Sbill } 232*22Sbill 233*22Sbill /*ARGSUSED*/ 234*22Sbill htintr(mbastat, as) 235*22Sbill { 236*22Sbill register struct buf *bp; 237*22Sbill register int unit, state; 238*22Sbill int err; 239*22Sbill 240*22Sbill if ((bp = httab.b_actf)==NULL) 241*22Sbill return; 242*22Sbill unit = minor(bp->b_dev) & 03; 243*22Sbill state = httab.b_active; 244*22Sbill httab.b_active = 0; 245*22Sbill if (HTADDR->htds&(ERR|EOT|TM) || mbastat & MBAEBITS) { 246*22Sbill err = HTADDR->hter & 0xffff; 247*22Sbill if ((mbastat & MBAEBITS) || (err&HARD)) 248*22Sbill state = 0; 249*22Sbill if (bp == &rhtbuf) 250*22Sbill err &= ~FCE; 251*22Sbill if ((bp->b_flags&B_READ) && (HTADDR->htds&PES)) 252*22Sbill err &= ~(CS|COR); 253*22Sbill if(HTADDR->htds&EOT || (HTADDR->htds&MOL)==0) { 254*22Sbill if(h_openf[unit]) 255*22Sbill h_openf[unit] = -1; 256*22Sbill } 257*22Sbill else if(HTADDR->htds&TM) { 258*22Sbill HTADDR->htfc = 0; 259*22Sbill h_nxrec[unit] = dbtofsb(bp->b_blkno); 260*22Sbill state = SOK; 261*22Sbill } 262*22Sbill else if(state && err == 0) 263*22Sbill state = SOK; 264*22Sbill if(httab.b_errcnt > 4) 265*22Sbill deverror(bp, HTADDR->hter, mbastat); 266*22Sbill ((struct mba_regs *)MBA1)->mba_cr &= ~MBAIE; 267*22Sbill HTADDR->htcs1 = DCLR|GO; 268*22Sbill ((struct mba_regs *)MBA1)->mba_cr |= MBAIE; 269*22Sbill if (state==SIO && ++httab.b_errcnt < 10) { 270*22Sbill httab.b_active = SRETRY; 271*22Sbill h_blkno[unit]++; 272*22Sbill HTADDR->htfc = -1; 273*22Sbill HTADDR->htcs1 = SREV|GO; 274*22Sbill return; 275*22Sbill } 276*22Sbill if (state!=SOK) { 277*22Sbill bp->b_flags |= B_ERROR; 278*22Sbill state = SIO; 279*22Sbill } 280*22Sbill } else if (HTADDR->htcs1 < 0) { /* SC */ 281*22Sbill if(HTADDR->htds & ERR) { 282*22Sbill ((struct mba_regs *)MBA1)->mba_cr &= ~MBAIE; 283*22Sbill HTADDR->htcs1 = DCLR|GO; 284*22Sbill ((struct mba_regs *)MBA1)->mba_cr |= MBAIE; 285*22Sbill } 286*22Sbill } 287*22Sbill switch(state) { 288*22Sbill case SIO: 289*22Sbill case SOK: 290*22Sbill h_blkno[unit]++; 291*22Sbill 292*22Sbill case SCOM: 293*22Sbill httab.b_errcnt = 0; 294*22Sbill httab.b_actf = bp->av_forw; 295*22Sbill bp->b_resid = - (HTADDR->htfc & 0xffff); 296*22Sbill if (bp->b_flags & B_READ) 297*22Sbill bp->b_resid += bp->b_bcount; 298*22Sbill iodone(bp); 299*22Sbill break; 300*22Sbill 301*22Sbill case SRETRY: 302*22Sbill if((bp->b_flags&B_READ)==0) { 303*22Sbill httab.b_active = SSFOR; 304*22Sbill HTADDR->htcs1 = ERASE|GO; 305*22Sbill return; 306*22Sbill } 307*22Sbill 308*22Sbill case SSFOR: 309*22Sbill case SSREV: 310*22Sbill if(HTADDR->htds & TM) { 311*22Sbill if(state == SSREV) { 312*22Sbill h_nxrec[unit] = dbtofsb(bp->b_blkno) - (HTADDR->htfc&0xffff); 313*22Sbill h_blkno[unit] = h_nxrec[unit]; 314*22Sbill } else { 315*22Sbill h_nxrec[unit] = dbtofsb(bp->b_blkno) + (HTADDR->htfc & 0xffff) - 1; 316*22Sbill h_blkno[unit] = dbtofsb(bp->b_blkno) + (HTADDR->htfc & 0xffff); 317*22Sbill } 318*22Sbill } else 319*22Sbill h_blkno[unit] = dbtofsb(bp->b_blkno); 320*22Sbill break; 321*22Sbill 322*22Sbill default: 323*22Sbill return; 324*22Sbill } 325*22Sbill htstart(); 326*22Sbill } 327*22Sbill 328*22Sbill htread(dev) 329*22Sbill { 330*22Sbill htphys(dev); 331*22Sbill physio(htstrategy, &rhtbuf, dev, B_READ, minphys); 332*22Sbill } 333*22Sbill 334*22Sbill htwrite(dev) 335*22Sbill { 336*22Sbill htphys(dev); 337*22Sbill physio(htstrategy, &rhtbuf, dev, B_WRITE, minphys); 338*22Sbill } 339*22Sbill 340*22Sbill htphys(dev) 341*22Sbill { 342*22Sbill register unit; 343*22Sbill daddr_t a; 344*22Sbill 345*22Sbill unit = minor(dev) & 03; 346*22Sbill if(unit < NUNIT) { 347*22Sbill a = u.u_offset >> 9; 348*22Sbill h_blkno[unit] = dbtofsb(a); 349*22Sbill h_nxrec[unit] = dbtofsb(a)+1; 350*22Sbill } 351*22Sbill } 352