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