1*420Sbill /* ht.c 3.5 07/29/80 */ 222Sbill 322Sbill /* 422Sbill * TJU16 tape driver 522Sbill */ 622Sbill 722Sbill #include "../h/param.h" 822Sbill #include "../h/systm.h" 922Sbill #include "../h/buf.h" 1022Sbill #include "../h/conf.h" 1122Sbill #include "../h/dir.h" 1222Sbill #include "../h/file.h" 1322Sbill #include "../h/user.h" 1422Sbill #include "../h/map.h" 15*420Sbill #include "../h/pte.h" 1622Sbill #include "../h/mba.h" 1722Sbill 1822Sbill struct device 1922Sbill { 2022Sbill int htcs1; 2122Sbill int htds; 2222Sbill int hter; 2322Sbill int htmr; 2422Sbill int htas; 2522Sbill int htfc; 2622Sbill int htdt; 2722Sbill int htck; 2822Sbill int htsn; 2922Sbill int httc; 3022Sbill }; 3122Sbill 3222Sbill struct buf httab; 3322Sbill struct buf rhtbuf; 3422Sbill struct buf chtbuf; 3522Sbill 3622Sbill #define NUNIT 1 3722Sbill #define BUNIT 2 3822Sbill #define INF 1000000 3922Sbill 4022Sbill char h_openf[NUNIT]; 4122Sbill daddr_t h_blkno[NUNIT]; 4222Sbill char h_flags[NUNIT]; 4322Sbill daddr_t h_nxrec[NUNIT]; 4422Sbill 45*420Sbill #define HTMBA MBA1 46*420Sbill #define HTMBANUM 1 4722Sbill 4822Sbill #define GO 01 4922Sbill #define WCOM 060 5022Sbill #define RCOM 070 5122Sbill #define NOP 0 5222Sbill #define WEOF 026 5322Sbill #define SFORW 030 5422Sbill #define SREV 032 5522Sbill #define ERASE 024 5622Sbill #define REW 06 5722Sbill #define DCLR 010 5822Sbill #define P800 01700 /* 800 + pdp11 mode */ 5922Sbill #define P1600 02300 /* 1600 + pdp11 mode */ 6022Sbill #define IENABLE 0100 6122Sbill #define RDY 0200 6222Sbill #define TM 04 6322Sbill #define DRY 0200 6422Sbill #define EOT 02000 6522Sbill #define CS 02000 6622Sbill #define COR 0100000 6722Sbill #define PES 040 6822Sbill #define WRL 04000 6922Sbill #define MOL 010000 7022Sbill #define ERR 040000 7122Sbill #define FCE 01000 7222Sbill #define TRE 040000 7322Sbill #define HARD 064023 /* UNS|OPI|NEF|FMT|RMR|ILR|ILF */ 7422Sbill 7522Sbill #define SIO 1 7622Sbill #define SSFOR 2 7722Sbill #define SSREV 3 7822Sbill #define SRETRY 4 7922Sbill #define SCOM 5 8022Sbill #define SOK 6 8122Sbill 8222Sbill #define H_WRITTEN 1 8322Sbill 8422Sbill htopen(dev, flag) 8522Sbill { 8622Sbill register unit, ds; 8722Sbill 88*420Sbill if ((mbaact&(1<<HTMBANUM)) == 0) 89*420Sbill mbainit(HTMBANUM); 9022Sbill httab.b_flags |= B_TAPE; 9122Sbill unit = minor(dev) & 03; 9222Sbill if (unit >= NUNIT || h_openf[unit]) { 9322Sbill u.u_error = ENXIO; 9422Sbill return; 9522Sbill } 9622Sbill h_blkno[unit] = 0; 9722Sbill h_nxrec[unit] = INF; 9822Sbill h_flags[unit] = 0; 9922Sbill ds = hcommand(dev, NOP); 10022Sbill if ((ds&MOL)==0 || (flag && (ds&WRL))) 10122Sbill u.u_error = ENXIO; 10222Sbill if (u.u_error==0) 10322Sbill h_openf[unit]++; 10422Sbill } 10522Sbill 10622Sbill htclose(dev, flag) 10722Sbill { 10822Sbill register int unit; 10922Sbill 11022Sbill unit = minor(dev) & 03; 11122Sbill if (flag == FWRITE || ((flag&FWRITE) && (h_flags[unit]&H_WRITTEN))) { 112128Sbill (void) hcommand(dev, WEOF); 113128Sbill (void) hcommand(dev, WEOF); 114128Sbill (void) hcommand(dev, SREV); 11522Sbill } 11622Sbill if((minor(dev)&4) == 0) /* no 4 -> rewind */ 117128Sbill (void) hcommand(dev, REW); 11822Sbill h_openf[unit] = 0; 11922Sbill } 12022Sbill 12122Sbill hcommand(dev, com) 12222Sbill { 12322Sbill register struct buf *bp; 12422Sbill 12522Sbill bp = &chtbuf; 126128Sbill (void) spl5(); 12722Sbill while(bp->b_flags&B_BUSY) { 12822Sbill bp->b_flags |= B_WANTED; 12922Sbill sleep((caddr_t)bp, PRIBIO); 13022Sbill } 131128Sbill (void) spl0(); 13222Sbill bp->b_dev = dev; 13322Sbill bp->b_resid = com; 13422Sbill bp->b_blkno = 0; 13522Sbill bp->b_flags = B_BUSY|B_READ; 13622Sbill htstrategy(bp); 13722Sbill iowait(bp); 13822Sbill if(bp->b_flags&B_WANTED) 13922Sbill wakeup((caddr_t)bp); 14022Sbill bp->b_flags = 0; 14122Sbill return(bp->b_resid); 14222Sbill } 14322Sbill 14422Sbill htstrategy(bp) 14522Sbill register struct buf *bp; 14622Sbill { 14722Sbill register daddr_t *p; 14822Sbill 14922Sbill if(bp != &chtbuf) { 15022Sbill p = &h_nxrec[minor(bp->b_dev)&03]; 15122Sbill if(dbtofsb(bp->b_blkno) > *p) { 15222Sbill bp->b_flags |= B_ERROR; 15322Sbill bp->b_error = ENXIO; 15422Sbill iodone(bp); 15522Sbill return; 15622Sbill } 15722Sbill if(dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) { 15822Sbill bp->b_resid = bp->b_bcount; 15922Sbill clrbuf(bp); 16022Sbill iodone(bp); 16122Sbill return; 16222Sbill } 16322Sbill if ((bp->b_flags&B_READ)==0) { 16422Sbill *p = dbtofsb(bp->b_blkno) + 1; 16522Sbill h_flags[minor(bp->b_dev)&03] |= H_WRITTEN; 16622Sbill } 16722Sbill } 16822Sbill bp->av_forw = NULL; 169128Sbill (void) spl5(); 17022Sbill if (httab.b_actf == NULL) 17122Sbill httab.b_actf = bp; 17222Sbill else 17322Sbill httab.b_actl->av_forw = bp; 17422Sbill httab.b_actl = bp; 17522Sbill if (httab.b_active==0) 17622Sbill htstart(); 177128Sbill (void) spl0(); 17822Sbill } 17922Sbill 18022Sbill htstart() 18122Sbill { 18222Sbill register struct buf *bp; 18322Sbill register unit, den; 18422Sbill daddr_t blkno; 185*420Sbill register struct device *htp = mbadev(HTMBA,0); 18622Sbill 18722Sbill loop: 18822Sbill if ((bp = httab.b_actf) == NULL) 18922Sbill return; 19022Sbill unit = minor(bp->b_dev); 19122Sbill den = P800 | (unit&03); 19222Sbill if(unit >= 8) 19322Sbill den = P1600 | (unit&03); 194*420Sbill if((htp->httc&03777) != den) 195*420Sbill htp->httc = den; 19622Sbill unit &= 03; 19722Sbill blkno = h_blkno[unit]; 19822Sbill if (bp == &chtbuf) { 19922Sbill if (bp->b_resid==NOP) { 200*420Sbill bp->b_resid = htp->htds & 0xffff; 20122Sbill goto next; 20222Sbill } 20322Sbill httab.b_active = SCOM; 204*420Sbill htp->htfc = 0; 205*420Sbill htp->htcs1 = bp->b_resid|GO; 20622Sbill return; 20722Sbill } 20822Sbill if (h_openf[unit] < 0 || dbtofsb(bp->b_blkno) > h_nxrec[unit]) 20922Sbill goto abort; 21022Sbill if (blkno == dbtofsb(bp->b_blkno)) { 21122Sbill httab.b_active = SIO; 212*420Sbill htp->htfc = -bp->b_bcount; 213*420Sbill mbastart(bp, (int *)htp); 21422Sbill } else { 21522Sbill if (blkno < dbtofsb(bp->b_blkno)) { 21622Sbill httab.b_active = SSFOR; 217*420Sbill htp->htfc = blkno - dbtofsb(bp->b_blkno); 218*420Sbill htp->htcs1 = SFORW|GO; 21922Sbill } else { 22022Sbill httab.b_active = SSREV; 221*420Sbill htp->htfc = dbtofsb(bp->b_blkno) - blkno; 222*420Sbill htp->htcs1 = SREV|GO; 22322Sbill } 22422Sbill } 22522Sbill return; 22622Sbill 22722Sbill abort: 22822Sbill bp->b_flags |= B_ERROR; 22922Sbill 23022Sbill next: 23122Sbill httab.b_actf = bp->av_forw; 23222Sbill iodone(bp); 23322Sbill goto loop; 23422Sbill } 23522Sbill 23622Sbill /*ARGSUSED*/ 23722Sbill htintr(mbastat, as) 23822Sbill { 23922Sbill register struct buf *bp; 24022Sbill register int unit, state; 24122Sbill int err; 242*420Sbill register struct device *htp = mbadev(HTMBA,0); 24322Sbill 24422Sbill if ((bp = httab.b_actf)==NULL) 24522Sbill return; 24622Sbill unit = minor(bp->b_dev) & 03; 24722Sbill state = httab.b_active; 24822Sbill httab.b_active = 0; 249*420Sbill if (htp->htds&(ERR|EOT|TM) || mbastat & MBAEBITS) { 250*420Sbill err = htp->hter & 0xffff; 25122Sbill if ((mbastat & MBAEBITS) || (err&HARD)) 25222Sbill state = 0; 25322Sbill if (bp == &rhtbuf) 25422Sbill err &= ~FCE; 255*420Sbill if ((bp->b_flags&B_READ) && (htp->htds&PES)) 25622Sbill err &= ~(CS|COR); 257*420Sbill if(htp->htds&EOT || (htp->htds&MOL)==0) { 25822Sbill if(h_openf[unit]) 25922Sbill h_openf[unit] = -1; 26022Sbill } 261*420Sbill else if(htp->htds&TM) { 262*420Sbill htp->htfc = 0; 26322Sbill h_nxrec[unit] = dbtofsb(bp->b_blkno); 26422Sbill state = SOK; 26522Sbill } 26622Sbill else if(state && err == 0) 26722Sbill state = SOK; 26822Sbill if(httab.b_errcnt > 4) 269*420Sbill deverror(bp, htp->hter, mbastat); 270*420Sbill HTMBA->mba_cr &= ~MBAIE; 271*420Sbill htp->htcs1 = DCLR|GO; 272*420Sbill HTMBA->mba_cr |= MBAIE; 27322Sbill if (state==SIO && ++httab.b_errcnt < 10) { 27422Sbill httab.b_active = SRETRY; 27522Sbill h_blkno[unit]++; 276*420Sbill htp->htfc = -1; 277*420Sbill htp->htcs1 = SREV|GO; 27822Sbill return; 27922Sbill } 28022Sbill if (state!=SOK) { 28122Sbill bp->b_flags |= B_ERROR; 28222Sbill state = SIO; 28322Sbill } 284*420Sbill } else if (htp->htcs1 < 0) { /* SC */ 285*420Sbill if(htp->htds & ERR) { 286*420Sbill HTMBA->mba_cr &= ~MBAIE; 287*420Sbill htp->htcs1 = DCLR|GO; 288*420Sbill HTMBA->mba_cr |= MBAIE; 28922Sbill } 29022Sbill } 29122Sbill switch(state) { 29222Sbill case SIO: 29322Sbill case SOK: 29422Sbill h_blkno[unit]++; 29522Sbill 29622Sbill case SCOM: 29722Sbill httab.b_errcnt = 0; 29822Sbill httab.b_actf = bp->av_forw; 299*420Sbill bp->b_resid = - (htp->htfc & 0xffff); 30022Sbill if (bp->b_flags & B_READ) 30122Sbill bp->b_resid += bp->b_bcount; 30222Sbill iodone(bp); 30322Sbill break; 30422Sbill 30522Sbill case SRETRY: 30622Sbill if((bp->b_flags&B_READ)==0) { 30722Sbill httab.b_active = SSFOR; 308*420Sbill htp->htcs1 = ERASE|GO; 30922Sbill return; 31022Sbill } 31122Sbill 31222Sbill case SSFOR: 31322Sbill case SSREV: 314220Sbill #define blk dbtofsb(bp->b_blkno) 315*420Sbill if(htp->htds & TM) { 31622Sbill if(state == SSREV) { 317*420Sbill h_nxrec[unit] = blk - (htp->htfc&0xffff); 31822Sbill h_blkno[unit] = h_nxrec[unit]; 31922Sbill } else { 320*420Sbill h_nxrec[unit] = blk + (htp->htfc&0xffff) - 1; 321*420Sbill h_blkno[unit] = blk + (htp->htfc & 0xffff); 32222Sbill } 32322Sbill } else 324220Sbill h_blkno[unit] = blk; 32522Sbill break; 32622Sbill 32722Sbill default: 32822Sbill return; 32922Sbill } 33022Sbill htstart(); 33122Sbill } 33222Sbill 33322Sbill htread(dev) 33422Sbill { 33522Sbill htphys(dev); 33622Sbill physio(htstrategy, &rhtbuf, dev, B_READ, minphys); 33722Sbill } 33822Sbill 33922Sbill htwrite(dev) 34022Sbill { 34122Sbill htphys(dev); 34222Sbill physio(htstrategy, &rhtbuf, dev, B_WRITE, minphys); 34322Sbill } 34422Sbill 34522Sbill htphys(dev) 34622Sbill { 34722Sbill register unit; 34822Sbill daddr_t a; 34922Sbill 35022Sbill unit = minor(dev) & 03; 35122Sbill if(unit < NUNIT) { 35222Sbill a = u.u_offset >> 9; 35322Sbill h_blkno[unit] = dbtofsb(a); 35422Sbill h_nxrec[unit] = dbtofsb(a)+1; 35522Sbill } 35622Sbill } 357