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