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.4 (Berkeley) 10/11/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 /* drive ready ? */ 201 while ((stat = scsi_test_unit_rdy(ctlr, slave, 0)) != 0) { 202 scsi_request_sense(ctlr, slave, 0, sp, 8); 203 204 if (stat != STS_CHECKCOND) { 205 printf("st%d: stopen: %s\n", scsi_status(stat)); 206 return(EIO); 207 } 208 209 if (retry-- < 0) { 210 printf("st%d: stopen: %s\n", sense_key(sp->key)); 211 return(EIO); 212 } 213 214 DELAY(1000000); 215 } 216 217 sc->sc_ctty = tprintf_open(p); 218 219 sc->sc_flags |= STF_OPEN; 220 if (flag & FWRITE) 221 sc->sc_flags |= STF_WMODE; 222 sc->sc_flags &= ~STF_MOVED; 223 224 return(0); 225 } 226 227 /*ARGSUSED*/ 228 stclose(dev) 229 dev_t dev; 230 { 231 register int unit = stunit(dev); 232 register struct st_softc *sc = &st_softc[unit]; 233 register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff; 234 int ctlr = sc->sc_hd->hp_ctlr; 235 int slave = sc->sc_hd->hp_slave; 236 int stat, retry = 9; 237 238 if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) { 239 st_write_EOF(dev); 240 } 241 242 if ((minor(dev) & STDEV_NOREWIND) == 0) { 243 st_rewind(dev); 244 } 245 246 sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN); 247 248 tprintf_close(sc->sc_ctty); 249 250 return(0); 251 } 252 253 /* 254 * Strategy 255 */ 256 257 int 258 ststrategy(bp) 259 register struct buf *bp; 260 { 261 register int unit = stunit(bp->b_dev); 262 register struct buf *dp = &sttab[unit]; 263 int s; 264 265 bp->av_forw = NULL; 266 267 s = splbio(); 268 269 if (dp->b_actf == NULL) 270 dp->b_actf = bp; 271 else 272 dp->b_actl->av_forw = bp; 273 274 dp->b_actl = bp; 275 276 if (dp->b_active == 0) { 277 dp->b_active = 1; 278 stustart(unit); 279 } 280 281 splx(s); 282 } 283 284 int 285 stustart(unit) 286 register int unit; 287 { 288 register struct st_softc *sc = &st_softc[unit]; 289 register struct hp_device *hp = sc->sc_hd; 290 register struct scsi_queue *dq = &sc->sc_dq; 291 register struct buf *bp = sttab[unit].b_actf; 292 register struct scsi_fmt_cdb *cmd; 293 long nblks; 294 295 cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd; 296 cmd->cdb[1] = 1; /* unknown setup */ 297 298 if (bp->b_flags & B_READ) 299 sc->sc_flags &= ~STF_WRTTN; 300 else 301 sc->sc_flags |= STF_WRTTN; 302 303 nblks = bp->b_bcount >> DEV_BSHIFT; 304 305 if (bp->b_bcount % DEV_BSIZE) { 306 tprintf(sc->sc_ctty, 307 "st%d: I/O not block aligned %d/%ld\n", 308 unit, DEV_BSIZE, bp->b_bcount); 309 310 bp->b_flags |= B_ERROR; 311 bp->b_error = EIO; 312 313 sttab[unit].b_errcnt = 0; 314 sttab[unit].b_actf = bp->b_actf; 315 316 bp->b_resid = 0; 317 318 biodone(bp); 319 320 if (sttab[unit].b_actf) { 321 stustart(unit); 322 } else { 323 sttab[unit].b_active = 0; 324 } 325 } 326 327 *(u_char *)(&cmd->cdb[2]) = (u_char) (nblks >> 16); 328 *(u_char *)(&cmd->cdb[3]) = (u_char) (nblks >> 8); 329 *(u_char *)(&cmd->cdb[4]) = (u_char) nblks; 330 331 cmd->cdb[5] = 0; /* unknown setup */ 332 333 sc->sc_flags |= STF_MOVED; 334 335 dq->dq_cdb = cmd; 336 dq->dq_bp = bp; 337 dq->dq_flags = 0; /* No Disconnect */ 338 339 if (screq(dq)) 340 ststart(unit); 341 } 342 343 int 344 ststart(unit) 345 register int unit; 346 { 347 register struct st_softc *sc = &st_softc[unit]; 348 register struct hp_device *hp = sc->sc_hd; 349 350 scstart(hp->hp_ctlr); 351 } 352 353 /* 354 * Interrupt 355 */ 356 357 char * 358 sense_key(key) 359 int key; 360 { 361 if (key == 0) 362 return("No Sense"); 363 else if (key == 2) 364 return("Not Ready"); 365 else if (key == 3) 366 return("Medium Error"); 367 else if (key == 4) 368 return("Hardware Error"); 369 else if (key == 5) 370 return("Illegal Request"); 371 else if (key == 6) 372 return("Unit Attention"); 373 else if (key == 7) 374 return("Data Protect"); 375 else if (key == 8) 376 return("No Data"); 377 else if (key == 11) 378 return("Aborted Command"); 379 else if (key == 13) 380 return("Volume Overflow"); 381 else 382 return("Unknown Error"); 383 } 384 385 int 386 stintr(unit, stat) 387 register int unit; 388 int stat; 389 { 390 register struct st_softc *sc = &st_softc[unit]; 391 register struct scsi_xsense *xp = (struct scsi_xsense *) xsense_buff; 392 register struct scsi_queue *dq = &sc->sc_dq; 393 register struct buf *bp = dq->dq_bp; 394 int ctlr = dq->dq_ctlr; 395 int slave = dq->dq_slave; 396 397 if (bp->b_flags & B_READ) { 398 st_iostat[unit].imin = min(dq->dq_imin, st_iostat[unit].imin); 399 if (dq->dq_imax > st_iostat[unit].imax) { 400 st_iostat[unit].imax = dq->dq_imax; 401 #ifdef ST_IOSTAT 402 printf("stintr: st%d INPUT MAX = %d, MIN = %d\n", 403 unit, st_iostat[unit].imax, st_iostat[unit].imin); 404 #endif 405 } 406 } else { 407 st_iostat[unit].omin = min(dq->dq_omin, st_iostat[unit].omin); 408 if (dq->dq_omax > st_iostat[unit].omax) { 409 st_iostat[unit].omax = dq->dq_omax; 410 #ifdef ST_IOSTAT 411 printf("stintr: st%d OUTPUT MAX = %d, MIN = %d\n", 412 unit, st_iostat[unit].omax, st_iostat[unit].omin); 413 #endif 414 } 415 } 416 if (stat < 0) { 417 bp->b_flags |= B_ERROR; 418 bp->b_error = EIO; 419 goto done; 420 } 421 422 switch (stat) { 423 /* scsi command completed ok */ 424 case 0: 425 bp->b_resid = 0; 426 break; 427 428 /* more status */ 429 case STS_CHECKCOND: 430 scsi_request_sense(ctlr, slave, 0, xp, 8); 431 #ifdef DEBUG 432 printf("stintr: xsense_buff[0] = 0x%s\n", hexstr(xsense_buff[0], 2)); 433 printf("stintr: xsense_buff[2] = 0x%s\n", hexstr(xsense_buff[2], 2)); 434 printf("stintr: Sense Key = [%s]\n", sense_key(xp->key)); 435 #endif 436 if (xp->valid) { 437 bp->b_resid = (u_long)((xp->info1 << 24) | 438 (xp->info2 << 16) | 439 (xp->info3 << 8) | 440 (xp->info4)); 441 bp->b_resid <<= DEV_BSHIFT; 442 } 443 444 if (xp->filemark) { /* End of File */ 445 tprintf(sc->sc_ctty, "st%d: End of File\n", unit); 446 bp->b_flags |= B_ERROR; 447 bp->b_error = EIO; 448 break; 449 } 450 451 if (xp->key) { 452 tprintf(sc->sc_ctty, "st%d: %s\n", unit, sense_key(xp->key)); 453 bp->b_flags |= B_ERROR; 454 bp->b_error = EIO; 455 break; 456 } 457 458 if (xp->eom) { /* End of TAPE */ 459 tprintf(sc->sc_ctty, "st%d: End of Tape\n", unit); 460 bp->b_flags |= B_ERROR; 461 bp->b_error = ENOSPC; 462 break; 463 } 464 465 tprintf(sc->sc_ctty, "st%d: unknown scsi error\n", unit); 466 bp->b_flags |= B_ERROR; 467 bp->b_error = EIO; 468 break; 469 470 default: 471 printf("st%d: stintr unknown stat 0x%x\n", unit, stat); 472 break; 473 } 474 475 done: 476 sttab[unit].b_errcnt = 0; 477 sttab[unit].b_actf = bp->b_actf; 478 479 bp->b_resid = 0; 480 481 biodone(bp); 482 483 scfree(&sc->sc_dq); 484 485 if (sttab[unit].b_actf) { 486 stustart(unit); 487 } else { 488 sttab[unit].b_active = 0; 489 } 490 } 491 492 493 /* 494 * RAW Device Routines 495 */ 496 497 498 stread(dev, uio) 499 dev_t dev; 500 struct uio *uio; 501 { 502 int unit = stunit(dev); 503 504 return(physio(ststrategy, &stbuf[unit], dev, B_READ, minphys, uio)); 505 } 506 507 stwrite(dev, uio) 508 dev_t dev; 509 struct uio *uio; 510 { 511 int unit = stunit(dev); 512 513 return(physio(ststrategy, &stbuf[unit], dev, B_WRITE, minphys, uio)); 514 } 515 516 int 517 stioctl(dev, cmd, data, flag, p) 518 dev_t dev; 519 int cmd; 520 caddr_t data; 521 int flag; 522 struct proc *p; 523 { 524 return(ENXIO); 525 } 526 527 struct scsi_fmt_cdb st_cmd; 528 529 st_rewind(dev) 530 dev_t dev; 531 { 532 register int unit = stunit(dev); 533 register struct st_softc *sc = &st_softc[unit]; 534 register struct scsi_fmt_cdb *cdb = &st_cmd; 535 register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff; 536 int ctlr, slave, stat; 537 int retry = 9; 538 539 ctlr = sc->sc_hd->hp_ctlr; 540 slave = sc->sc_hd->hp_slave; 541 542 cdb->len = 6; 543 544 cdb->cdb[0] = CMD_REWIND; 545 546 cdb->cdb[1] = 1; /* command finished soon */ 547 548 cdb->cdb[2] = 0; 549 cdb->cdb[3] = 0; 550 cdb->cdb[4] = 0; 551 552 cdb->cdb[5] = 0; /* unknown setup */ 553 554 rewind: 555 stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0); 556 557 if (stat == 0) { 558 return(1); 559 } else { 560 printf("st: rewind error\n"); 561 scsi_request_sense(ctlr, slave, 0, sp, 8); 562 printf("st: status = 0x%x, sens key = 0x%x\n", stat, sp->key); 563 564 if (retry > 0) { 565 DELAY(1000000); 566 retry--; 567 goto rewind; 568 } 569 570 return(0); 571 } 572 } 573 574 st_write_EOF(dev) 575 dev_t dev; 576 { 577 register int unit = stunit(dev); 578 register struct st_softc *sc = &st_softc[unit]; 579 register struct scsi_fmt_cdb *cdb = &st_cmd; 580 int ctlr, slave, stat; 581 int marks = 1; 582 583 ctlr = sc->sc_hd->hp_ctlr; 584 slave = sc->sc_hd->hp_slave; 585 586 cdb->len = 6; 587 588 cdb->cdb[0] = CMD_WRITE_FILEMARK; 589 590 cdb->cdb[1] = 0; 591 592 cdb->cdb[2] = 0; 593 cdb->cdb[3] = 0; 594 cdb->cdb[4] = marks; 595 596 cdb->cdb[5] = 0; /* unknown setup */ 597 598 stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0); 599 600 if (stat == 0) 601 return(1); 602 603 printf("st: write EOF error\n"); 604 605 return(0); 606 } 607 608 /* 609 * Dump 610 */ 611 612 int 613 stdump(dev) 614 dev_t dev; 615 { 616 } 617 #endif 618