1*1917Swnj /* ht.c 4.3 12/17/80 */ 222Sbill 31563Sbill #include "../conf/ht.h" 41563Sbill #if NHT > 0 522Sbill /* 622Sbill * TJU16 tape driver 722Sbill */ 822Sbill 922Sbill #include "../h/param.h" 1022Sbill #include "../h/systm.h" 1122Sbill #include "../h/buf.h" 1222Sbill #include "../h/conf.h" 1322Sbill #include "../h/dir.h" 1422Sbill #include "../h/file.h" 1522Sbill #include "../h/user.h" 1622Sbill #include "../h/map.h" 17420Sbill #include "../h/pte.h" 1822Sbill #include "../h/mba.h" 19*1917Swnj #include "../h/vm.h" 20*1917Swnj #include "../h/cmap.h" 2122Sbill 2222Sbill struct device 2322Sbill { 2422Sbill int htcs1; 2522Sbill int htds; 2622Sbill int hter; 2722Sbill int htmr; 2822Sbill int htas; 2922Sbill int htfc; 3022Sbill int htdt; 3122Sbill int htck; 3222Sbill int htsn; 3322Sbill int httc; 3422Sbill }; 3522Sbill 3622Sbill struct buf httab; 3722Sbill struct buf rhtbuf; 3822Sbill struct buf chtbuf; 3922Sbill 4022Sbill #define INF 1000000 4122Sbill 421563Sbill char h_openf[NHT]; 431563Sbill daddr_t h_blkno[NHT]; 441563Sbill char h_flags[NHT]; 451563Sbill daddr_t h_nxrec[NHT]; 4622Sbill 4722Sbill #define GO 01 4822Sbill #define WCOM 060 4922Sbill #define RCOM 070 5022Sbill #define NOP 0 5122Sbill #define WEOF 026 5222Sbill #define SFORW 030 5322Sbill #define SREV 032 5422Sbill #define ERASE 024 5522Sbill #define REW 06 5622Sbill #define DCLR 010 5722Sbill #define P800 01700 /* 800 + pdp11 mode */ 5822Sbill #define P1600 02300 /* 1600 + pdp11 mode */ 5922Sbill #define IENABLE 0100 6022Sbill #define RDY 0200 6122Sbill #define TM 04 6222Sbill #define DRY 0200 6322Sbill #define EOT 02000 6422Sbill #define CS 02000 6522Sbill #define COR 0100000 6622Sbill #define PES 040 6722Sbill #define WRL 04000 6822Sbill #define MOL 010000 6922Sbill #define ERR 040000 7022Sbill #define FCE 01000 7122Sbill #define TRE 040000 7222Sbill #define HARD 064023 /* UNS|OPI|NEF|FMT|RMR|ILR|ILF */ 7322Sbill 7422Sbill #define SIO 1 7522Sbill #define SSFOR 2 7622Sbill #define SSREV 3 7722Sbill #define SRETRY 4 7822Sbill #define SCOM 5 7922Sbill #define SOK 6 8022Sbill 8122Sbill #define H_WRITTEN 1 8222Sbill 8322Sbill htopen(dev, flag) 8422Sbill { 8522Sbill register unit, ds; 8622Sbill 87420Sbill if ((mbaact&(1<<HTMBANUM)) == 0) 88420Sbill mbainit(HTMBANUM); 8922Sbill httab.b_flags |= B_TAPE; 9022Sbill unit = minor(dev) & 03; 911563Sbill if (unit >= NHT || h_openf[unit]) { 9222Sbill u.u_error = ENXIO; 9322Sbill return; 9422Sbill } 9522Sbill h_blkno[unit] = 0; 9622Sbill h_nxrec[unit] = INF; 9722Sbill h_flags[unit] = 0; 9822Sbill ds = hcommand(dev, NOP); 9922Sbill if ((ds&MOL)==0 || (flag && (ds&WRL))) 10022Sbill u.u_error = ENXIO; 10122Sbill if (u.u_error==0) 10222Sbill h_openf[unit]++; 10322Sbill } 10422Sbill 10522Sbill htclose(dev, flag) 10622Sbill { 10722Sbill register int unit; 10822Sbill 10922Sbill unit = minor(dev) & 03; 11022Sbill if (flag == FWRITE || ((flag&FWRITE) && (h_flags[unit]&H_WRITTEN))) { 111128Sbill (void) hcommand(dev, WEOF); 112128Sbill (void) hcommand(dev, WEOF); 113128Sbill (void) hcommand(dev, SREV); 11422Sbill } 11522Sbill if((minor(dev)&4) == 0) /* no 4 -> rewind */ 116128Sbill (void) hcommand(dev, REW); 11722Sbill h_openf[unit] = 0; 11822Sbill } 11922Sbill 12022Sbill hcommand(dev, com) 12122Sbill { 12222Sbill register struct buf *bp; 12322Sbill 12422Sbill bp = &chtbuf; 125128Sbill (void) spl5(); 12622Sbill while(bp->b_flags&B_BUSY) { 12722Sbill bp->b_flags |= B_WANTED; 12822Sbill sleep((caddr_t)bp, PRIBIO); 12922Sbill } 130128Sbill (void) spl0(); 13122Sbill bp->b_dev = dev; 13222Sbill bp->b_resid = com; 13322Sbill bp->b_blkno = 0; 13422Sbill bp->b_flags = B_BUSY|B_READ; 13522Sbill htstrategy(bp); 13622Sbill iowait(bp); 13722Sbill if(bp->b_flags&B_WANTED) 13822Sbill wakeup((caddr_t)bp); 13922Sbill bp->b_flags = 0; 14022Sbill return(bp->b_resid); 14122Sbill } 14222Sbill 14322Sbill htstrategy(bp) 14422Sbill register struct buf *bp; 14522Sbill { 14622Sbill register daddr_t *p; 14722Sbill 14822Sbill if(bp != &chtbuf) { 14922Sbill p = &h_nxrec[minor(bp->b_dev)&03]; 15022Sbill if(dbtofsb(bp->b_blkno) > *p) { 15122Sbill bp->b_flags |= B_ERROR; 15222Sbill bp->b_error = ENXIO; 15322Sbill iodone(bp); 15422Sbill return; 15522Sbill } 15622Sbill if(dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) { 15722Sbill bp->b_resid = bp->b_bcount; 15822Sbill clrbuf(bp); 15922Sbill iodone(bp); 16022Sbill return; 16122Sbill } 16222Sbill if ((bp->b_flags&B_READ)==0) { 16322Sbill *p = dbtofsb(bp->b_blkno) + 1; 16422Sbill h_flags[minor(bp->b_dev)&03] |= H_WRITTEN; 16522Sbill } 16622Sbill } 16722Sbill bp->av_forw = NULL; 168128Sbill (void) spl5(); 16922Sbill if (httab.b_actf == NULL) 17022Sbill httab.b_actf = bp; 17122Sbill else 17222Sbill httab.b_actl->av_forw = bp; 17322Sbill httab.b_actl = bp; 17422Sbill if (httab.b_active==0) 17522Sbill htstart(); 176128Sbill (void) spl0(); 17722Sbill } 17822Sbill 17922Sbill htstart() 18022Sbill { 18122Sbill register struct buf *bp; 18222Sbill register unit, den; 18322Sbill daddr_t blkno; 184420Sbill register struct device *htp = mbadev(HTMBA,0); 18522Sbill 18622Sbill loop: 18722Sbill if ((bp = httab.b_actf) == NULL) 18822Sbill return; 18922Sbill unit = minor(bp->b_dev); 19022Sbill den = P800 | (unit&03); 19122Sbill if(unit >= 8) 19222Sbill den = P1600 | (unit&03); 193420Sbill if((htp->httc&03777) != den) 194420Sbill htp->httc = den; 19522Sbill unit &= 03; 19622Sbill blkno = h_blkno[unit]; 19722Sbill if (bp == &chtbuf) { 19822Sbill if (bp->b_resid==NOP) { 199420Sbill bp->b_resid = htp->htds & 0xffff; 20022Sbill goto next; 20122Sbill } 20222Sbill httab.b_active = SCOM; 203420Sbill htp->htfc = 0; 204420Sbill htp->htcs1 = bp->b_resid|GO; 20522Sbill return; 20622Sbill } 20722Sbill if (h_openf[unit] < 0 || dbtofsb(bp->b_blkno) > h_nxrec[unit]) 20822Sbill goto abort; 20922Sbill if (blkno == dbtofsb(bp->b_blkno)) { 21022Sbill httab.b_active = SIO; 211420Sbill htp->htfc = -bp->b_bcount; 212420Sbill mbastart(bp, (int *)htp); 21322Sbill } else { 21422Sbill if (blkno < dbtofsb(bp->b_blkno)) { 21522Sbill httab.b_active = SSFOR; 216420Sbill htp->htfc = blkno - dbtofsb(bp->b_blkno); 217420Sbill htp->htcs1 = SFORW|GO; 21822Sbill } else { 21922Sbill httab.b_active = SSREV; 220420Sbill htp->htfc = dbtofsb(bp->b_blkno) - blkno; 221420Sbill htp->htcs1 = SREV|GO; 22222Sbill } 22322Sbill } 22422Sbill return; 22522Sbill 22622Sbill abort: 22722Sbill bp->b_flags |= B_ERROR; 22822Sbill 22922Sbill next: 23022Sbill httab.b_actf = bp->av_forw; 23122Sbill iodone(bp); 23222Sbill goto loop; 23322Sbill } 23422Sbill 23522Sbill /*ARGSUSED*/ 23622Sbill htintr(mbastat, as) 23722Sbill { 23822Sbill register struct buf *bp; 23922Sbill register int unit, state; 24022Sbill int err; 241420Sbill register struct device *htp = mbadev(HTMBA,0); 24222Sbill 24322Sbill if ((bp = httab.b_actf)==NULL) 24422Sbill return; 24522Sbill unit = minor(bp->b_dev) & 03; 24622Sbill state = httab.b_active; 24722Sbill httab.b_active = 0; 248420Sbill if (htp->htds&(ERR|EOT|TM) || mbastat & MBAEBITS) { 249420Sbill err = htp->hter & 0xffff; 25022Sbill if ((mbastat & MBAEBITS) || (err&HARD)) 25122Sbill state = 0; 25222Sbill if (bp == &rhtbuf) 25322Sbill err &= ~FCE; 254420Sbill if ((bp->b_flags&B_READ) && (htp->htds&PES)) 25522Sbill err &= ~(CS|COR); 256420Sbill if(htp->htds&EOT || (htp->htds&MOL)==0) { 25722Sbill if(h_openf[unit]) 25822Sbill h_openf[unit] = -1; 25922Sbill } 260420Sbill else if(htp->htds&TM) { 261420Sbill htp->htfc = 0; 26222Sbill h_nxrec[unit] = dbtofsb(bp->b_blkno); 26322Sbill state = SOK; 26422Sbill } 26522Sbill else if(state && err == 0) 26622Sbill state = SOK; 26722Sbill if(httab.b_errcnt > 4) 268420Sbill deverror(bp, htp->hter, mbastat); 269420Sbill HTMBA->mba_cr &= ~MBAIE; 270420Sbill htp->htcs1 = DCLR|GO; 271420Sbill HTMBA->mba_cr |= MBAIE; 27222Sbill if (state==SIO && ++httab.b_errcnt < 10) { 27322Sbill httab.b_active = SRETRY; 27422Sbill h_blkno[unit]++; 275420Sbill htp->htfc = -1; 276420Sbill htp->htcs1 = SREV|GO; 27722Sbill return; 27822Sbill } 27922Sbill if (state!=SOK) { 28022Sbill bp->b_flags |= B_ERROR; 28122Sbill state = SIO; 28222Sbill } 283420Sbill } else if (htp->htcs1 < 0) { /* SC */ 284420Sbill if(htp->htds & ERR) { 285420Sbill HTMBA->mba_cr &= ~MBAIE; 286420Sbill htp->htcs1 = DCLR|GO; 287420Sbill HTMBA->mba_cr |= MBAIE; 28822Sbill } 28922Sbill } 29022Sbill switch(state) { 29122Sbill case SIO: 29222Sbill case SOK: 29322Sbill h_blkno[unit]++; 29422Sbill 29522Sbill case SCOM: 29622Sbill httab.b_errcnt = 0; 29722Sbill httab.b_actf = bp->av_forw; 298420Sbill bp->b_resid = - (htp->htfc & 0xffff); 29922Sbill if (bp->b_flags & B_READ) 30022Sbill bp->b_resid += bp->b_bcount; 30122Sbill iodone(bp); 30222Sbill break; 30322Sbill 30422Sbill case SRETRY: 30522Sbill if((bp->b_flags&B_READ)==0) { 30622Sbill httab.b_active = SSFOR; 307420Sbill htp->htcs1 = ERASE|GO; 30822Sbill return; 30922Sbill } 31022Sbill 31122Sbill case SSFOR: 31222Sbill case SSREV: 313220Sbill #define blk dbtofsb(bp->b_blkno) 314420Sbill if(htp->htds & TM) { 31522Sbill if(state == SSREV) { 316420Sbill h_nxrec[unit] = blk - (htp->htfc&0xffff); 31722Sbill h_blkno[unit] = h_nxrec[unit]; 31822Sbill } else { 319420Sbill h_nxrec[unit] = blk + (htp->htfc&0xffff) - 1; 320420Sbill h_blkno[unit] = blk + (htp->htfc & 0xffff); 32122Sbill } 32222Sbill } else 323220Sbill h_blkno[unit] = blk; 32422Sbill break; 325*1917Swnj #undef blk 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; 3511563Sbill if(unit < NHT) { 35222Sbill a = u.u_offset >> 9; 35322Sbill h_blkno[unit] = dbtofsb(a); 35422Sbill h_nxrec[unit] = dbtofsb(a)+1; 35522Sbill } 35622Sbill } 357*1917Swnj 358*1917Swnj #define HTADDR ((struct device *)(HTPHYSMBA + 0x400)) 359*1917Swnj #define HTMAP ((struct pte *) (HTPHYSMBA + 0x800)) 360*1917Swnj 361*1917Swnj #define DBSIZE 20 362*1917Swnj 363*1917Swnj twall(start, num) 364*1917Swnj char *start; 365*1917Swnj int num; 366*1917Swnj { 367*1917Swnj int blk; 368*1917Swnj 369*1917Swnj HTADDR->httc = P800; /* set 800 bpi mode */ 370*1917Swnj HTADDR->htcs1 = DCLR | GO; 371*1917Swnj while (num > 0) { 372*1917Swnj blk = num > DBSIZE ? DBSIZE : num; 373*1917Swnj twrite(start, blk); 374*1917Swnj start += blk*NBPG; 375*1917Swnj num -= blk; 376*1917Swnj } 377*1917Swnj } 378*1917Swnj 379*1917Swnj twrite(buf, num) 380*1917Swnj char *buf; 381*1917Swnj { 382*1917Swnj register struct pte *hpte = HTMAP; 383*1917Swnj register int i; 384*1917Swnj 385*1917Swnj twait(); 386*1917Swnj HTADDR->htfc = -(num*NBPG); 387*1917Swnj for (i = 0; i < num; i++) 388*1917Swnj *(int *)hpte++ = (btop(buf)+i) | PG_V; 389*1917Swnj ((struct mba_regs *)PHYSMBA1)->mba_sr = -1; 390*1917Swnj ((struct mba_regs *)PHYSMBA1)->mba_bcr = -(num*NBPG); 391*1917Swnj ((struct mba_regs *)PHYSMBA1)->mba_var = 0; 392*1917Swnj HTADDR->htcs1 = WCOM | GO; 393*1917Swnj } 394*1917Swnj 395*1917Swnj twait() 396*1917Swnj { 397*1917Swnj register s; 398*1917Swnj 399*1917Swnj do 400*1917Swnj s = HTADDR->htds; 401*1917Swnj while ((s & RDY) == 0); 402*1917Swnj } 403*1917Swnj 404*1917Swnj rewind() 405*1917Swnj { 406*1917Swnj 407*1917Swnj twait(); 408*1917Swnj HTADDR->htcs1 = REW | GO; 409*1917Swnj } 410*1917Swnj 411*1917Swnj teof() 412*1917Swnj { 413*1917Swnj 414*1917Swnj twait(); 415*1917Swnj HTADDR->htcs1 = WEOF | GO; 416*1917Swnj } 4171563Sbill #endif 418