1 /* cy.c 1.5 86/01/26 */ 2 3 #include "yc.h" 4 #if NCY > 0 5 /* 6 * Cipher Tapemaster driver. 7 */ 8 int cydebug = 0; 9 #define dlog if (cydebug) log 10 11 #include "../tahoe/mtpr.h" 12 #include "../tahoe/pte.h" 13 14 #include "param.h" 15 #include "systm.h" 16 #include "vm.h" 17 #include "buf.h" 18 #include "file.h" 19 #include "dir.h" 20 #include "user.h" 21 #include "proc.h" 22 #include "signal.h" 23 #include "uio.h" 24 #include "ioctl.h" 25 #include "mtio.h" 26 #include "errno.h" 27 #include "cmap.h" 28 #include "kernel.h" 29 #include "syslog.h" 30 31 #include "../tahoevba/vbavar.h" 32 #define CYERROR 33 #include "../tahoevba/cyreg.h" 34 35 /* 36 * There is a ccybuf per tape controller. 37 * It is used as the token to pass to the internal routines 38 * to execute tape ioctls, and also acts as a lock on the slaves 39 * on the controller, since there is only one per controller. 40 * In particular, when the tape is rewinding on close we release 41 * the user process but any further attempts to use the tape drive 42 * before the rewind completes will hang waiting for ccybuf. 43 */ 44 struct buf ccybuf[NCY]; 45 46 /* 47 * Raw tape operations use rcybuf. The driver notices when 48 * rcybuf is being used and allows the user program to contine 49 * after errors and read records not of the standard length. 50 */ 51 struct buf rcybuf[NCY]; 52 53 int cyprobe(), cyslave(), cyattach(); 54 struct buf ycutab[NYC]; 55 short yctocy[NYC]; 56 struct vba_ctlr *cyminfo[NCY]; 57 struct vba_device *ycdinfo[NYC]; 58 long cystd[] = { 0 }; 59 struct vba_driver cydriver = 60 { cyprobe, cyslave, cyattach, 0, cystd, "yc", ycdinfo, "cy", cyminfo }; 61 62 /* bits in minor device */ 63 #define YCUNIT(dev) (minor(dev)&03) 64 #define CYUNIT(dev) (yctocy[YCUNIT(dev)]) 65 #define T_NOREWIND 0x04 66 #define T_1600BPI 0x08 67 #define T_3200BPI 0x10 68 69 #define INF 1000000L /* close to infinity */ 70 #define CYMAXIO (32*NBPG) /* max i/o size */ 71 72 /* 73 * Software state and shared command areas per controller. 74 * 75 * The i/o buffer must be defined statically to insure 76 * it's address will fit in 20-bits (YECH!!!!!!!!!!!!!!) 77 */ 78 struct cy_softc { 79 struct pte *cy_map; /* pte's for mapped buffer i/o */ 80 caddr_t cy_utl; /* mapped virtual address */ 81 int cy_bs; /* controller's buffer size */ 82 char cy_buf[CYMAXIO];/* intermediate buffer */ 83 struct cyscp *cy_scp; /* system configuration block address */ 84 struct cyccb cy_ccb; /* channel control block */ 85 struct cyscb cy_scb; /* system configuration block */ 86 struct cytpb cy_tpb; /* tape parameter block */ 87 struct cytpb cy_nop; /* nop parameter block for cyintr */ 88 } cy_softc[NCY]; 89 90 /* 91 * Software state per tape transport. 92 */ 93 struct yc_softc { 94 char yc_openf; /* lock against multiple opens */ 95 char yc_lastiow; /* last operation was a write */ 96 short yc_tact; /* timeout is active */ 97 long yc_timo; /* time until timeout expires */ 98 u_short yc_control; /* copy of last tpcb.tpcontrol */ 99 u_short yc_status; /* copy of last tpcb.tpstatus */ 100 u_short yc_resid; /* copy of last bc */ 101 u_short yc_dens; /* prototype control word with density info */ 102 struct tty *yc_ttyp; /* user's tty for errors */ 103 daddr_t yc_blkno; /* block number, for block device tape */ 104 daddr_t yc_nxrec; /* position of end of tape, if known */ 105 } yc_softc[NYC]; 106 107 /* 108 * States for vm->um_tab.b_active, the per controller state flag. 109 * This is used to sequence control in the driver. 110 */ 111 #define SSEEK 1 /* seeking */ 112 #define SIO 2 /* doing seq i/o */ 113 #define SCOM 3 /* sending control command */ 114 #define SREW 4 /* sending a rewind */ 115 #define SERASE 5 /* erase inter-record gap */ 116 #define SERASED 6 /* erased inter-record gap */ 117 118 /* there's no way to figure these out dynamically? -- yech */ 119 struct cyscp *cyscp[] = 120 { (struct cyscp *)0xc0000c06, (struct cyscp *)0xc0000c16 }; 121 #define NCYSCP (sizeof (cyscp) / sizeof (cyscp[0])) 122 123 cyprobe(reg, vm) 124 caddr_t reg; 125 struct vba_ctlr *vm; 126 { 127 register br, cvec; /* must be r12, r11 */ 128 struct cy_softc *cy; 129 130 if (badcyaddr(reg+1)) 131 return (0); 132 if (vm->um_ctlr > NCYSCP || cyscp[vm->um_ctlr] == 0) /* XXX */ 133 return (0); /* XXX */ 134 cy_softc[vm->um_ctlr].cy_scp = cyscp[vm->um_ctlr]; /* XXX */ 135 /* 136 * Tapemaster controller must have interrupt handler 137 * disable interrupt, so we'll just kludge things 138 * (stupid multibus non-vectored interrupt crud). 139 */ 140 br = 0x13, cvec = 0x80; /* XXX */ 141 return (sizeof (struct cyccb)); 142 } 143 144 /* 145 * Check to see if a drive is attached to a controller. 146 * Since we can only tell that a drive is there if a tape is loaded and 147 * the drive is placed online, we always indicate the slave is present. 148 */ 149 cyslave(vi, addr) 150 struct vba_device *vi; 151 caddr_t addr; 152 { 153 154 #ifdef lint 155 vi = vi; addr = addr; 156 #endif 157 return (1); 158 } 159 160 cyattach(vi) 161 struct vba_device *vi; 162 { 163 register struct cy_softc *cy; 164 int ctlr = vi->ui_mi->um_ctlr; 165 166 yctocy[vi->ui_unit] = ctlr; 167 cy = &cy_softc[ctlr]; 168 if (cy->cy_bs == 0 && cyinit(ctlr)) { 169 uncache(&cy->cy_tpb.tpcount); 170 cy->cy_bs = htoms(cy->cy_tpb.tpcount); 171 printf("cy%d: %dkb buffer\n", ctlr, cy->cy_bs/1024); 172 /* 173 * Setup nop parameter block for clearing interrupts. 174 */ 175 cy->cy_nop.tpcmd = CY_NOP; 176 cy->cy_nop.tpcontrol = 0; 177 /* 178 * Allocate page tables. 179 */ 180 vbmapalloc(btoc(CYMAXIO)+1, &cy->cy_map, &cy->cy_utl); 181 } 182 } 183 184 /* 185 * Initialize the controller after a controller reset or 186 * during autoconfigure. All of the system control blocks 187 * are initialized and the controller is asked to configure 188 * itself for later use. 189 */ 190 cyinit(ctlr) 191 int ctlr; 192 { 193 register struct cy_softc *cy = &cy_softc[ctlr]; 194 register caddr_t addr = cyminfo[ctlr]->um_addr; 195 register int *pte; 196 197 /* 198 * Initialize the system configuration pointer. 199 */ 200 /* make kernel writable */ 201 pte = (int *)vtopte((struct proc *)0, btop(cy->cy_scp)); 202 *pte &= ~PG_PROT; *pte |= PG_KW; 203 mtpr(TBIS, cy->cy_scp); 204 /* load the correct values in the scp */ 205 cy->cy_scp->csp_buswidth = CSP_16BITS; 206 cyldmba(cy->cy_scp->csp_scb, (caddr_t)&cy->cy_scb); 207 /* put it back to read-only */ 208 *pte &= ~PG_PROT; *pte |= PG_KR; 209 mtpr(TBIS, cy->cy_scp); 210 211 /* 212 * Init system configuration block. 213 */ 214 cy->cy_scb.csb_fixed = 0x3; 215 /* set pointer to the channel control block */ 216 cyldmba(cy->cy_scb.csb_ccb, (caddr_t)&cy->cy_ccb); 217 218 /* 219 * Initialize the chanel control block. 220 */ 221 cy->cy_ccb.cbcw = CBCW_CLRINT; 222 cy->cy_ccb.cbgate = GATE_OPEN; 223 /* set pointer to the tape parameter block */ 224 cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_tpb); 225 226 /* 227 * Issue a nop cmd and get the internal buffer size for buffered i/o. 228 */ 229 cy->cy_tpb.tpcmd = CY_NOP; 230 cy->cy_tpb.tpcontrol = CYCW_16BITS; 231 cy->cy_ccb.cbgate = GATE_CLOSED; 232 CY_GO(addr); 233 if (cywait(&cy->cy_ccb) || (cy->cy_tpb.tpstatus&CYS_ERR)) { 234 uncache(&cy->cy_tpb.tpstatus); 235 printf("cy%d: timeout or err during init, status=%b\n", ctlr, 236 cy->cy_tpb.tpstatus, CYS_BITS); 237 return (0); 238 } 239 cy->cy_tpb.tpcmd = CY_CONFIG; 240 cy->cy_tpb.tpcontrol = CYCW_16BITS; 241 cy->cy_ccb.cbgate = GATE_CLOSED; 242 CY_GO(addr); 243 if (cywait(&cy->cy_ccb) || (cy->cy_tpb.tpstatus&CYS_ERR)) { 244 uncache(&cy->cy_tpb.tpstatus); 245 printf("cy%d: configuration failure, status=%b\n", ctlr, 246 cy->cy_tpb.tpstatus, CYS_BITS); 247 return (0); 248 } 249 return (1); 250 } 251 252 int cytimer(); 253 /* 254 * Open the device. Tapes are unique open 255 * devices, so we refuse if it is already open. 256 * We also check that a tape is available, and 257 * don't block waiting here; if you want to wait 258 * for a tape you should timeout in user code. 259 */ 260 cyopen(dev, flag) 261 dev_t dev; 262 register int flag; 263 { 264 register int ycunit; 265 register struct vba_device *vi; 266 register struct yc_softc *yc; 267 int s; 268 269 ycunit = YCUNIT(dev); 270 if (ycunit >= NYC || (vi = ycdinfo[ycunit]) == 0 || vi->ui_alive == 0) 271 return (ENXIO); 272 if ((yc = &yc_softc[ycunit])->yc_openf) 273 return (EBUSY); 274 #define PACKUNIT(vi) \ 275 (((vi->ui_slave&1)<<11)|((vi->ui_slave&2)<<9)|((vi->ui_slave&4)>>2)) 276 /* no way to select density */ 277 yc->yc_dens = PACKUNIT(vi)|CYCW_IE|CYCW_16BITS; 278 cycommand(dev, CY_SENSE, 1); 279 if ((yc->yc_status&CYS_OL) == 0) { /* not on-line */ 280 uprintf("yc%d: not online\n", ycunit); 281 return (ENXIO); 282 } 283 if ((flag&FWRITE) && (yc->yc_status&CYS_WP)) { 284 uprintf("yc%d: no write ring\n", ycunit); 285 return (ENXIO); 286 } 287 yc->yc_openf = 1; 288 yc->yc_blkno = (daddr_t)0; 289 yc->yc_nxrec = INF; 290 yc->yc_lastiow = 0; 291 yc->yc_ttyp = u.u_ttyp; 292 s = splclock(); 293 if (yc->yc_tact == 0) { 294 yc->yc_timo = INF; 295 yc->yc_tact = 1; 296 timeout(cytimer, (caddr_t)dev, 5*hz); 297 } 298 splx(s); 299 return (0); 300 } 301 302 /* 303 * Close tape device. 304 * 305 * If tape was open for writing or last operation was a write, 306 * then write two EOF's and backspace over the last one. 307 * Unless this is a non-rewinding special file, rewind the tape. 308 * Make the tape available to others. 309 */ 310 cyclose(dev, flag) 311 dev_t dev; 312 register int flag; 313 { 314 register struct yc_softc *yc = &yc_softc[YCUNIT(dev)]; 315 316 if (flag == FWRITE || (flag&FWRITE) && yc->yc_lastiow) { 317 cycommand(dev, CY_WEOF, 2); 318 cycommand(dev, CY_SREV, 1); 319 } 320 if ((minor(dev)&T_NOREWIND) == 0) 321 /* 322 * 0 count means don't hang waiting for rewind complete 323 * rather ccybuf stays busy until the operation completes 324 * preventing further opens from completing by preventing 325 * a CY_SENSE from completing. 326 */ 327 cycommand(dev, CY_REW, 0); 328 yc->yc_openf = 0; 329 } 330 331 /* 332 * Execute a command on the tape drive a specified number of times. 333 */ 334 cycommand(dev, com, count) 335 dev_t dev; 336 int com, count; 337 { 338 register int unit = CYUNIT(dev); 339 register struct buf *bp; 340 int s; 341 342 bp = &ccybuf[CYUNIT(dev)]; 343 s = spl3(); 344 dlog(LOG_INFO, "cycommand(%o, %x, %d), b_flags %x\n", 345 dev, com, count, bp->b_flags); 346 while (bp->b_flags&B_BUSY) { 347 /* 348 * This special check is because B_BUSY never 349 * gets cleared in the non-waiting rewind case. 350 */ 351 if (bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 352 break; 353 bp->b_flags |= B_WANTED; 354 sleep((caddr_t)bp, PRIBIO); 355 } 356 bp->b_flags = B_BUSY|B_READ; 357 splx(s); 358 bp->b_dev = dev; 359 bp->b_repcnt = count; 360 bp->b_command = com; 361 bp->b_blkno = 0; 362 cystrategy(bp); 363 /* 364 * In case of rewind from close; don't wait. 365 * This is the only case where count can be 0. 366 */ 367 if (count == 0) 368 return; 369 iowait(bp); 370 if (bp->b_flags&B_WANTED) 371 wakeup((caddr_t)bp); 372 bp->b_flags &= B_ERROR; 373 } 374 375 cystrategy(bp) 376 register struct buf *bp; 377 { 378 int ycunit = YCUNIT(bp->b_dev); 379 register struct vba_ctlr *vm; 380 register struct buf *dp; 381 int s; 382 383 /* 384 * Put transfer at end of unit queue. 385 */ 386 dlog(LOG_INFO, "cystrategy(%o, %x)\n", bp->b_dev, bp->b_command); 387 dp = &ycutab[ycunit]; 388 bp->av_forw = NULL; 389 vm = ycdinfo[ycunit]->ui_mi; 390 /* BEGIN GROT */ 391 if (bp == &rcybuf[CYUNIT(bp->b_dev)]) { 392 if (bp->b_bcount > CYMAXIO) { 393 uprintf("cy%d: i/o size too large\n", vm->um_ctlr); 394 bp->b_error = EIO; 395 bp->b_resid = bp->b_bcount; 396 bp->b_flags |= B_ERROR; 397 iodone(bp); 398 return; 399 } 400 vbasetup(bp, CYMAXIO); 401 } 402 /* END GROT */ 403 s = spl3(); 404 if (dp->b_actf == NULL) { 405 dp->b_actf = bp; 406 /* 407 * Transport not already active... 408 * put at end of controller queue. 409 */ 410 dp->b_forw = NULL; 411 if (vm->um_tab.b_actf == NULL) 412 vm->um_tab.b_actf = dp; 413 else 414 vm->um_tab.b_actl->b_forw = dp; 415 } else 416 dp->b_actl->av_forw = bp; 417 dp->b_actl = bp; 418 /* 419 * If the controller is not busy, get it going. 420 */ 421 if (vm->um_tab.b_active == 0) 422 cystart(vm); 423 splx(s); 424 } 425 426 /* 427 * Start activity on a cy controller. 428 */ 429 cystart(vm) 430 register struct vba_ctlr *vm; 431 { 432 register struct buf *bp, *dp; 433 register struct yc_softc *yc; 434 register struct cy_softc *cy; 435 register struct vba_device *vi; 436 int ycunit; 437 daddr_t blkno; 438 439 dlog(LOG_INFO, "cystart()\n"); 440 /* 441 * Look for an idle transport on the controller. 442 */ 443 loop: 444 if ((dp = vm->um_tab.b_actf) == NULL) 445 return; 446 if ((bp = dp->b_actf) == NULL) { 447 vm->um_tab.b_actf = dp->b_forw; 448 goto loop; 449 } 450 ycunit = YCUNIT(bp->b_dev); 451 yc = &yc_softc[ycunit]; 452 cy = &cy_softc[CYUNIT(bp->b_dev)]; 453 /* 454 * Default is that last command was NOT a write command; 455 * if we do a write command we will notice this in cyintr(). 456 */ 457 yc->yc_lastiow = 0; 458 if (yc->yc_openf < 0 || 459 (bp->b_command != CY_SENSE && (cy->cy_tpb.tpstatus&CYS_OL) == 0)) { 460 /* 461 * Have had a hard error on a non-raw tape 462 * or the tape unit is now unavailable (e.g. 463 * taken off line). 464 */ 465 dlog(LOG_INFO, "openf %d command %x status %b\n", 466 yc->yc_openf, bp->b_command, cy->cy_tpb.tpstatus, CYS_BITS); 467 bp->b_flags |= B_ERROR; 468 goto next; 469 } 470 if (bp == &ccybuf[CYUNIT(bp->b_dev)]) { 471 /* 472 * Execute control operation with the specified count. 473 * 474 * Set next state; give 5 minutes to complete 475 * rewind or file mark search, or 10 seconds per 476 * iteration (minimum 60 seconds and max 5 minutes) 477 * to complete other ops. 478 */ 479 if (bp->b_command == CY_REW) { 480 vm->um_tab.b_active = SREW; 481 yc->yc_timo = 5*60; 482 } else { 483 vm->um_tab.b_active = SCOM; 484 yc->yc_timo = imin(imax(10*(int)bp->b_repcnt,60),5*60); 485 } 486 cy->cy_tpb.tprec = htoms(bp->b_repcnt); 487 goto dobpcmd; 488 } 489 /* 490 * The following checks handle boundary cases for operation 491 * on no-raw tapes. On raw tapes the initialization of 492 * yc->yc_nxrec by cyphys causes them to be skipped normally 493 * (except in the case of retries). 494 */ 495 if (bdbtofsb(bp->b_blkno) > yc->yc_nxrec) { 496 /* 497 * Can't read past known end-of-file. 498 */ 499 bp->b_flags |= B_ERROR; 500 bp->b_error = ENXIO; 501 goto next; 502 } 503 if (bdbtofsb(bp->b_blkno) == yc->yc_nxrec && bp->b_flags&B_READ) { 504 /* 505 * Reading at end of file returns 0 bytes. 506 */ 507 bp->b_resid = bp->b_bcount; 508 clrbuf(bp); 509 goto next; 510 } 511 if ((bp->b_flags&B_READ) == 0) 512 /* 513 * Writing sets EOF. 514 */ 515 yc->yc_nxrec = bdbtofsb(bp->b_blkno) + 1; 516 if ((blkno = yc->yc_blkno) == bdbtofsb(bp->b_blkno)) { 517 caddr_t addr; 518 int cmd; 519 520 /* 521 * Choose the appropriate i/o command based on the 522 * transfer size and the controller's internal buffer. 523 * If we're retrying a read on a raw device because 524 * the original try was a buffer request which failed 525 * due to a record length error, then we force the use 526 * of the raw controller read (YECH!!!!). 527 */ 528 if (bp->b_flags&B_READ) { 529 if (bp->b_bcount > cy->cy_bs || bp->b_errcnt) 530 cmd = CY_RCOM; 531 else 532 cmd = CY_BRCOM; 533 } else { 534 /* 535 * On write error retries erase the 536 * inter-record gap before rewriting. 537 */ 538 if (vm->um_tab.b_errcnt && 539 vm->um_tab.b_active != SERASED) { 540 vm->um_tab.b_active = SERASE; 541 bp->b_command = CY_ERASE; 542 yc->yc_timo = 60; 543 goto dobpcmd; 544 } 545 cmd = (bp->b_bcount > cy->cy_bs) ? CY_WCOM : CY_BWCOM; 546 } 547 vm->um_tab.b_active = SIO; 548 addr = (caddr_t)vbastart(bp, cy->cy_buf, 549 (long *)cy->cy_map, cy->cy_utl); 550 cy->cy_tpb.tpcmd = cmd; 551 cy->cy_tpb.tpcontrol = yc->yc_dens; 552 if (cmd == CY_RCOM || cmd == CY_WCOM) 553 cy->cy_tpb.tpcontrol |= CYCW_LOCK; 554 cy->cy_tpb.tpstatus = 0; 555 cy->cy_tpb.tpcount = 0; 556 cyldmba(cy->cy_tpb.tpdata, (caddr_t)addr); 557 cy->cy_tpb.tprec = 0; 558 cy->cy_tpb.tpsize = htoms(bp->b_bcount); 559 cyldmba(cy->cy_tpb.tplink, (caddr_t)0); 560 do 561 uncache(&cy->cy_ccb.cbgate); 562 while (cy->cy_ccb.cbgate == GATE_CLOSED); 563 cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_tpb); 564 cy->cy_ccb.cbcw = CBCW_IE; 565 cy->cy_ccb.cbgate = GATE_CLOSED; 566 dlog(LOG_INFO, "CY_GO(%x) cmd %x control %x size %d\n", 567 vm->um_addr, cy->cy_tpb.tpcmd, cy->cy_tpb.tpcontrol, 568 htoms(cy->cy_tpb.tpsize)); 569 CY_GO(vm->um_addr); 570 return; 571 } 572 /* 573 * Tape positioned incorrectly; set to seek forwards 574 * or backwards to the correct spot. This happens 575 * for raw tapes only on error retries. 576 */ 577 vm->um_tab.b_active = SSEEK; 578 if (blkno < bdbtofsb(bp->b_blkno)) { 579 bp->b_command = CY_SFORW; 580 cy->cy_tpb.tprec = htoms(bdbtofsb(bp->b_blkno) - blkno); 581 } else { 582 bp->b_command = CY_SREV; 583 cy->cy_tpb.tprec = htoms(blkno - bdbtofsb(bp->b_blkno)); 584 } 585 yc->yc_timo = imin(imax(10 * htoms(cy->cy_tpb.tprec), 60), 5*60); 586 dobpcmd: 587 /* 588 * Do the command in bp. Reverse direction commands 589 * are indicated by having CYCW_REV or'd into their 590 * value. For these we must set the appropriate bit 591 * in the control field. 592 */ 593 if (bp->b_command&CYCW_REV) { 594 cy->cy_tpb.tpcmd = bp->b_command &~ CYCW_REV; 595 cy->cy_tpb.tpcontrol = yc->yc_dens | CYCW_REV; 596 } else { 597 cy->cy_tpb.tpcmd = bp->b_command; 598 cy->cy_tpb.tpcontrol = yc->yc_dens; 599 } 600 cy->cy_tpb.tpstatus = 0; 601 cy->cy_tpb.tpcount = 0; 602 cyldmba(cy->cy_tpb.tplink, (caddr_t)0); 603 do 604 uncache(&cy->cy_ccb.cbgate); 605 while (cy->cy_ccb.cbgate == GATE_CLOSED); 606 cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_tpb); 607 cy->cy_ccb.cbcw = CBCW_IE; 608 cy->cy_ccb.cbgate = GATE_CLOSED; 609 dlog(LOG_INFO, "CY_GO(%x) cmd %x control %x rec %d\n", 610 vm->um_addr, cy->cy_tpb.tpcmd, cy->cy_tpb.tpcontrol, 611 htoms(cy->cy_tpb.tprec)); 612 CY_GO(vm->um_addr); 613 return; 614 next: 615 /* 616 * Done with this operation due to error or the 617 * fact that it doesn't do anything. Release VERSAbus 618 * resource (if any), dequeue the transfer and continue 619 * processing this slave. 620 */ 621 if (bp == &rcybuf[CYUNIT(bp->b_dev)]) 622 vbadone(bp, cy->cy_buf, (long *)cy->cy_map, cy->cy_utl); 623 vm->um_tab.b_errcnt = 0; 624 dp->b_actf = bp->av_forw; 625 iodone(bp); 626 goto loop; 627 } 628 629 /* 630 * Cy interrupt routine. 631 */ 632 cyintr(cipher) 633 int cipher; 634 { 635 struct buf *dp; 636 register struct buf *bp; 637 register struct vba_ctlr *vm = cyminfo[cipher]; 638 register struct cy_softc *cy; 639 register struct yc_softc *yc; 640 int cyunit, err; 641 register state; 642 643 dlog(LOG_INFO, "cyintr(%d)\n", cipher); 644 /* 645 * First, turn off the interrupt from the controller 646 * (device uses Multibus non-vectored interrupts...yech). 647 */ 648 cy = &cy_softc[vm->um_ctlr]; 649 cy->cy_ccb.cbcw = CBCW_CLRINT; 650 cyldmba(cy->cy_ccb.cbtpb, &cy->cy_nop); 651 cy->cy_ccb.cbgate = GATE_CLOSED; 652 CY_GO(vm->um_addr); 653 if ((dp = vm->um_tab.b_actf) == NULL) { 654 dlog(LOG_ERR, "cy%d: stray interrupt", vm->um_ctlr); 655 return; 656 } 657 bp = dp->b_actf; 658 cyunit = CYUNIT(bp->b_dev); 659 cy = &cy_softc[cyunit]; 660 cyuncachetpb(cy); 661 /* 662 * If last command was a rewind or file mark search, and 663 * tape is still moving, wait for the operation to complete. 664 */ 665 if (vm->um_tab.b_active == SREW) { 666 vm->um_tab.b_active = SCOM; 667 if ((cy->cy_tpb.tpstatus&CYS_RDY) == 0) { 668 yc->yc_timo = 5*60; /* 5 minutes */ 669 return; 670 } 671 } 672 /* 673 * An operation completed...record status. 674 */ 675 yc = &yc_softc[YCUNIT(bp->b_dev)]; 676 yc->yc_timo = INF; 677 yc->yc_control = cy->cy_tpb.tpcontrol; 678 yc->yc_status = cy->cy_tpb.tpstatus; 679 yc->yc_resid = bp->b_bcount - htoms(cy->cy_tpb.tpcount); 680 dlog(LOG_INFO, "cmd %x control %b status %b resid %d\n", 681 cy->cy_tpb.tpcmd, yc->yc_control, CYCW_BITS, 682 yc->yc_status, CYS_BITS, yc->yc_resid); 683 if ((bp->b_flags&B_READ) == 0) 684 yc->yc_lastiow = 1; 685 state = vm->um_tab.b_active; 686 vm->um_tab.b_active = 0; 687 /* 688 * Check for errors. 689 */ 690 if (cy->cy_tpb.tpstatus&CYS_ERR) { 691 err = cy->cy_tpb.tpstatus&CYS_ERR; 692 dlog(LOG_INFO, "error %d\n", err); 693 /* 694 * If we hit the end of tape file, update our position. 695 */ 696 if (err == CYER_FM) { 697 yc->yc_status |= CYS_FM; 698 state = SCOM; /* force completion */ 699 cyseteof(bp); /* set blkno and nxrec */ 700 goto opdone; 701 } 702 /* 703 * Fix up errors which occur due to backspacing over 704 * the beginning of the tape. 705 */ 706 if (err == CYER_BOT && cy->cy_tpb.tpcontrol&CYCW_REV) { 707 yc->yc_status |= CYS_BOT; 708 goto ignoreerr; 709 } 710 /* 711 * If we were reading raw tape and the only error was that the 712 * record was too long, then we don't consider this an error. 713 */ 714 if (bp == &rcybuf[cyunit] && (bp->b_flags&B_READ) && 715 err == CYER_STROBE) { 716 /* 717 * Retry reads once with the command changed to 718 * a raw read (if possible). Setting b_errcnt 719 * here causes cystart (above) to force a CY_RCOM. 720 */ 721 if (bp->b_errcnt++ != 0) 722 goto ignoreerr; 723 yc->yc_blkno++; 724 goto opcont; 725 } 726 /* 727 * If error is not hard, and this was an i/o operation 728 * retry up to 8 times. 729 */ 730 err = 1 << err; 731 if ((err&CYER_SOFT) && state == SIO) { 732 if (++vm->um_tab.b_errcnt < 7) { 733 yc->yc_blkno++; 734 goto opcont; 735 } 736 } else 737 /* 738 * Hard or non-i/o errors on non-raw tape 739 * cause it to close. 740 */ 741 if (yc->yc_openf>0 && bp != &rcybuf[cyunit]) 742 yc->yc_openf = -1; 743 /* 744 * Couldn't recover from error. 745 */ 746 tprintf(yc->yc_ttyp, 747 "yc%d: hard error bn%d status=%b", YCUNIT(bp->b_dev), 748 bp->b_blkno, yc->yc_status, CYS_BITS); 749 if (err < NCYERROR) 750 tprintf(yc->yc_ttyp, ", %s", cyerror[err]); 751 tprintf(yc->yc_ttyp, "\n"); 752 bp->b_flags |= B_ERROR; 753 goto opdone; 754 } 755 /* 756 * Advance tape control FSM. 757 */ 758 ignoreerr: 759 /* 760 * If we hit a tape mark update our position. 761 */ 762 if (yc->yc_status&CYS_FM && bp->b_flags&B_READ) { 763 cyseteof(bp); 764 goto opdone; 765 } 766 switch (state) { 767 768 case SIO: 769 /* 770 * Read/write increments tape block number. 771 */ 772 yc->yc_blkno++; 773 goto opdone; 774 775 case SCOM: 776 /* 777 * For forward/backward space record update current position. 778 */ 779 if (bp == &ccybuf[CYUNIT(bp->b_dev)]) switch (bp->b_command) { 780 781 case CY_SFORW: 782 yc->yc_blkno -= bp->b_repcnt; 783 break; 784 785 case CY_SREV: 786 yc->yc_blkno += bp->b_repcnt; 787 break; 788 } 789 goto opdone; 790 791 case SSEEK: 792 yc->yc_blkno = bdbtofsb(bp->b_blkno); 793 goto opcont; 794 795 case SERASE: 796 /* 797 * Completed erase of the inter-record gap due to a 798 * write error; now retry the write operation. 799 */ 800 vm->um_tab.b_active = SERASED; 801 goto opcont; 802 } 803 804 opdone: 805 /* 806 * Reset error count and remove from device queue. 807 */ 808 vm->um_tab.b_errcnt = 0; 809 dp->b_actf = bp->av_forw; 810 /* 811 * Save resid and release resources. 812 */ 813 bp->b_resid = bp->b_bcount - htoms(cy->cy_tpb.tpcount); 814 if (bp == &rcybuf[CYUNIT(bp->b_dev)]) 815 vbadone(bp, cy->cy_buf, (long *)cy->cy_map, cy->cy_utl); 816 iodone(bp); 817 /* 818 * Circulate slave to end of controller 819 * queue to give other slaves a chance. 820 */ 821 vm->um_tab.b_actf = dp->b_forw; 822 if (dp->b_actf) { 823 dp->b_forw = NULL; 824 if (vm->um_tab.b_actf == NULL) 825 vm->um_tab.b_actf = dp; 826 else 827 vm->um_tab.b_actl->b_forw = dp; 828 } 829 if (vm->um_tab.b_actf == 0) 830 return; 831 opcont: 832 cystart(vm); 833 } 834 835 cytimer(dev) 836 int dev; 837 { 838 register struct yc_softc *yc = &yc_softc[YCUNIT(dev)]; 839 int s; 840 841 if (yc->yc_timo != INF && (yc->yc_timo -= 5) < 0) { 842 printf("yc%d: lost interrupt\n", YCUNIT(dev)); 843 yc->yc_timo = INF; 844 s = spl3(); 845 cyintr(CYUNIT(dev)); 846 splx(s); 847 } 848 timeout(cytimer, (caddr_t)dev, 5*hz); 849 } 850 851 cyseteof(bp) 852 register struct buf *bp; 853 { 854 register int cyunit = CYUNIT(bp->b_dev); 855 register struct cy_softc *cy = &cy_softc[cyunit]; 856 register struct yc_softc *yc = &yc_softc[YCUNIT(bp->b_dev)]; 857 858 if (bp == &ccybuf[cyunit]) { 859 if (yc->yc_blkno > bdbtofsb(bp->b_blkno)) { 860 /* reversing */ 861 yc->yc_nxrec = bdbtofsb(bp->b_blkno) - 862 htoms(cy->cy_tpb.tpcount); 863 yc->yc_blkno = yc->yc_nxrec; 864 } else { 865 yc->yc_blkno = bdbtofsb(bp->b_blkno) + 866 htoms(cy->cy_tpb.tpcount); 867 yc->yc_nxrec = yc->yc_blkno - 1; 868 } 869 return; 870 } 871 /* eof on read */ 872 yc->yc_nxrec = bdbtofsb(bp->b_blkno); 873 } 874 875 cyread(dev, uio) 876 dev_t dev; 877 struct uio *uio; 878 { 879 int errno; 880 881 errno = cyphys(dev, uio); 882 if (errno) 883 return (errno); 884 return (physio(cystrategy, &rcybuf[CYUNIT(dev)], dev, B_READ, minphys, uio)); 885 } 886 887 cywrite(dev, uio) 888 dev_t dev; 889 struct uio *uio; 890 { 891 int errno; 892 893 errno = cyphys(dev, uio); 894 if (errno) 895 return (errno); 896 return (physio(cystrategy, &rcybuf[CYUNIT(dev)], dev, B_WRITE, minphys, uio)); 897 } 898 899 /* 900 * Check that a raw device exits. 901 * If it does, set up the yc_blkno and yc_nxrec 902 * so that the tape will appear positioned correctly. 903 */ 904 cyphys(dev, uio) 905 dev_t dev; 906 struct uio *uio; 907 { 908 register int ycunit = YCUNIT(dev); 909 register daddr_t a; 910 register struct yc_softc *yc; 911 register struct vba_device *vi; 912 913 if (ycunit >= NYC || (vi = ycdinfo[ycunit]) == 0 || vi->ui_alive == 0) 914 return (ENXIO); 915 yc = &yc_softc[ycunit]; 916 a = bdbtofsb(uio->uio_offset >> DEV_BSHIFT); 917 yc->yc_blkno = a; 918 yc->yc_nxrec = a + 1; 919 return (0); 920 } 921 922 /*ARGSUSED*/ 923 cyioctl(dev, cmd, data, flag) 924 caddr_t data; 925 dev_t dev; 926 { 927 int ycunit = YCUNIT(dev); 928 register struct yc_softc *yc = &yc_softc[ycunit]; 929 register struct buf *bp = &ccybuf[CYUNIT(dev)]; 930 register callcount; 931 int fcount, op; 932 struct mtop *mtop; 933 struct mtget *mtget; 934 /* we depend of the values and order of the MT codes here */ 935 static cyops[] = 936 {CY_WEOF,CY_SFORW,CY_SREV,CY_SFORW,CY_SREV,CY_REW,CY_OFFL,CY_SENSE}; 937 938 switch (cmd) { 939 940 case MTIOCTOP: /* tape operation */ 941 mtop = (struct mtop *)data; 942 switch (op = mtop->mt_op) { 943 944 case MTWEOF: 945 case MTFSR: case MTBSR: 946 case MTFSF: case MTBSF: 947 callcount = mtop->mt_count; 948 fcount = 1; 949 break; 950 951 case MTREW: case MTOFFL: case MTNOP: 952 callcount = 1; 953 fcount = 1; 954 break; 955 956 default: 957 return (ENXIO); 958 } 959 if (callcount <= 0 || fcount <= 0) 960 return (EINVAL); 961 while (--callcount >= 0) { 962 /* 963 * Gagh, this controller is the pits... 964 */ 965 if (op == MTFSF || op == MTBSF) { 966 do 967 cycommand(dev, cyops[op], 1); 968 while ((bp->b_flags&B_ERROR) == 0 && 969 (yc->yc_status&(CYS_EOT|CYS_BOT|CYS_FM)) == 0); 970 } else 971 cycommand(dev, cyops[op], fcount); 972 if ((bp->b_flags&B_ERROR) || 973 (yc->yc_status&(CYS_BOT|CYS_EOT))) 974 break; 975 } 976 bp->b_resid = callcount + 1; 977 return (geterror(bp)); 978 979 case MTIOCGET: 980 cycommand(dev, CY_SENSE, 1); 981 mtget = (struct mtget *)data; 982 mtget->mt_dsreg = yc->yc_status; 983 mtget->mt_erreg = yc->yc_control; 984 mtget->mt_resid = yc->yc_resid; 985 mtget->mt_type = MT_ISCY; 986 break; 987 988 default: 989 return (ENXIO); 990 } 991 return (0); 992 } 993 994 /* 995 * Poll until the controller is ready. 996 */ 997 cywait(cp) 998 register struct cyccb *cp; 999 { 1000 register int i = 5000; 1001 1002 uncache(&cp->cbgate); 1003 while (i-- > 0 && cp->cbgate == GATE_CLOSED) { 1004 DELAY(1000); 1005 uncache(&cp->cbgate); 1006 } 1007 return (i <= 0); 1008 } 1009 1010 /* 1011 * Load a 20 bit pointer into an i/o register. 1012 */ 1013 cyldmba(wreg, value) 1014 short *wreg; 1015 caddr_t value; 1016 { 1017 register int v = (int)value; 1018 register caddr_t reg = (caddr_t)wreg; 1019 1020 *reg++ = v; 1021 *reg++ = v >> 8; 1022 *reg++ = 0; 1023 *reg = (v&0xf0000) >> 12; 1024 } 1025 1026 /* 1027 * Unconditionally reset all controllers to their initial state. 1028 */ 1029 cyreset(vba) 1030 int vba; 1031 { 1032 register caddr_t addr; 1033 register int ctlr; 1034 1035 for (ctlr = 0; ctlr < NCY; ctlr++) 1036 if (cyminfo[ctlr] && cyminfo[ctlr]->um_vbanum == vba) { 1037 addr = cyminfo[ctlr]->um_addr; 1038 CY_RESET(addr); 1039 if (!cyinit(ctlr)) { 1040 printf("cy%d: reset failed\n", ctlr); 1041 cyminfo[ctlr] = NULL; 1042 } 1043 } 1044 } 1045 1046 cyuncachetpb(cy) 1047 struct cy_softc *cy; 1048 { 1049 register long *lp = (long *)&cy->cy_tpb; 1050 register int i; 1051 1052 for (i = 0; i < howmany(sizeof (struct cytpb), sizeof (long)); i++) 1053 uncache(lp++); 1054 } 1055 1056 /* 1057 * Dump routine. 1058 */ 1059 cydump(dev) 1060 dev_t dev; 1061 { 1062 register struct cy_softc *cy; 1063 register int bs, num, start; 1064 register caddr_t addr; 1065 int unit = CYUNIT(dev), ctlr, error; 1066 1067 if (unit >= NCY || cyminfo[unit] == 0 || 1068 (cy = &cy_softc[unit])->cy_bs == 0 || YCUNIT(dev) >= NYC) 1069 return (ENXIO); 1070 if (cywait(&cy->cy_ccb)) 1071 return (EFAULT); 1072 #define phys(a) ((caddr_t)((int)(a)&~0xc0000000)) 1073 addr = phys(cyminfo[ctlr]->um_addr); 1074 num = maxfree, start = NBPG*2; 1075 while (num > 0) { 1076 bs = num > btoc(CYMAXIO) ? btoc(CYMAXIO) : num; 1077 error = cydwrite(cy, start, bs, addr); 1078 if (error) 1079 return (error); 1080 start += bs, num -= bs; 1081 } 1082 cyweof(cy, addr); 1083 cyweof(cy, addr); 1084 uncache(&cy->cy_tpb); 1085 if (cy->cy_tpb.tpstatus&CYS_ERR) 1086 return (EIO); 1087 cyrewind(cy, addr); 1088 return (0); 1089 } 1090 1091 cydwrite(cy, pf, npf, addr) 1092 register struct cy_softc *cy; 1093 int pf, npf; 1094 caddr_t addr; 1095 { 1096 1097 cy->cy_tpb.tpcmd = CY_WCOM; 1098 cy->cy_tpb.tpcontrol = CYCW_LOCK|CYCW_25IPS|CYCW_16BITS; 1099 cy->cy_tpb.tpstatus = 0; 1100 cy->cy_tpb.tpsize = htoms(npf*NBPG); 1101 cyldmba(cy->cy_tpb.tplink, (caddr_t)0); 1102 cyldmba(cy->cy_tpb.tpdata, (caddr_t)(pf*NBPG)); 1103 cyldmba(cy->cy_ccb.cbtpb, (caddr_t)&cy->cy_tpb); 1104 cy->cy_ccb.cbgate = GATE_CLOSED; 1105 CY_GO(addr); 1106 if (cywait(&cy->cy_ccb)) 1107 return (EFAULT); 1108 uncache(&cy->cy_tpb); 1109 if (cy->cy_tpb.tpstatus&CYS_ERR) 1110 return (EIO); 1111 return (0); 1112 } 1113 1114 cyweof(cy, addr) 1115 register struct cy_softc *cy; 1116 caddr_t addr; 1117 { 1118 1119 cy->cy_tpb.tpcmd = CY_WEOF; 1120 cy->cy_tpb.tpcount = htoms(1); 1121 cy->cy_ccb.cbgate = GATE_CLOSED; 1122 CY_GO(addr); 1123 (void) cywait(&cy->cy_ccb); 1124 } 1125 1126 cyrewind(cy, addr) 1127 register struct cy_softc *cy; 1128 caddr_t addr; 1129 { 1130 1131 cy->cy_tpb.tpcmd = CY_REW; 1132 cy->cy_tpb.tpcount = htoms(1); 1133 cy->cy_ccb.cbgate = GATE_CLOSED; 1134 CY_GO(addr); 1135 (void) cywait(&cy->cy_ccb); 1136 } 1137 #endif 1138