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