1*128Sbill /* ht.c 3.2 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))) { 108*128Sbill (void) hcommand(dev, WEOF); 109*128Sbill (void) hcommand(dev, WEOF); 110*128Sbill (void) hcommand(dev, SREV); 11122Sbill } 112*128Sbill /* (void) hcommand(dev, REW); */ 11322Sbill /* for 'mtm' file positioning */ 11422Sbill if((minor(dev)&4) == 0) /* no 4 -> rewind */ 115*128Sbill (void) hcommand(dev, REW); 11622Sbill h_openf[unit] = 0; 11722Sbill } 11822Sbill 11922Sbill hcommand(dev, com) 12022Sbill { 12122Sbill register struct buf *bp; 12222Sbill 12322Sbill bp = &chtbuf; 124*128Sbill (void) spl5(); 12522Sbill while(bp->b_flags&B_BUSY) { 12622Sbill bp->b_flags |= B_WANTED; 12722Sbill sleep((caddr_t)bp, PRIBIO); 12822Sbill } 129*128Sbill (void) spl0(); 13022Sbill bp->b_dev = dev; 13122Sbill bp->b_resid = com; 13222Sbill bp->b_blkno = 0; 13322Sbill bp->b_flags = B_BUSY|B_READ; 13422Sbill htstrategy(bp); 13522Sbill iowait(bp); 13622Sbill if(bp->b_flags&B_WANTED) 13722Sbill wakeup((caddr_t)bp); 13822Sbill bp->b_flags = 0; 13922Sbill return(bp->b_resid); 14022Sbill } 14122Sbill 14222Sbill htstrategy(bp) 14322Sbill register struct buf *bp; 14422Sbill { 14522Sbill register daddr_t *p; 14622Sbill 14722Sbill if(bp != &chtbuf) { 14822Sbill p = &h_nxrec[minor(bp->b_dev)&03]; 14922Sbill if(dbtofsb(bp->b_blkno) > *p) { 15022Sbill bp->b_flags |= B_ERROR; 15122Sbill bp->b_error = ENXIO; 15222Sbill iodone(bp); 15322Sbill return; 15422Sbill } 15522Sbill if(dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) { 15622Sbill bp->b_resid = bp->b_bcount; 15722Sbill clrbuf(bp); 15822Sbill iodone(bp); 15922Sbill return; 16022Sbill } 16122Sbill if ((bp->b_flags&B_READ)==0) { 16222Sbill *p = dbtofsb(bp->b_blkno) + 1; 16322Sbill h_flags[minor(bp->b_dev)&03] |= H_WRITTEN; 16422Sbill } 16522Sbill } 16622Sbill bp->av_forw = NULL; 167*128Sbill (void) spl5(); 16822Sbill if (httab.b_actf == NULL) 16922Sbill httab.b_actf = bp; 17022Sbill else 17122Sbill httab.b_actl->av_forw = bp; 17222Sbill httab.b_actl = bp; 17322Sbill if (httab.b_active==0) 17422Sbill htstart(); 175*128Sbill (void) spl0(); 17622Sbill } 17722Sbill 17822Sbill htstart() 17922Sbill { 18022Sbill register struct buf *bp; 18122Sbill register unit, den; 18222Sbill daddr_t blkno; 18322Sbill 18422Sbill loop: 18522Sbill if ((bp = httab.b_actf) == NULL) 18622Sbill return; 18722Sbill unit = minor(bp->b_dev); 18822Sbill den = P800 | (unit&03); 18922Sbill if(unit >= 8) 19022Sbill den = P1600 | (unit&03); 19122Sbill if((HTADDR->httc&03777) != den) 19222Sbill HTADDR->httc = den; 19322Sbill unit &= 03; 19422Sbill blkno = h_blkno[unit]; 19522Sbill if (bp == &chtbuf) { 19622Sbill if (bp->b_resid==NOP) { 19722Sbill bp->b_resid = HTADDR->htds & 0xffff; 19822Sbill goto next; 19922Sbill } 20022Sbill httab.b_active = SCOM; 20122Sbill HTADDR->htfc = 0; 20222Sbill HTADDR->htcs1 = bp->b_resid|GO; 20322Sbill return; 20422Sbill } 20522Sbill if (h_openf[unit] < 0 || dbtofsb(bp->b_blkno) > h_nxrec[unit]) 20622Sbill goto abort; 20722Sbill if (blkno == dbtofsb(bp->b_blkno)) { 20822Sbill httab.b_active = SIO; 20922Sbill HTADDR->htfc = -bp->b_bcount; 21022Sbill mbastart(bp, (int *)HTADDR); 21122Sbill } else { 21222Sbill if (blkno < dbtofsb(bp->b_blkno)) { 21322Sbill httab.b_active = SSFOR; 21422Sbill HTADDR->htfc = blkno - dbtofsb(bp->b_blkno); 21522Sbill HTADDR->htcs1 = SFORW|GO; 21622Sbill } else { 21722Sbill httab.b_active = SSREV; 21822Sbill HTADDR->htfc = dbtofsb(bp->b_blkno) - blkno; 21922Sbill HTADDR->htcs1 = SREV|GO; 22022Sbill } 22122Sbill } 22222Sbill return; 22322Sbill 22422Sbill abort: 22522Sbill bp->b_flags |= B_ERROR; 22622Sbill 22722Sbill next: 22822Sbill httab.b_actf = bp->av_forw; 22922Sbill iodone(bp); 23022Sbill goto loop; 23122Sbill } 23222Sbill 23322Sbill /*ARGSUSED*/ 23422Sbill htintr(mbastat, as) 23522Sbill { 23622Sbill register struct buf *bp; 23722Sbill register int unit, state; 23822Sbill int err; 23922Sbill 24022Sbill if ((bp = httab.b_actf)==NULL) 24122Sbill return; 24222Sbill unit = minor(bp->b_dev) & 03; 24322Sbill state = httab.b_active; 24422Sbill httab.b_active = 0; 24522Sbill if (HTADDR->htds&(ERR|EOT|TM) || mbastat & MBAEBITS) { 24622Sbill err = HTADDR->hter & 0xffff; 24722Sbill if ((mbastat & MBAEBITS) || (err&HARD)) 24822Sbill state = 0; 24922Sbill if (bp == &rhtbuf) 25022Sbill err &= ~FCE; 25122Sbill if ((bp->b_flags&B_READ) && (HTADDR->htds&PES)) 25222Sbill err &= ~(CS|COR); 25322Sbill if(HTADDR->htds&EOT || (HTADDR->htds&MOL)==0) { 25422Sbill if(h_openf[unit]) 25522Sbill h_openf[unit] = -1; 25622Sbill } 25722Sbill else if(HTADDR->htds&TM) { 25822Sbill HTADDR->htfc = 0; 25922Sbill h_nxrec[unit] = dbtofsb(bp->b_blkno); 26022Sbill state = SOK; 26122Sbill } 26222Sbill else if(state && err == 0) 26322Sbill state = SOK; 26422Sbill if(httab.b_errcnt > 4) 26522Sbill deverror(bp, HTADDR->hter, mbastat); 26622Sbill ((struct mba_regs *)MBA1)->mba_cr &= ~MBAIE; 26722Sbill HTADDR->htcs1 = DCLR|GO; 26822Sbill ((struct mba_regs *)MBA1)->mba_cr |= MBAIE; 26922Sbill if (state==SIO && ++httab.b_errcnt < 10) { 27022Sbill httab.b_active = SRETRY; 27122Sbill h_blkno[unit]++; 27222Sbill HTADDR->htfc = -1; 27322Sbill HTADDR->htcs1 = SREV|GO; 27422Sbill return; 27522Sbill } 27622Sbill if (state!=SOK) { 27722Sbill bp->b_flags |= B_ERROR; 27822Sbill state = SIO; 27922Sbill } 28022Sbill } else if (HTADDR->htcs1 < 0) { /* SC */ 28122Sbill if(HTADDR->htds & ERR) { 28222Sbill ((struct mba_regs *)MBA1)->mba_cr &= ~MBAIE; 28322Sbill HTADDR->htcs1 = DCLR|GO; 28422Sbill ((struct mba_regs *)MBA1)->mba_cr |= MBAIE; 28522Sbill } 28622Sbill } 28722Sbill switch(state) { 28822Sbill case SIO: 28922Sbill case SOK: 29022Sbill h_blkno[unit]++; 29122Sbill 29222Sbill case SCOM: 29322Sbill httab.b_errcnt = 0; 29422Sbill httab.b_actf = bp->av_forw; 29522Sbill bp->b_resid = - (HTADDR->htfc & 0xffff); 29622Sbill if (bp->b_flags & B_READ) 29722Sbill bp->b_resid += bp->b_bcount; 29822Sbill iodone(bp); 29922Sbill break; 30022Sbill 30122Sbill case SRETRY: 30222Sbill if((bp->b_flags&B_READ)==0) { 30322Sbill httab.b_active = SSFOR; 30422Sbill HTADDR->htcs1 = ERASE|GO; 30522Sbill return; 30622Sbill } 30722Sbill 30822Sbill case SSFOR: 30922Sbill case SSREV: 31022Sbill if(HTADDR->htds & TM) { 31122Sbill if(state == SSREV) { 31222Sbill h_nxrec[unit] = dbtofsb(bp->b_blkno) - (HTADDR->htfc&0xffff); 31322Sbill h_blkno[unit] = h_nxrec[unit]; 31422Sbill } else { 31522Sbill h_nxrec[unit] = dbtofsb(bp->b_blkno) + (HTADDR->htfc & 0xffff) - 1; 31622Sbill h_blkno[unit] = dbtofsb(bp->b_blkno) + (HTADDR->htfc & 0xffff); 31722Sbill } 31822Sbill } else 31922Sbill h_blkno[unit] = dbtofsb(bp->b_blkno); 32022Sbill break; 32122Sbill 32222Sbill default: 32322Sbill return; 32422Sbill } 32522Sbill htstart(); 32622Sbill } 32722Sbill 32822Sbill htread(dev) 32922Sbill { 33022Sbill htphys(dev); 33122Sbill physio(htstrategy, &rhtbuf, dev, B_READ, minphys); 33222Sbill } 33322Sbill 33422Sbill htwrite(dev) 33522Sbill { 33622Sbill htphys(dev); 33722Sbill physio(htstrategy, &rhtbuf, dev, B_WRITE, minphys); 33822Sbill } 33922Sbill 34022Sbill htphys(dev) 34122Sbill { 34222Sbill register unit; 34322Sbill daddr_t a; 34422Sbill 34522Sbill unit = minor(dev) & 03; 34622Sbill if(unit < NUNIT) { 34722Sbill a = u.u_offset >> 9; 34822Sbill h_blkno[unit] = dbtofsb(a); 34922Sbill h_nxrec[unit] = dbtofsb(a)+1; 35022Sbill } 35122Sbill } 352