1 /* tm.c 4.11 02/16/81 */ 2 3 #include "tm.h" 4 #if NTM > 0 5 /* 6 * TM tape driver 7 */ 8 #define DELAY(N) { register int d; d = N; while (--d > 0); } 9 #include "../h/param.h" 10 #include "../h/buf.h" 11 #include "../h/dir.h" 12 #include "../h/conf.h" 13 #include "../h/user.h" 14 #include "../h/file.h" 15 #include "../h/map.h" 16 #include "../h/pte.h" 17 #include "../h/uba.h" 18 #include "../h/mtio.h" 19 #include "../h/ioctl.h" 20 #include "../h/vm.h" 21 #include "../h/cmap.h" 22 #include "../h/cpu.h" 23 24 #include "../h/tmreg.h" 25 26 struct buf ctmbuf; 27 struct buf rtmbuf; 28 29 int tmcntrlr(), tmslave(), tmdgo(), tmintr(); 30 struct uba_dinfo *tmdinfo[NTM]; 31 struct uba_minfo *tmminfo[NTM]; 32 u_short tmstd[] = { 0772520, 0 }; 33 struct uba_driver tmdriver = 34 { tmcntrlr, tmslave, tmdgo, 0, tmstd, "tm", tmdinfo, tmminfo }; 35 int tm_ubinfo; 36 37 /* bits in minor device */ 38 #define T_NOREWIND 04 39 #define T_1600BPI 08 40 41 #define INF (daddr_t)1000000L 42 43 /* 44 * Really only handle one tape drive... if you have more than one, 45 * you can put all these (and some of the above) in a structure, 46 * change the obvious things, and make tmslave smarter, but 47 * it is not clear what happens when some drives are transferring while 48 * others rewind, so we don't pretend that this driver handles multiple 49 * tape drives. 50 */ 51 char t_openf; 52 daddr_t t_blkno; 53 char t_flags; 54 daddr_t t_nxrec; 55 u_short t_erreg; 56 u_short t_dsreg; 57 short t_resid; 58 59 #define SSEEK 1 /* seeking */ 60 #define SIO 2 /* doing seq i/o */ 61 #define SCOM 3 /* sending control command */ 62 63 #define LASTIOW 1 /* last op was a write */ 64 #define WAITREW 2 /* someone is waiting for a rewind */ 65 66 /* 67 * Determine if there is a controller for 68 * a tm at address reg. Our goal is to make the 69 * device interrupt. 70 */ 71 tmcntrlr(um, reg) 72 struct uba_minfo *um; 73 caddr_t reg; 74 { 75 register int br, cvec; 76 77 ((struct device *)reg)->tmcs = IENABLE; 78 /* 79 * If this is a tm03/tc11, it ought to have interrupted 80 * by now, if it isn't (ie: it is a ts04) then we just 81 * hope that it didn't interrupt, so autoconf will ignore it. 82 * Just in case, we will reference one 83 * of the more distant registers, and hope for a machine 84 * check, or similar disaster if this is a ts. 85 */ 86 if (badaddr(&((struct device *)reg)->tmrd, 2)) 87 return (0); 88 return (1); 89 } 90 91 tmslave(ui, reg, slaveno) 92 struct uba_dinfo *ui; 93 caddr_t reg; 94 { 95 96 /* 97 * Due to a design flaw, we cannot ascertain if the tape 98 * exists or not unless it is on line - ie: unless a tape is 99 * mounted. This is too servere a restriction to bear. 100 * As we can only handle one tape, we might just as well insist 101 * that it be slave #0, and just assume that it exists. 102 * Something better will have to be done if you have two 103 * tapes on one controller, or two controllers 104 */ 105 if (slaveno != 0 || tmdinfo[0]) 106 return(0); 107 return (1); 108 } 109 110 tmopen(dev, flag) 111 dev_t dev; 112 int flag; 113 { 114 register ds, unit; 115 register struct uba_dinfo *ui; 116 117 tmminfo[0]->um_tab.b_flags |= B_TAPE; 118 unit = minor(dev)&03; 119 if (unit>=NTM || t_openf || !(ui = tmdinfo[minor(dev)&03])->ui_alive) { 120 u.u_error = ENXIO; /* out of range or open */ 121 return; 122 } 123 tcommand(dev, NOP, 1); 124 if ((t_erreg&SELR) == 0) { 125 u.u_error = EIO; /* offline */ 126 return; 127 } 128 t_openf = 1; 129 if (t_erreg&RWS) 130 tmwaitrws(dev); /* wait for rewind complete */ 131 while (t_erreg&SDWN) 132 tcommand(dev, NOP, 1); /* await settle down */ 133 if ((t_erreg&TUR)==0 || 134 ((flag&(FREAD|FWRITE)) == FWRITE && (t_erreg&WRL))) { 135 ((struct device *)ui->ui_addr)->tmcs = DCLR|GO; 136 u.u_error = EIO; /* offline or write protect */ 137 } 138 if (u.u_error != 0) { 139 t_openf = 0; 140 return; 141 } 142 t_blkno = (daddr_t)0; 143 t_nxrec = INF; 144 t_flags = 0; 145 t_openf = 1; 146 } 147 148 tmwaitrws(dev) 149 register dev; 150 { 151 register struct device *addr = 152 (struct device *)tmdinfo[minor(dev)&03]->ui_addr; 153 154 spl5(); 155 for (;;) { 156 if ((addr->tmer&RWS) == 0) { 157 spl0(); /* rewind complete */ 158 return; 159 } 160 t_flags |= WAITREW; 161 sleep((caddr_t)&t_flags, PRIBIO); 162 } 163 } 164 165 tmclose(dev, flag) 166 register dev_t dev; 167 register flag; 168 { 169 170 if (flag == FWRITE || ((flag&FWRITE) && (t_flags&LASTIOW))) { 171 tcommand(dev, WEOF, 1); 172 tcommand(dev, WEOF, 1); 173 tcommand(dev, SREV, 1); 174 } 175 if ((minor(dev)&T_NOREWIND) == 0) 176 tcommand(dev, REW, 1); 177 t_openf = 0; 178 } 179 180 tcommand(dev, com, count) 181 dev_t dev; 182 int com, count; 183 { 184 register struct buf *bp; 185 186 bp = &ctmbuf; 187 (void) spl5(); 188 while (bp->b_flags&B_BUSY) { 189 bp->b_flags |= B_WANTED; 190 sleep((caddr_t)bp, PRIBIO); 191 } 192 bp->b_flags = B_BUSY|B_READ; 193 (void) spl0(); 194 bp->b_dev = dev; 195 bp->b_repcnt = -count; 196 bp->b_command = com; 197 bp->b_blkno = 0; 198 tmstrategy(bp); 199 iowait(bp); 200 if (bp->b_flags&B_WANTED) 201 wakeup((caddr_t)bp); 202 bp->b_flags &= B_ERROR; 203 } 204 205 tmstrategy(bp) 206 register struct buf *bp; 207 { 208 register daddr_t *p; 209 register struct buf *tmi; 210 211 tmwaitrws(bp->b_dev); 212 if (bp != &ctmbuf) { 213 p = &t_nxrec; 214 if (dbtofsb(bp->b_blkno) > *p) { 215 bp->b_flags |= B_ERROR; 216 bp->b_error = ENXIO; /* past EOF */ 217 iodone(bp); 218 return; 219 } else if (dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) { 220 bp->b_resid = bp->b_bcount; 221 clrbuf(bp); /* at EOF */ 222 iodone(bp); 223 return; 224 } else if ((bp->b_flags&B_READ) == 0) 225 *p = dbtofsb(bp->b_blkno) + 1; /* write sets EOF */ 226 } 227 bp->av_forw = NULL; 228 (void) spl5(); 229 tmi = &tmminfo[0]->um_tab; 230 if (tmi->b_actf == NULL) 231 tmi->b_actf = bp; 232 else 233 tmi->b_actl->av_forw = bp; 234 tmi->b_actl = bp; 235 if (tmi->b_active == 0) 236 tmstart(); 237 (void) spl0(); 238 } 239 240 tmstart() 241 { 242 register struct buf *bp; 243 register struct uba_dinfo *ui; 244 register struct device *addr; 245 register cmd; 246 register daddr_t blkno; 247 int s; 248 249 loop: 250 if ((bp = tmminfo[0]->um_tab.b_actf) == 0) 251 return; 252 ui = tmdinfo[minor(bp->b_dev)&03]; 253 addr = (struct device *)ui->ui_addr; 254 t_dsreg = addr->tmcs; 255 t_erreg = addr->tmer; 256 t_resid = addr->tmbc; 257 t_flags &= ~LASTIOW; 258 if (t_openf < 0 || (addr->tmcs&CUR) == 0) { 259 /* t_openf = -1; ??? */ 260 bp->b_flags |= B_ERROR; /* hard error'ed or !SELR */ 261 goto next; 262 } 263 cmd = IENABLE | GO; 264 if ((minor(bp->b_dev) & T_1600BPI) == 0) 265 cmd |= D800; 266 if (bp == &ctmbuf) { 267 if (bp->b_command == NOP) 268 goto next; /* just get status */ 269 else { 270 cmd |= bp->b_command; 271 tmminfo[0]->um_tab.b_active = SCOM; 272 if (bp->b_command == SFORW || bp->b_command == SREV) 273 addr->tmbc = bp->b_repcnt; 274 addr->tmcs = cmd; 275 return; 276 } 277 } 278 if ((blkno = t_blkno) == dbtofsb(bp->b_blkno)) { 279 addr->tmbc = -bp->b_bcount; 280 s = spl6(); 281 if (tm_ubinfo == 0) 282 tm_ubinfo = ubasetup(ui->ui_ubanum, bp, 1); 283 splx(s); 284 if ((bp->b_flags&B_READ) == 0) { 285 if (tmminfo[0]->um_tab.b_errcnt) 286 cmd |= WIRG; 287 else 288 cmd |= WCOM; 289 } else 290 cmd |= RCOM; 291 cmd |= (tm_ubinfo >> 12) & 0x30; 292 tmminfo[0]->um_tab.b_active = SIO; 293 addr->tmba = tm_ubinfo; 294 addr->tmcs = cmd; 295 return; 296 } 297 tmminfo[0]->um_tab.b_active = SSEEK; 298 if (blkno < dbtofsb(bp->b_blkno)) { 299 cmd |= SFORW; 300 addr->tmbc = blkno - dbtofsb(bp->b_blkno); 301 } else { 302 cmd |= SREV; 303 addr->tmbc = dbtofsb(bp->b_blkno) - blkno; 304 } 305 addr->tmcs = cmd; 306 return; 307 308 next: 309 ubarelse(ui->ui_ubanum, &tm_ubinfo); 310 tmminfo[0]->um_tab.b_actf = bp->av_forw; 311 iodone(bp); 312 goto loop; 313 } 314 315 tmdgo() 316 { 317 } 318 319 tmintr(d) 320 { 321 register struct buf *bp; 322 register struct device *addr = (struct device *)tmdinfo[d]->ui_addr; 323 register state; 324 325 if (t_flags&WAITREW && (addr->tmer&RWS) == 0) { 326 t_flags &= ~WAITREW; 327 wakeup((caddr_t)&t_flags); 328 } 329 if ((bp = tmminfo[0]->um_tab.b_actf) == NULL) 330 return; 331 t_dsreg = addr->tmcs; 332 t_erreg = addr->tmer; 333 t_resid = addr->tmbc; 334 if ((bp->b_flags & B_READ) == 0) 335 t_flags |= LASTIOW; 336 state = tmminfo[0]->um_tab.b_active; 337 tmminfo[0]->um_tab.b_active = 0; 338 if (addr->tmcs&ERROR) { 339 while(addr->tmer & SDWN) 340 ; /* await settle down */ 341 if (addr->tmer&EOF) { 342 tmseteof(bp); /* set blkno and nxrec */ 343 state = SCOM; 344 addr->tmbc = -bp->b_bcount; 345 goto errout; 346 } 347 if ((bp->b_flags&B_READ) && (addr->tmer&(HARD|SOFT)) == RLE) 348 goto out; 349 if ((addr->tmer&HARD)==0 && state==SIO) { 350 if (++tmminfo[0]->um_tab.b_errcnt < 7) { 351 if((addr->tmer&SOFT) == NXM) 352 printf("TM UBA late error\n"); 353 t_blkno++; 354 ubarelse(tmdinfo[d]->ui_ubanum, &tm_ubinfo); 355 tmstart(); 356 return; 357 } 358 } else if (t_openf>0 && bp != &rtmbuf) 359 t_openf = -1; 360 deverror(bp, t_erreg, t_dsreg); 361 bp->b_flags |= B_ERROR; 362 state = SIO; 363 } 364 out: 365 switch (state) { 366 367 case SIO: 368 t_blkno++; 369 /* fall into ... */ 370 371 case SCOM: 372 if (bp == &ctmbuf) { 373 switch (bp->b_command) { 374 case SFORW: 375 t_blkno -= bp->b_repcnt; 376 break; 377 378 case SREV: 379 t_blkno += bp->b_repcnt; 380 break; 381 382 default: 383 if (++bp->b_repcnt < 0) { 384 tmstart(); /* continue */ 385 return; 386 } 387 } 388 } 389 errout: 390 tmminfo[0]->um_tab.b_errcnt = 0; 391 tmminfo[0]->um_tab.b_actf = bp->av_forw; 392 bp->b_resid = -addr->tmbc; 393 ubarelse(tmdinfo[d]->ui_ubanum, &tm_ubinfo); 394 iodone(bp); 395 break; 396 397 case SSEEK: 398 t_blkno = dbtofsb(bp->b_blkno); 399 break; 400 401 default: 402 return; 403 } 404 tmstart(); 405 } 406 407 tmseteof(bp) 408 register struct buf *bp; 409 { 410 register struct device *addr = 411 (struct device *)tmdinfo[minor(bp->b_dev)&03]->ui_addr; 412 413 if (bp == &ctmbuf) { 414 if (t_blkno > dbtofsb(bp->b_blkno)) { 415 /* reversing */ 416 t_nxrec = dbtofsb(bp->b_blkno) - addr->tmbc; 417 t_blkno = t_nxrec; 418 } else { 419 /* spacing forward */ 420 t_blkno = dbtofsb(bp->b_blkno) + addr->tmbc; 421 t_nxrec = t_blkno - 1; 422 } 423 return; 424 } 425 /* eof on read */ 426 t_nxrec = dbtofsb(bp->b_blkno); 427 } 428 429 tmread(dev) 430 { 431 432 tmphys(dev); 433 physio(tmstrategy, &rtmbuf, dev, B_READ, minphys); 434 } 435 436 tmwrite(dev) 437 { 438 439 tmphys(dev); 440 physio(tmstrategy, &rtmbuf, dev, B_WRITE, minphys); 441 } 442 443 tmphys(dev) 444 { 445 register daddr_t a; 446 447 a = dbtofsb(u.u_offset >> 9); 448 t_blkno = a; 449 t_nxrec = a + 1; 450 } 451 452 /*ARGSUSED*/ 453 tmioctl(dev, cmd, addr, flag) 454 caddr_t addr; 455 dev_t dev; 456 { 457 register callcount; 458 int fcount; 459 struct mtop mtop; 460 struct mtget mtget; 461 /* we depend of the values and order of the MT codes here */ 462 static tmops[] = {WEOF, SFORW, SREV, SFORW, SREV, REW, OFFL, NOP}; 463 464 switch(cmd) { 465 case MTIOCTOP: /* tape operation */ 466 if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 467 u.u_error = EFAULT; 468 return; 469 } 470 switch(mtop.mt_op) { 471 case MTWEOF: case MTFSF: case MTBSF: 472 callcount = mtop.mt_count; 473 fcount = INF; 474 break; 475 case MTFSR: case MTBSR: 476 callcount = 1; 477 fcount = mtop.mt_count; 478 break; 479 case MTREW: case MTOFFL: case MTNOP: 480 callcount = 1; 481 fcount = 1; 482 break; 483 default: 484 u.u_error = ENXIO; 485 return; 486 } 487 if (callcount <= 0 || fcount <= 0) 488 u.u_error = ENXIO; 489 else while (--callcount >= 0) { 490 tcommand(dev, tmops[mtop.mt_op], fcount); 491 if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 492 ctmbuf.b_resid) { 493 u.u_error = EIO; 494 break; 495 } 496 if ((ctmbuf.b_flags&B_ERROR) || t_erreg&BOT) 497 break; 498 } 499 geterror(&ctmbuf); 500 return; 501 case MTIOCGET: 502 mtget.mt_dsreg = t_dsreg; 503 mtget.mt_erreg = t_erreg; 504 mtget.mt_resid = t_resid; 505 if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 506 u.u_error = EFAULT; 507 return; 508 default: 509 u.u_error = ENXIO; 510 } 511 } 512 513 #define DBSIZE 20 514 515 tmdump() 516 { 517 register struct uba_dinfo *ui; 518 register struct uba_regs *up; 519 register struct device *addr; 520 int blk, num; 521 int start; 522 523 start = 0; 524 num = maxfree; 525 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 526 if (tmdinfo[0] == 0) { 527 printf("dna\n"); 528 return (-1); 529 } 530 ui = phys(tmdinfo[0], struct uba_dinfo *); 531 up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; 532 #if VAX780 533 if (cpu == VAX_780) 534 ubainit(up); 535 #endif 536 DELAY(1000000); 537 addr = (struct device *)ui->ui_physaddr; 538 tmwait(addr); 539 addr->tmcs = DCLR | GO; 540 while (num > 0) { 541 blk = num > DBSIZE ? DBSIZE : num; 542 tmdwrite(start, blk, addr, up); 543 start += blk; 544 num -= blk; 545 } 546 tmwait(addr); 547 tmeof(addr); 548 tmeof(addr); 549 tmrewind(addr); 550 tmwait(addr); 551 return (0); 552 } 553 554 tmdwrite(buf, num, addr, up) 555 register buf, num; 556 register struct device *addr; 557 struct uba_regs *up; 558 { 559 register struct pte *io; 560 register int npf; 561 562 tmwait(addr); 563 io = up->uba_map; 564 npf = num+1; 565 while (--npf != 0) 566 *(int *)io++ = (buf++ | (1<<UBA_DPSHIFT) | UBA_MRV); 567 *(int *)io = 0; 568 addr->tmbc = -(num*NBPG); 569 addr->tmba = 0; 570 addr->tmcs = WCOM | GO; 571 } 572 573 tmwait(addr) 574 register struct device *addr; 575 { 576 register s; 577 578 do 579 s = addr->tmcs; 580 while ((s & CUR) == 0); 581 } 582 583 tmrewind(addr) 584 struct device *addr; 585 { 586 587 tmwait(addr); 588 addr->tmcs = REW | GO; 589 } 590 591 tmeof(addr) 592 struct device *addr; 593 { 594 595 tmwait(addr); 596 addr->tmcs = WEOF | GO; 597 } 598 #endif 599