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