1 /* 2 * Copyright (c) 1992 OMRON Corporation. 3 * Copyright (c) 1992 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * OMRON Corporation. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)st.c 7.2 (Berkeley) 07/13/92 12 */ 13 14 /* 15 * st.c -- TEAC MT-2ST/N60 SCSI TAPE UNIT Device Driver 16 * remaked by A.Fujita, MAR-22-1992 17 */ 18 19 /* 20 * SCSI CCS (Command Command Set) disk driver. 21 */ 22 #include "st.h" 23 #if NST > 0 24 25 #include "param.h" 26 #include "buf.h" 27 #include "file.h" 28 #include "proc.h" 29 #include "mtio.h" 30 #include "tprintf.h" 31 32 #include "device.h" 33 #include "scsireg.h" 34 #include "scsivar.h" 35 36 extern int scsi_test_unit_rdy(); 37 extern int scsi_request_sense(); 38 extern int scsi_immed_command(); 39 extern char *scsi_status(); 40 41 extern int scgo(); 42 extern void scfree(); 43 44 char *sense_key(); 45 46 int stinit(), ststrategy(), ststart(), stintr(); 47 48 struct driver stdriver = { 49 stinit, "st", ststart, (int (*)()) 0, stintr, (int (*)()) 0 50 }; 51 52 struct st_softc { 53 struct hp_device *sc_hd; 54 struct scsi_queue sc_dq; 55 int sc_flags; 56 short sc_type; /* drive type */ 57 short sc_punit; /* physical unit (scsi lun) */ 58 tpr_t sc_ctty; 59 } st_softc[NST]; 60 61 /* softc flags */ 62 #define STF_ALIVE 0x0001 63 #define STF_OPEN 0x0002 64 #define STF_WMODE 0x0004 65 #define STF_WRTTN 0x0008 66 #define STF_CMD 0x0010 67 #define STF_LEOT 0x0020 68 #define STF_MOVED 0x0040 69 70 u_char xsense_buff[60]; 71 72 struct scsi_fmt_cdb st_read_cmd = { 6, CMD_READ }; 73 struct scsi_fmt_cdb st_write_cmd = { 6, CMD_WRITE }; 74 75 struct buf sttab[NST]; 76 struct buf stbuf[NST]; 77 78 #define stunit(x) (minor(x) & 3) 79 #define stpunit(x) ((x) & 7) 80 81 #define STDEV_NOREWIND 0x04 82 83 #define STRETRY 2 /* IO retry count */ 84 85 struct st_iostat { 86 int imax; 87 int imin; 88 int omax; 89 int omin; 90 }; 91 92 struct st_iostat st_iostat[NST]; 93 94 95 /* 96 * Initialize 97 */ 98 99 int 100 stinit(hd) 101 register struct hp_device *hd; 102 { 103 register struct st_softc *sc = &st_softc[hd->hp_unit]; 104 105 sc->sc_hd = hd; 106 sc->sc_punit = stpunit(hd->hp_flags); 107 sc->sc_type = stident(sc, hd); 108 if (sc->sc_type < 0) 109 return(0); 110 sc->sc_dq.dq_ctlr = hd->hp_ctlr; 111 sc->sc_dq.dq_unit = hd->hp_unit; 112 sc->sc_dq.dq_slave = hd->hp_slave; 113 sc->sc_dq.dq_driver = &stdriver; 114 sc->sc_flags = STF_ALIVE; 115 return(1); 116 } 117 118 static struct scsi_inquiry inqbuf; 119 static struct scsi_fmt_cdb inq = { 120 6, 121 CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 122 }; 123 124 int 125 stident(sc, hd) 126 struct st_softc *sc; 127 struct hp_device *hd; 128 { 129 char idstr[32]; 130 int unit; 131 register int ctlr, slave; 132 register int i, stat; 133 register int tries = 10; 134 135 ctlr = hd->hp_ctlr; 136 slave = hd->hp_slave; 137 unit = sc->sc_punit; 138 139 /* 140 * See if unit exists and is a disk then read block size & nblocks. 141 */ 142 while ((stat = scsi_immed_command(ctlr, slave, unit, 143 &inq, (u_char *)&inqbuf, sizeof(inqbuf))) != 0) { 144 if (stat < 0 || --tries < 0) 145 return (-1); 146 DELAY(1000); 147 } 148 149 switch (inqbuf.type) { 150 case 1: /* tape */ 151 break; 152 default: /* not a disk */ 153 printf("stident: inqbuf.type = %d\n", inqbuf.type); 154 return (-1); 155 } 156 157 bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 158 for (i = 27; i > 23; --i) 159 if (idstr[i] != ' ') 160 break; 161 idstr[i+1] = 0; 162 for (i = 23; i > 7; --i) 163 if (idstr[i] != ' ') 164 break; 165 idstr[i+1] = 0; 166 for (i = 7; i >= 0; --i) 167 if (idstr[i] != ' ') 168 break; 169 idstr[i+1] = 0; 170 printf("st%d: %s %s rev %s\n", hd->hp_unit, idstr, &idstr[8], 171 &idstr[24]); 172 173 return(inqbuf.type); 174 } 175 176 177 /* 178 * Open 179 */ 180 181 int 182 stopen(dev, flag, type, p) 183 dev_t dev; 184 int flag, type; 185 struct proc *p; 186 { 187 register int unit = stunit(dev); 188 register struct st_softc *sc = &st_softc[unit]; 189 register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff; 190 int ctlr = sc->sc_dq.dq_ctlr; 191 int slave = sc->sc_dq.dq_slave; 192 int stat, retry = 9; 193 194 if (unit >= NST || (sc->sc_flags & STF_ALIVE) == 0) 195 return(-1); 196 if (sc->sc_flags & STF_OPEN) 197 return(-1); 198 199 /* drive ready ? */ 200 while ((stat = scsi_test_unit_rdy(ctlr, slave, 0)) != 0) { 201 scsi_request_sense(ctlr, slave, 0, sp, 8); 202 203 if (stat != STS_CHECKCOND) { 204 printf("st%d: stopen: %s\n", scsi_status(stat)); 205 return(EIO); 206 } 207 208 if (retry-- < 0) { 209 printf("st%d: stopen: %s\n", sense_key(sp->key)); 210 return(EIO); 211 } 212 213 DELAY(1000000); 214 } 215 216 sc->sc_ctty = tprintf_open(p); 217 218 sc->sc_flags |= STF_OPEN; 219 if (flag & FWRITE) 220 sc->sc_flags |= STF_WMODE; 221 sc->sc_flags &= ~STF_MOVED; 222 223 return(0); 224 } 225 226 /*ARGSUSED*/ 227 stclose(dev) 228 dev_t dev; 229 { 230 register int unit = stunit(dev); 231 register struct st_softc *sc = &st_softc[unit]; 232 register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff; 233 int ctlr = sc->sc_hd->hp_ctlr; 234 int slave = sc->sc_hd->hp_slave; 235 int stat, retry = 9; 236 237 if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) { 238 st_write_EOF(dev); 239 } 240 241 if ((minor(dev) & STDEV_NOREWIND) == 0) { 242 st_rewind(dev); 243 } 244 245 sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN); 246 247 tprintf_close(sc->sc_ctty); 248 249 return(0); 250 } 251 252 /* 253 * Strategy 254 */ 255 256 int 257 ststrategy(bp) 258 register struct buf *bp; 259 { 260 register int unit = stunit(bp->b_dev); 261 register struct buf *dp = &sttab[unit]; 262 int s; 263 264 bp->av_forw = NULL; 265 266 s = splbio(); 267 268 if (dp->b_actf == NULL) 269 dp->b_actf = bp; 270 else 271 dp->b_actl->av_forw = bp; 272 273 dp->b_actl = bp; 274 275 if (dp->b_active == 0) { 276 dp->b_active = 1; 277 stustart(unit); 278 } 279 280 splx(s); 281 } 282 283 int 284 stustart(unit) 285 register int unit; 286 { 287 register struct st_softc *sc = &st_softc[unit]; 288 register struct hp_device *hp = sc->sc_hd; 289 register struct scsi_queue *dq = &sc->sc_dq; 290 register struct buf *bp = sttab[unit].b_actf; 291 register struct scsi_fmt_cdb *cmd; 292 long nblks; 293 294 cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd; 295 cmd->cdb[1] = 1; /* unknown setup */ 296 297 if (bp->b_flags & B_READ) 298 sc->sc_flags &= ~STF_WRTTN; 299 else 300 sc->sc_flags |= STF_WRTTN; 301 302 nblks = bp->b_bcount >> DEV_BSHIFT; 303 304 if (bp->b_bcount % DEV_BSIZE) { 305 tprintf(sc->sc_ctty, 306 "st%d: I/O not block aligned %d/%ld\n", 307 unit, DEV_BSIZE, bp->b_bcount); 308 309 bp->b_flags |= B_ERROR; 310 bp->b_error = EIO; 311 312 sttab[unit].b_errcnt = 0; 313 sttab[unit].b_actf = bp->b_actf; 314 315 bp->b_resid = 0; 316 317 biodone(bp); 318 319 if (sttab[unit].b_actf) { 320 stustart(unit); 321 } else { 322 sttab[unit].b_active = 0; 323 } 324 } 325 326 *(u_char *)(&cmd->cdb[2]) = (u_char) (nblks >> 16); 327 *(u_char *)(&cmd->cdb[3]) = (u_char) (nblks >> 8); 328 *(u_char *)(&cmd->cdb[4]) = (u_char) nblks; 329 330 cmd->cdb[5] = 0; /* unknown setup */ 331 332 sc->sc_flags |= STF_MOVED; 333 334 dq->dq_cdb = cmd; 335 dq->dq_bp = bp; 336 dq->dq_flags = 0; /* No Disconnect */ 337 338 if (screq(dq)) 339 ststart(unit); 340 } 341 342 int 343 ststart(unit) 344 register int unit; 345 { 346 register struct st_softc *sc = &st_softc[unit]; 347 register struct hp_device *hp = sc->sc_hd; 348 349 scstart(hp->hp_ctlr); 350 } 351 352 /* 353 * Interrupt 354 */ 355 356 char * 357 sense_key(key) 358 int key; 359 { 360 if (key == 0) 361 return("No Sense"); 362 else if (key == 2) 363 return("Not Ready"); 364 else if (key == 3) 365 return("Medium Error"); 366 else if (key == 4) 367 return("Hardware Error"); 368 else if (key == 5) 369 return("Illegal Request"); 370 else if (key == 6) 371 return("Unit Attention"); 372 else if (key == 7) 373 return("Data Protect"); 374 else if (key == 8) 375 return("No Data"); 376 else if (key == 11) 377 return("Aborted Command"); 378 else if (key == 13) 379 return("Volume Overflow"); 380 else 381 return("Unknown Error"); 382 } 383 384 int 385 stintr(unit, stat) 386 register int unit; 387 int stat; 388 { 389 register struct st_softc *sc = &st_softc[unit]; 390 register struct scsi_xsense *xp = (struct scsi_xsense *) xsense_buff; 391 register struct scsi_queue *dq = &sc->sc_dq; 392 register struct buf *bp = dq->dq_bp; 393 int ctlr = dq->dq_ctlr; 394 int slave = dq->dq_slave; 395 396 if (bp->b_flags & B_READ) { 397 st_iostat[unit].imin = min(dq->dq_imin, st_iostat[unit].imin); 398 if (dq->dq_imax > st_iostat[unit].imax) { 399 st_iostat[unit].imax = dq->dq_imax; 400 #ifdef ST_IOSTAT 401 printf("stintr: st%d INPUT MAX = %d, MIN = %d\n", 402 unit, st_iostat[unit].imax, st_iostat[unit].imin); 403 #endif 404 } 405 } else { 406 st_iostat[unit].omin = min(dq->dq_omin, st_iostat[unit].omin); 407 if (dq->dq_omax > st_iostat[unit].omax) { 408 st_iostat[unit].omax = dq->dq_omax; 409 #ifdef ST_IOSTAT 410 printf("stintr: st%d OUTPUT MAX = %d, MIN = %d\n", 411 unit, st_iostat[unit].omax, st_iostat[unit].omin); 412 #endif 413 } 414 } 415 if (stat < 0) { 416 bp->b_flags |= B_ERROR; 417 bp->b_error = EIO; 418 goto done; 419 } 420 421 switch (stat) { 422 /* scsi command completed ok */ 423 case 0: 424 bp->b_resid = 0; 425 break; 426 427 /* more status */ 428 case STS_CHECKCOND: 429 scsi_request_sense(ctlr, slave, 0, xp, 8); 430 #ifdef DEBUG 431 printf("stintr: xsense_buff[0] = 0x%s\n", hexstr(xsense_buff[0], 2)); 432 printf("stintr: xsense_buff[2] = 0x%s\n", hexstr(xsense_buff[2], 2)); 433 printf("stintr: Sense Key = [%s]\n", sense_key(xp->key)); 434 #endif 435 if (xp->valid) { 436 bp->b_resid = (u_long)((xp->info1 << 24) | 437 (xp->info2 << 16) | 438 (xp->info3 << 8) | 439 (xp->info4)); 440 bp->b_resid <<= DEV_BSHIFT; 441 } 442 443 if (xp->filemark) { /* End of File */ 444 tprintf(sc->sc_ctty, "st%d: End of File\n", unit); 445 bp->b_flags |= B_ERROR; 446 bp->b_error = EIO; 447 break; 448 } 449 450 if (xp->key) { 451 tprintf(sc->sc_ctty, "st%d: %s\n", unit, sense_key(xp->key)); 452 bp->b_flags |= B_ERROR; 453 bp->b_error = EIO; 454 break; 455 } 456 457 if (xp->eom) { /* End of TAPE */ 458 tprintf(sc->sc_ctty, "st%d: End of Tape\n", unit); 459 bp->b_flags |= B_ERROR; 460 bp->b_error = ENOSPC; 461 break; 462 } 463 464 tprintf(sc->sc_ctty, "st%d: unknown scsi error\n", unit); 465 bp->b_flags |= B_ERROR; 466 bp->b_error = EIO; 467 break; 468 469 default: 470 printf("st%d: stintr unknown stat 0x%x\n", unit, stat); 471 break; 472 } 473 474 done: 475 sttab[unit].b_errcnt = 0; 476 sttab[unit].b_actf = bp->b_actf; 477 478 bp->b_resid = 0; 479 480 biodone(bp); 481 482 scfree(&sc->sc_dq); 483 484 if (sttab[unit].b_actf) { 485 stustart(unit); 486 } else { 487 sttab[unit].b_active = 0; 488 } 489 } 490 491 492 /* 493 * RAW Device Routines 494 */ 495 496 497 stread(dev, uio) 498 dev_t dev; 499 struct uio *uio; 500 { 501 int unit = stunit(dev); 502 503 return(physio(ststrategy, &stbuf[unit], dev, B_READ, minphys, uio)); 504 } 505 506 stwrite(dev, uio) 507 dev_t dev; 508 struct uio *uio; 509 { 510 int unit = stunit(dev); 511 512 return(physio(ststrategy, &stbuf[unit], dev, B_WRITE, minphys, uio)); 513 } 514 515 int 516 stioctl(dev, cmd, data, flag, p) 517 dev_t dev; 518 int cmd; 519 caddr_t data; 520 int flag; 521 struct proc *p; 522 { 523 return(ENXIO); 524 } 525 526 struct scsi_fmt_cdb st_cmd; 527 528 st_rewind(dev) 529 dev_t dev; 530 { 531 register int unit = stunit(dev); 532 register struct st_softc *sc = &st_softc[unit]; 533 register struct scsi_fmt_cdb *cdb = &st_cmd; 534 register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff; 535 int ctlr, slave, stat; 536 int retry = 9; 537 538 ctlr = sc->sc_hd->hp_ctlr; 539 slave = sc->sc_hd->hp_slave; 540 541 cdb->len = 6; 542 543 cdb->cdb[0] = CMD_REWIND; 544 545 cdb->cdb[1] = 1; /* command finished soon */ 546 547 cdb->cdb[2] = 0; 548 cdb->cdb[3] = 0; 549 cdb->cdb[4] = 0; 550 551 cdb->cdb[5] = 0; /* unknown setup */ 552 553 rewind: 554 stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0); 555 556 if (stat == 0) { 557 return(1); 558 } else { 559 printf("st: rewind error\n"); 560 scsi_request_sense(ctlr, slave, 0, sp, 8); 561 printf("st: status = 0x%x, sens key = 0x%x\n", stat, sp->key); 562 563 if (retry > 0) { 564 DELAY(1000000); 565 retry--; 566 goto rewind; 567 } 568 569 return(0); 570 } 571 } 572 573 st_write_EOF(dev) 574 dev_t dev; 575 { 576 register int unit = stunit(dev); 577 register struct st_softc *sc = &st_softc[unit]; 578 register struct scsi_fmt_cdb *cdb = &st_cmd; 579 int ctlr, slave, stat; 580 int marks = 1; 581 582 ctlr = sc->sc_hd->hp_ctlr; 583 slave = sc->sc_hd->hp_slave; 584 585 cdb->len = 6; 586 587 cdb->cdb[0] = CMD_WRITE_FILEMARK; 588 589 cdb->cdb[1] = 0; 590 591 cdb->cdb[2] = 0; 592 cdb->cdb[3] = 0; 593 cdb->cdb[4] = marks; 594 595 cdb->cdb[5] = 0; /* unknown setup */ 596 597 stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0); 598 599 if (stat == 0) 600 return(1); 601 602 printf("st: write EOF error\n"); 603 604 return(0); 605 } 606 607 /* 608 * Dump 609 */ 610 611 int 612 stdump(dev) 613 dev_t dev; 614 { 615 } 616 #endif 617