1*220Sbill /* ht.c 3.3 10/14/12 */ 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" 1522Sbill #include "../h/mba.h" 1622Sbill 1722Sbill struct device 1822Sbill { 1922Sbill int htcs1; 2022Sbill int htds; 2122Sbill int hter; 2222Sbill int htmr; 2322Sbill int htas; 2422Sbill int htfc; 2522Sbill int htdt; 2622Sbill int htck; 2722Sbill int htsn; 2822Sbill int httc; 2922Sbill }; 3022Sbill 3122Sbill struct buf httab; 3222Sbill struct buf rhtbuf; 3322Sbill struct buf chtbuf; 3422Sbill 3522Sbill #define NUNIT 1 3622Sbill #define BUNIT 2 3722Sbill #define INF 1000000 3822Sbill 3922Sbill char h_openf[NUNIT]; 4022Sbill daddr_t h_blkno[NUNIT]; 4122Sbill char h_flags[NUNIT]; 4222Sbill daddr_t h_nxrec[NUNIT]; 4322Sbill 4422Sbill #define HTADDR ((struct device *)(MBA1 + MBA_ERB)) 4522Sbill 4622Sbill #define GO 01 4722Sbill #define WCOM 060 4822Sbill #define RCOM 070 4922Sbill #define NOP 0 5022Sbill #define WEOF 026 5122Sbill #define SFORW 030 5222Sbill #define SREV 032 5322Sbill #define ERASE 024 5422Sbill #define REW 06 5522Sbill #define DCLR 010 5622Sbill #define P800 01700 /* 800 + pdp11 mode */ 5722Sbill #define P1600 02300 /* 1600 + pdp11 mode */ 5822Sbill #define IENABLE 0100 5922Sbill #define RDY 0200 6022Sbill #define TM 04 6122Sbill #define DRY 0200 6222Sbill #define EOT 02000 6322Sbill #define CS 02000 6422Sbill #define COR 0100000 6522Sbill #define PES 040 6622Sbill #define WRL 04000 6722Sbill #define MOL 010000 6822Sbill #define ERR 040000 6922Sbill #define FCE 01000 7022Sbill #define TRE 040000 7122Sbill #define HARD 064023 /* UNS|OPI|NEF|FMT|RMR|ILR|ILF */ 7222Sbill 7322Sbill #define SIO 1 7422Sbill #define SSFOR 2 7522Sbill #define SSREV 3 7622Sbill #define SRETRY 4 7722Sbill #define SCOM 5 7822Sbill #define SOK 6 7922Sbill 8022Sbill #define H_WRITTEN 1 8122Sbill 8222Sbill htopen(dev, flag) 8322Sbill { 8422Sbill register unit, ds; 8522Sbill 8622Sbill httab.b_flags |= B_TAPE; 8722Sbill unit = minor(dev) & 03; 8822Sbill if (unit >= NUNIT || h_openf[unit]) { 8922Sbill u.u_error = ENXIO; 9022Sbill return; 9122Sbill } 9222Sbill h_blkno[unit] = 0; 9322Sbill h_nxrec[unit] = INF; 9422Sbill h_flags[unit] = 0; 9522Sbill ds = hcommand(dev, NOP); 9622Sbill if ((ds&MOL)==0 || (flag && (ds&WRL))) 9722Sbill u.u_error = ENXIO; 9822Sbill if (u.u_error==0) 9922Sbill h_openf[unit]++; 10022Sbill } 10122Sbill 10222Sbill htclose(dev, flag) 10322Sbill { 10422Sbill register int unit; 10522Sbill 10622Sbill unit = minor(dev) & 03; 10722Sbill if (flag == FWRITE || ((flag&FWRITE) && (h_flags[unit]&H_WRITTEN))) { 108128Sbill (void) hcommand(dev, WEOF); 109128Sbill (void) hcommand(dev, WEOF); 110128Sbill (void) hcommand(dev, SREV); 11122Sbill } 11222Sbill if((minor(dev)&4) == 0) /* no 4 -> rewind */ 113128Sbill (void) hcommand(dev, REW); 11422Sbill h_openf[unit] = 0; 11522Sbill } 11622Sbill 11722Sbill hcommand(dev, com) 11822Sbill { 11922Sbill register struct buf *bp; 12022Sbill 12122Sbill bp = &chtbuf; 122128Sbill (void) spl5(); 12322Sbill while(bp->b_flags&B_BUSY) { 12422Sbill bp->b_flags |= B_WANTED; 12522Sbill sleep((caddr_t)bp, PRIBIO); 12622Sbill } 127128Sbill (void) spl0(); 12822Sbill bp->b_dev = dev; 12922Sbill bp->b_resid = com; 13022Sbill bp->b_blkno = 0; 13122Sbill bp->b_flags = B_BUSY|B_READ; 13222Sbill htstrategy(bp); 13322Sbill iowait(bp); 13422Sbill if(bp->b_flags&B_WANTED) 13522Sbill wakeup((caddr_t)bp); 13622Sbill bp->b_flags = 0; 13722Sbill return(bp->b_resid); 13822Sbill } 13922Sbill 14022Sbill htstrategy(bp) 14122Sbill register struct buf *bp; 14222Sbill { 14322Sbill register daddr_t *p; 14422Sbill 14522Sbill if(bp != &chtbuf) { 14622Sbill p = &h_nxrec[minor(bp->b_dev)&03]; 14722Sbill if(dbtofsb(bp->b_blkno) > *p) { 14822Sbill bp->b_flags |= B_ERROR; 14922Sbill bp->b_error = ENXIO; 15022Sbill iodone(bp); 15122Sbill return; 15222Sbill } 15322Sbill if(dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) { 15422Sbill bp->b_resid = bp->b_bcount; 15522Sbill clrbuf(bp); 15622Sbill iodone(bp); 15722Sbill return; 15822Sbill } 15922Sbill if ((bp->b_flags&B_READ)==0) { 16022Sbill *p = dbtofsb(bp->b_blkno) + 1; 16122Sbill h_flags[minor(bp->b_dev)&03] |= H_WRITTEN; 16222Sbill } 16322Sbill } 16422Sbill bp->av_forw = NULL; 165128Sbill (void) spl5(); 16622Sbill if (httab.b_actf == NULL) 16722Sbill httab.b_actf = bp; 16822Sbill else 16922Sbill httab.b_actl->av_forw = bp; 17022Sbill httab.b_actl = bp; 17122Sbill if (httab.b_active==0) 17222Sbill htstart(); 173128Sbill (void) spl0(); 17422Sbill } 17522Sbill 17622Sbill htstart() 17722Sbill { 17822Sbill register struct buf *bp; 17922Sbill register unit, den; 18022Sbill daddr_t blkno; 18122Sbill 18222Sbill loop: 18322Sbill if ((bp = httab.b_actf) == NULL) 18422Sbill return; 18522Sbill unit = minor(bp->b_dev); 18622Sbill den = P800 | (unit&03); 18722Sbill if(unit >= 8) 18822Sbill den = P1600 | (unit&03); 18922Sbill if((HTADDR->httc&03777) != den) 19022Sbill HTADDR->httc = den; 19122Sbill unit &= 03; 19222Sbill blkno = h_blkno[unit]; 19322Sbill if (bp == &chtbuf) { 19422Sbill if (bp->b_resid==NOP) { 19522Sbill bp->b_resid = HTADDR->htds & 0xffff; 19622Sbill goto next; 19722Sbill } 19822Sbill httab.b_active = SCOM; 19922Sbill HTADDR->htfc = 0; 20022Sbill HTADDR->htcs1 = bp->b_resid|GO; 20122Sbill return; 20222Sbill } 20322Sbill if (h_openf[unit] < 0 || dbtofsb(bp->b_blkno) > h_nxrec[unit]) 20422Sbill goto abort; 20522Sbill if (blkno == dbtofsb(bp->b_blkno)) { 20622Sbill httab.b_active = SIO; 20722Sbill HTADDR->htfc = -bp->b_bcount; 20822Sbill mbastart(bp, (int *)HTADDR); 20922Sbill } else { 21022Sbill if (blkno < dbtofsb(bp->b_blkno)) { 21122Sbill httab.b_active = SSFOR; 21222Sbill HTADDR->htfc = blkno - dbtofsb(bp->b_blkno); 21322Sbill HTADDR->htcs1 = SFORW|GO; 21422Sbill } else { 21522Sbill httab.b_active = SSREV; 21622Sbill HTADDR->htfc = dbtofsb(bp->b_blkno) - blkno; 21722Sbill HTADDR->htcs1 = SREV|GO; 21822Sbill } 21922Sbill } 22022Sbill return; 22122Sbill 22222Sbill abort: 22322Sbill bp->b_flags |= B_ERROR; 22422Sbill 22522Sbill next: 22622Sbill httab.b_actf = bp->av_forw; 22722Sbill iodone(bp); 22822Sbill goto loop; 22922Sbill } 23022Sbill 23122Sbill /*ARGSUSED*/ 23222Sbill htintr(mbastat, as) 23322Sbill { 23422Sbill register struct buf *bp; 23522Sbill register int unit, state; 23622Sbill int err; 23722Sbill 23822Sbill if ((bp = httab.b_actf)==NULL) 23922Sbill return; 24022Sbill unit = minor(bp->b_dev) & 03; 24122Sbill state = httab.b_active; 24222Sbill httab.b_active = 0; 24322Sbill if (HTADDR->htds&(ERR|EOT|TM) || mbastat & MBAEBITS) { 24422Sbill err = HTADDR->hter & 0xffff; 24522Sbill if ((mbastat & MBAEBITS) || (err&HARD)) 24622Sbill state = 0; 24722Sbill if (bp == &rhtbuf) 24822Sbill err &= ~FCE; 24922Sbill if ((bp->b_flags&B_READ) && (HTADDR->htds&PES)) 25022Sbill err &= ~(CS|COR); 25122Sbill if(HTADDR->htds&EOT || (HTADDR->htds&MOL)==0) { 25222Sbill if(h_openf[unit]) 25322Sbill h_openf[unit] = -1; 25422Sbill } 25522Sbill else if(HTADDR->htds&TM) { 25622Sbill HTADDR->htfc = 0; 25722Sbill h_nxrec[unit] = dbtofsb(bp->b_blkno); 25822Sbill state = SOK; 25922Sbill } 26022Sbill else if(state && err == 0) 26122Sbill state = SOK; 26222Sbill if(httab.b_errcnt > 4) 26322Sbill deverror(bp, HTADDR->hter, mbastat); 26422Sbill ((struct mba_regs *)MBA1)->mba_cr &= ~MBAIE; 26522Sbill HTADDR->htcs1 = DCLR|GO; 26622Sbill ((struct mba_regs *)MBA1)->mba_cr |= MBAIE; 26722Sbill if (state==SIO && ++httab.b_errcnt < 10) { 26822Sbill httab.b_active = SRETRY; 26922Sbill h_blkno[unit]++; 27022Sbill HTADDR->htfc = -1; 27122Sbill HTADDR->htcs1 = SREV|GO; 27222Sbill return; 27322Sbill } 27422Sbill if (state!=SOK) { 27522Sbill bp->b_flags |= B_ERROR; 27622Sbill state = SIO; 27722Sbill } 27822Sbill } else if (HTADDR->htcs1 < 0) { /* SC */ 27922Sbill if(HTADDR->htds & ERR) { 28022Sbill ((struct mba_regs *)MBA1)->mba_cr &= ~MBAIE; 28122Sbill HTADDR->htcs1 = DCLR|GO; 28222Sbill ((struct mba_regs *)MBA1)->mba_cr |= MBAIE; 28322Sbill } 28422Sbill } 28522Sbill switch(state) { 28622Sbill case SIO: 28722Sbill case SOK: 28822Sbill h_blkno[unit]++; 28922Sbill 29022Sbill case SCOM: 29122Sbill httab.b_errcnt = 0; 29222Sbill httab.b_actf = bp->av_forw; 29322Sbill bp->b_resid = - (HTADDR->htfc & 0xffff); 29422Sbill if (bp->b_flags & B_READ) 29522Sbill bp->b_resid += bp->b_bcount; 29622Sbill iodone(bp); 29722Sbill break; 29822Sbill 29922Sbill case SRETRY: 30022Sbill if((bp->b_flags&B_READ)==0) { 30122Sbill httab.b_active = SSFOR; 30222Sbill HTADDR->htcs1 = ERASE|GO; 30322Sbill return; 30422Sbill } 30522Sbill 30622Sbill case SSFOR: 30722Sbill case SSREV: 308*220Sbill #define blk dbtofsb(bp->b_blkno) 30922Sbill if(HTADDR->htds & TM) { 31022Sbill if(state == SSREV) { 311*220Sbill h_nxrec[unit] = blk - (HTADDR->htfc&0xffff); 31222Sbill h_blkno[unit] = h_nxrec[unit]; 31322Sbill } else { 314*220Sbill h_nxrec[unit] = blk + (HTADDR->htfc&0xffff) - 1; 315*220Sbill h_blkno[unit] = blk + (HTADDR->htfc & 0xffff); 31622Sbill } 31722Sbill } else 318*220Sbill h_blkno[unit] = blk; 31922Sbill break; 32022Sbill 32122Sbill default: 32222Sbill return; 32322Sbill } 32422Sbill htstart(); 32522Sbill } 32622Sbill 32722Sbill htread(dev) 32822Sbill { 32922Sbill htphys(dev); 33022Sbill physio(htstrategy, &rhtbuf, dev, B_READ, minphys); 33122Sbill } 33222Sbill 33322Sbill htwrite(dev) 33422Sbill { 33522Sbill htphys(dev); 33622Sbill physio(htstrategy, &rhtbuf, dev, B_WRITE, minphys); 33722Sbill } 33822Sbill 33922Sbill htphys(dev) 34022Sbill { 34122Sbill register unit; 34222Sbill daddr_t a; 34322Sbill 34422Sbill unit = minor(dev) & 03; 34522Sbill if(unit < NUNIT) { 34622Sbill a = u.u_offset >> 9; 34722Sbill h_blkno[unit] = dbtofsb(a); 34822Sbill h_nxrec[unit] = dbtofsb(a)+1; 34922Sbill } 35022Sbill } 351