1 /* 2 * Copyright (c) 1992 OMRON Corporation. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. 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 8.1 (Berkeley) 06/10/93 12 */ 13 14 /* 15 * st.c -- SCSI Disk Device Driver for LUNA-68K 16 * remaked by A.Fujita, MAR-22-1992 17 */ 18 19 /* 20 * SCSI CCS (Command Command Set) disk driver. 21 */ 22 #define NST 1 23 24 #include <sys/param.h> 25 #include <sys/mtio.h> 26 #include <luna68k/dev/scsireg.h> 27 #include <luna68k/stand/device.h> 28 29 extern int scsi_test_unit_rdy(); 30 extern int scsi_request_sense(); 31 extern int scsi_immed_command(); 32 33 extern int scgo(); 34 extern void scfree(); 35 36 int stinit(), ststrategy(), ststart(), stintr(); 37 38 struct driver stdriver = { 39 stinit, "st", ststart, (int (*)()) 0, stintr, (int (*)()) 0 40 }; 41 42 struct st_softc { 43 struct hp_device *sc_hd; 44 struct devqueue sc_dq; 45 int sc_flags; 46 short sc_type; /* drive type */ 47 short sc_punit; /* physical unit (scsi lun) */ 48 } st_softc[NST]; 49 50 /* softc flags */ 51 #define STF_ALIVE 0x0001 52 #define STF_OPEN 0x0002 53 #define STF_WMODE 0x0004 54 #define STF_WRTTN 0x0008 55 #define STF_CMD 0x0010 56 #define STF_LEOT 0x0020 57 #define STF_MOVED 0x0040 58 59 struct scsi_fmt_sense stsense[NST]; 60 61 #define stunit(x) (minor(x) & 3) 62 #define stpunit(x) ((x) & 7) 63 64 #define STDEV_NOREWIND 0x04 65 #define STDEV_HIDENSITY 0x08 66 #define STDEV_EXSFMK 0x10 67 #define STDEV_FIXEDBLK 0x20 68 69 #define b_lba b_resid 70 71 #define STRETRY 2 /* IO retry count */ 72 73 74 /* 75 * Initialize 76 */ 77 78 int 79 stinit(hd) 80 register struct hp_device *hd; 81 { 82 register struct st_softc *sc = &st_softc[hd->hp_unit]; 83 84 sc->sc_hd = hd; 85 sc->sc_punit = stpunit(hd->hp_flags); 86 sc->sc_type = stident(sc, hd); 87 if (sc->sc_type < 0) 88 return(0); 89 sc->sc_dq.dq_ctlr = hd->hp_ctlr; 90 sc->sc_dq.dq_unit = hd->hp_unit; 91 sc->sc_dq.dq_slave = hd->hp_slave; 92 sc->sc_dq.dq_driver = &stdriver; 93 sc->sc_flags = STF_ALIVE; 94 return(1); 95 } 96 97 static struct scsi_inquiry inqbuf; 98 static struct scsi_fmt_cdb inq = { 99 6, 100 CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 101 }; 102 103 int 104 stident(sc, hd) 105 struct st_softc *sc; 106 struct hp_device *hd; 107 { 108 char idstr[32]; 109 int unit; 110 register int ctlr, slave; 111 register int i, stat; 112 register int tries = 10; 113 114 ctlr = hd->hp_ctlr; 115 slave = hd->hp_slave; 116 unit = sc->sc_punit; 117 118 /* 119 * See if unit exists and is a disk then read block size & nblocks. 120 */ 121 while ((stat = scsi_immed_command(ctlr, slave, unit, 122 &inq, (u_char *)&inqbuf, sizeof(inqbuf))) != 0) { 123 if (stat < 0 || --tries < 0) 124 return (-1); 125 DELAY(1000); 126 } 127 128 if (stat) 129 return (-1); 130 131 switch (inqbuf.type) { 132 case 1: /* tape */ 133 break; 134 default: /* not a disk */ 135 return (-1); 136 } 137 138 bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 139 for (i = 27; i > 23; --i) 140 if (idstr[i] != ' ') 141 break; 142 idstr[i+1] = 0; 143 for (i = 23; i > 7; --i) 144 if (idstr[i] != ' ') 145 break; 146 idstr[i+1] = 0; 147 for (i = 7; i >= 0; --i) 148 if (idstr[i] != ' ') 149 break; 150 idstr[i+1] = 0; 151 printf("st%d: %s %s rev %s\n", hd->hp_unit, idstr, &idstr[8], 152 &idstr[24]); 153 154 return(inqbuf.type); 155 } 156 157 158 /* 159 * Open 160 */ 161 162 int 163 stopen(dev) 164 dev_t dev; 165 { 166 register int unit = stunit(dev); 167 register struct st_softc *sc = &st_softc[unit]; 168 169 if (unit >= NST || (sc->sc_flags & STF_ALIVE) == 0) 170 return(-1); 171 if (sc->sc_flags & STF_OPEN) 172 return(-1); 173 174 sc->sc_flags |= STF_OPEN; 175 sc->sc_flags |= STF_WMODE; 176 sc->sc_flags &= ~STF_MOVED; 177 178 return(0); 179 } 180 181 /*ARGSUSED*/ 182 stclose(dev) 183 dev_t dev; 184 { 185 register int unit = stunit(dev); 186 register struct st_softc *sc = &st_softc[unit]; 187 188 printf("st: sc->sc_flags = 0x%s\n", hexstr(sc->sc_flags, 8)); 189 190 if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) { 191 st_write_EOF(dev); 192 } 193 194 if ((minor(dev) & STDEV_NOREWIND) == 0) { 195 st_rewind(dev); 196 } 197 198 sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN); 199 200 return(0); 201 } 202 203 /* 204 * Strategy 205 */ 206 207 int 208 ststrategy() 209 { 210 } 211 212 int 213 ststart(unit) 214 register int unit; 215 { 216 } 217 218 /* 219 * Interrupt 220 */ 221 222 /* 223 * Return: 224 * 0 if not really an error 225 * <0 if we should do a retry 226 * >0 if a fatal error 227 */ 228 static int 229 sterror(unit, sc, hp, stat) 230 int unit, stat; 231 register struct st_softc *sc; 232 register struct hp_device *hp; 233 { 234 int cond = 1; 235 236 stsense[unit].status = stat; 237 if (stat & STS_CHECKCOND) { 238 struct scsi_xsense *sp; 239 240 scsi_request_sense(hp->hp_ctlr, hp->hp_slave, 241 sc->sc_punit, stsense[unit].sense, 242 sizeof(stsense[unit].sense)); 243 sp = (struct scsi_xsense *)stsense[unit].sense; 244 printf("st%d: scsi sense class %d, code %d", unit, 245 sp->class, sp->code); 246 if (sp->class == 7) { 247 printf(", key %d", sp->key); 248 if (sp->valid) 249 printf(", blk %d", *(int *)&sp->info1); 250 switch (sp->key) { 251 /* no sense, try again */ 252 case 0: 253 cond = -1; 254 break; 255 /* recovered error, not a problem */ 256 case 1: 257 cond = 0; 258 break; 259 } 260 } 261 printf("\n"); 262 } 263 return(cond); 264 } 265 266 int 267 stintr(unit, stat) 268 register int unit; 269 int stat; 270 { 271 } 272 273 274 /* 275 * RAW Device Routines 276 */ 277 278 char * 279 sense_key(key) 280 int key; 281 { 282 if (key == 0) 283 return("No Sense"); 284 else if (key == 2) 285 return("Not Ready"); 286 else if (key == 3) 287 return("Medium Error"); 288 else if (key == 4) 289 return("Hardware Error"); 290 else if (key == 5) 291 return("Illegal Request"); 292 else if (key == 6) 293 return("Unit Attention"); 294 else if (key == 7) 295 return("Data Protect"); 296 else if (key == 8) 297 return("No Data"); 298 else if (key == 11) 299 return("Aborted Command"); 300 else if (key == 13) 301 return("Volume Overflow"); 302 else 303 return("Unknown Error"); 304 } 305 306 static struct scsi_fmt_cdb st_cmd = { 6, 0, 0, 0, 0, 0, 0 }; 307 308 u_char sensebuf[8]; 309 310 int 311 stread(dev, buf, size) 312 dev_t dev; 313 char *buf; 314 int size; 315 { 316 register int unit = stunit(dev); 317 register struct st_softc *sc = &st_softc[unit]; 318 register struct scsi_fmt_cdb *cdb = &st_cmd; 319 register int nblk = size >> DEV_BSHIFT; 320 struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 321 int ctlr, slave, stat; 322 323 ctlr = sc->sc_hd->hp_ctlr; 324 slave = sc->sc_hd->hp_slave; 325 326 cdb->cdb[0] = CMD_READ; 327 cdb->cdb[1] = 1; /* unknown setup */ 328 329 cdb->cdb[2] = (nblk & 0xff0000) >> 16; 330 cdb->cdb[3] = (nblk & 0x00ff00) >> 8; 331 cdb->cdb[4] = (nblk & 0x0000ff); 332 333 cdb->cdb[5] = 0; /* unknown setup */ 334 335 stat = scsi_immed_command(ctlr, slave, 0, cdb, buf, size); 336 337 if (stat == 0) 338 return(size); 339 else { 340 scsi_request_sense(ctlr, slave, 0, sp, 8); 341 342 if (stat == STS_CHECKCOND) { 343 printf("stread: Sense Key = [%s]", sense_key(sp->key)); 344 if (sp->filemark) 345 printf(" [EOF]"); 346 if (sp->eom) 347 printf(" [EOM]"); 348 printf("\n"); 349 } 350 351 return(-1); 352 } 353 } 354 355 int 356 stwrite(dev, buf, size) 357 dev_t dev; 358 char *buf; 359 int size; 360 { 361 register int unit = stunit(dev); 362 register struct st_softc *sc = &st_softc[unit]; 363 register struct scsi_fmt_cdb *cdb = &st_cmd; 364 struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 365 register int nblk; 366 int ctlr, slave, stat; 367 368 nblk = size >> DEV_BSHIFT; 369 if (size % DEV_BSIZE) 370 nblk++; 371 size = nblk << DEV_BSHIFT; 372 373 ctlr = sc->sc_hd->hp_ctlr; 374 slave = sc->sc_hd->hp_slave; 375 376 sc->sc_flags |= STF_WRTTN; 377 378 cdb->cdb[0] = CMD_WRITE; 379 cdb->cdb[1] = 1; /* unknown setup */ 380 381 cdb->cdb[2] = (nblk & 0xff0000) >> 16; 382 cdb->cdb[3] = (nblk & 0x00ff00) >> 8; 383 cdb->cdb[4] = (nblk & 0x0000ff); 384 385 cdb->cdb[5] = 0; /* unknown setup */ 386 387 stat = scsi_immed_command(ctlr, slave, 0, cdb, buf, size); 388 389 if (stat == 0) 390 return(size); 391 else { 392 scsi_request_sense(ctlr, slave, 0, sp, 8); 393 394 if (stat == STS_CHECKCOND) { 395 printf("stwrite: Sense Key = [%s]", sense_key(sp->key)); 396 if (sp->eom) 397 printf(" [EOM]"); 398 printf("\n"); 399 } 400 401 return(-1); 402 } 403 } 404 405 int 406 stioctl(dev, cmd, data, flag, p) 407 dev_t dev; 408 int cmd; 409 caddr_t data; 410 int flag; 411 struct proc *p; 412 { 413 } 414 415 st_rewind(dev) 416 dev_t dev; 417 { 418 register int unit = stunit(dev); 419 register struct st_softc *sc = &st_softc[unit]; 420 register struct scsi_fmt_cdb *cdb = &st_cmd; 421 struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 422 int ctlr, slave, stat; 423 int retry = 5; 424 425 ctlr = sc->sc_hd->hp_ctlr; 426 slave = sc->sc_hd->hp_slave; 427 428 cdb->cdb[0] = CMD_REWIND; 429 cdb->cdb[1] = 1; /* command finished soon */ 430 431 cdb->cdb[2] = 0; 432 cdb->cdb[3] = 0; 433 cdb->cdb[4] = 0; 434 435 cdb->cdb[5] = 0; /* unknown setup */ 436 437 rewind: 438 stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0); 439 440 if (stat == 0) { 441 return(1); 442 } else { 443 scsi_request_sense(ctlr, slave, 0, sp, 8); 444 445 if (stat == STS_CHECKCOND) { 446 printf("st_rewind: Sense Key = [%s]", sense_key(sp->key)); 447 printf("\n"); 448 } 449 450 if (retry > 0) { 451 DELAY(1000000); 452 retry--; 453 goto rewind; 454 } 455 456 return(0); 457 } 458 } 459 460 st_write_EOF(dev) 461 dev_t dev; 462 { 463 register int unit = stunit(dev); 464 register struct st_softc *sc = &st_softc[unit]; 465 register struct scsi_fmt_cdb *cdb = &st_cmd; 466 int ctlr, slave, stat; 467 int marks = 1; 468 469 ctlr = sc->sc_hd->hp_ctlr; 470 slave = sc->sc_hd->hp_slave; 471 472 cdb->cdb[0] = CMD_WRITE_FILEMARK; 473 cdb->cdb[1] = 1; /* command finished soon */ 474 475 cdb->cdb[2] = (marks & 0xff0000) >> 16; 476 cdb->cdb[3] = (marks & 0x00ff00) >> 8; 477 cdb->cdb[4] = (marks & 0x0000ff); 478 479 cdb->cdb[5] = 0; /* unknown setup */ 480 481 stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0); 482 483 if (stat == 0) 484 return(1); 485 486 printf("st: write EOF error\n"); 487 488 return(0); 489 } 490 491 int 492 st_skip(dev) 493 dev_t dev; 494 { 495 register int unit = stunit(dev); 496 register struct st_softc *sc = &st_softc[unit]; 497 register struct scsi_fmt_cdb *cdb = &st_cmd; 498 register int nfmk = 1; 499 struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 500 int ctlr, slave, stat; 501 502 ctlr = sc->sc_hd->hp_ctlr; 503 slave = sc->sc_hd->hp_slave; 504 505 cdb->cdb[0] = CMD_SPACE; 506 cdb->cdb[1] = 1; /* it mean skip until EOF */ 507 508 cdb->cdb[2] = (nfmk & 0xff0000) >> 16; 509 cdb->cdb[3] = (nfmk & 0x00ff00) >> 8; 510 cdb->cdb[4] = (nfmk & 0x0000ff); 511 512 cdb->cdb[5] = 0; /* unknown setup */ 513 514 stat = scsi_immed_command(ctlr, slave, 0, cdb, 0, 0); 515 516 if (stat == 0) 517 return(0); 518 else { 519 scsi_request_sense(ctlr, slave, 0, sp, 8); 520 521 if (stat == STS_CHECKCOND) { 522 printf("st_skip: Sense Key = [%s]", sense_key(sp->key)); 523 if (sp->filemark) 524 printf(" [EOF]"); 525 if (sp->eom) 526 printf(" [EOM]"); 527 printf("\n"); 528 } 529 530 return(-1); 531 } 532 } 533 534 /* 535 * Dump 536 */ 537 538 int 539 stdump(dev) 540 dev_t dev; 541 { 542 } 543