|
|
1.1 ! root 1: /* ! 2: * @(#)sd.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc. ! 3: */ ! 4: #include <sys/param.h> ! 5: #include <sys/inode.h> ! 6: #include <sun/dklabel.h> ! 7: #include <sun/dkio.h> ! 8: #include <sys/buf.h> ! 9: #include <sundev/screg.h> ! 10: #include <sundev/sireg.h> ! 11: #include <sundev/scsi.h> ! 12: #include <machine/sunromvec.h> ! 13: #include <machine/idprom.h> ! 14: #include "saio.h" ! 15: #include "param.h" ! 16: ! 17: /* For RAM-based code, print detailed error messages */ ! 18: #if !defined(SDBOOT) && !defined(BOOTBLOCK) ! 19: #define SDERRORS ! 20: #endif ! 21: ! 22: /* ! 23: * Scsi disk parameter block ! 24: */ ! 25: struct sdparam { ! 26: int sd_target; ! 27: int sd_unit; ! 28: int sd_boff; ! 29: #ifdef SUN3 ! 30: int sd_ha_type; ! 31: #endif ! 32: struct saioreq subsip[1]; /* Sip for host adapter */ ! 33: }; ! 34: ! 35: /* ! 36: * Record an error message from scsi ! 37: */ ! 38: #define DEBUG FIXME ! 39: ! 40: #if (!defined(SDBOOT)) & !defined(STBOOT) & !defined(DEBUG) ! 41: ! 42: #define sc_error(msg) scerrmsg = msg ! 43: #define DEFERRED_ERRORS ! 44: extern char *scerrmsg; ! 45: ! 46: #else ! 47: ! 48: extern sc_error(); /* It's in sc.c */ ! 49: #undef DEFERRED_ERRORS ! 50: ! 51: #endif ! 52: ! 53: /* ! 54: * Our DMA space ! 55: */ ! 56: struct sddma { ! 57: char buffer[MAXBSIZE]; ! 58: struct dk_label xlabel[1]; ! 59: }; ! 60: ! 61: #define SDBUF (((struct sddma *)sip->si_dmaaddr)->buffer) ! 62: #define label (((struct sddma *)sip->si_dmaaddr)->xlabel) ! 63: ! 64: /* ! 65: * What resources we need to run ! 66: */ ! 67: struct devinfo sdinfo = { ! 68: 0, /* No device to map in */ ! 69: sizeof (struct sddma), ! 70: sizeof (struct sdparam), ! 71: 0, /* Dummy devices */ ! 72: 0, /* Dummy devices */ ! 73: MAP_MAINMEM, ! 74: MAXBSIZE, /* transfer size */ ! 75: }; ! 76: ! 77: /* ! 78: * The interfaces we export ! 79: */ ! 80: extern int xxprobe(), xxboot(); ! 81: int sdopen(), sdclose(), sdstrategy(); ! 82: ! 83: struct boottab sddriver = { ! 84: "sd", xxprobe, xxboot, ! 85: sdopen, sdclose, sdstrategy, ! 86: "sd: Adaptec SCSI disk", &sdinfo ! 87: }; ! 88: ! 89: #ifndef BOOTBLOCK ! 90: ! 91: /* ! 92: * Test routine for isspinning() to see if SCSI disk is running. ! 93: */ ! 94: sdspin(sip, dummy) ! 95: struct saioreq *sip; ! 96: int dummy; ! 97: { ! 98: ! 99: #ifdef lint ! 100: dummy = dummy; ! 101: #endif lint ! 102: sip->si_bn = 0; ! 103: sip->si_cc = 0; ! 104: sip->si_ma = 0; ! 105: return (sdcmd (SC_TEST_UNIT_READY, sip, 0)); ! 106: } ! 107: #endif ! 108: ! 109: #ifdef SUN3 ! 110: /* ! 111: * Determine type of host adaptor interface, si or sc. ! 112: * Returns 1 if si host adaptor and 0 if sc host adaptor. ! 113: */ ! 114: sd_probe(sip) ! 115: struct saioreq *sip; ! 116: { ! 117: if (siprobe(sip)) { ! 118: return (1); ! 119: } else { ! 120: return (0); ! 121: } ! 122: } ! 123: #endif ! 124: ! 125: /* ! 126: * Open the SCSI Disk controller ! 127: */ ! 128: sdopen(sip) ! 129: register struct saioreq *sip; ! 130: { ! 131: register struct sdparam *sdp; ! 132: register short *sp, sum; ! 133: register int count, r; ! 134: ! 135: sdp = (struct sdparam *)sip->si_devdata; ! 136: bzero( (char *)sdp, (sizeof (struct sdparam))); ! 137: ! 138: /* ! 139: * Open the host adapter ! 140: */ ! 141: *sdp->subsip = *sip; /* Initialize sub-sip */ ! 142: #ifdef SUN3 ! 143: { ! 144: extern struct boottab scdriver; ! 145: extern struct boottab sidriver; ! 146: ! 147: /* FIXME, find out which scsi interface to use */ ! 148: if (sd_probe(sip)) { ! 149: sdp->sd_ha_type = 1; ! 150: ! 151: /* FIXME, must vector thru table */ ! 152: sdp->subsip->si_boottab = &sidriver; ! 153: } else { ! 154: sdp->sd_ha_type = 0; ! 155: ! 156: /* FIXME, must vector thru table */ ! 157: sdp->subsip->si_boottab = &scdriver; ! 158: } ! 159: ! 160: } ! 161: #endif ! 162: #ifdef SUN2 ! 163: { ! 164: extern struct boottab scdriver; ! 165: ! 166: sdp->subsip->si_boottab = &scdriver; ! 167: } ! 168: #endif ! 169: sdp->subsip->si_unit = sip->si_unit >> 2; /* Target number */ ! 170: r = devopen(sdp->subsip); ! 171: if (r < 0) return r; ! 172: ! 173: sdp->sd_unit = sip->si_unit & 0x03; /* Logical unit number */ ! 174: ! 175: #ifndef BOOTBLOCK ! 176: /* ! 177: * Check that the disk is up and running... ! 178: */ ! 179: switch (isspinning(sdspin, (char *)sip, 0)) { ! 180: ! 181: default: /* Error from sdspin */ ! 182: case 0: /* Disk still not ready */ ! 183: /* isspinning has already printed "Giving up..." */ ! 184: return (-1); ! 185: ! 186: case 1: ! 187: break; ! 188: ! 189: case 2: ! 190: DELAY(1000000); /* one second delay after spinup */ ! 191: break; ! 192: } ! 193: #endif ! 194: ! 195: /* ! 196: * Actually read the label ! 197: */ ! 198: label->dkl_magic = 0; ! 199: sip->si_ma = (char *)label; ! 200: sip->si_cc = SECSIZE; ! 201: sip->si_bn = 0; /* Read block #0 */ ! 202: if (sdcmd(SC_READ, sip, 1) <= 0) { ! 203: return (-1); ! 204: } ! 205: if (chklabel(label)) ! 206: return -1; ! 207: sdp->sd_boff = (unsigned short)(label->dkl_map[sip->si_boff].dkl_cylno) ! 208: * (unsigned short)(label->dkl_nhead * label->dkl_nsect); ! 209: return (0); ! 210: } ! 211: ! 212: /* ! 213: * Execute reads or writes for the outside world. ! 214: */ ! 215: sdstrategy(sip, rw) ! 216: struct saioreq *sip; ! 217: register int rw; ! 218: { ! 219: rw = sdcmd(rw == WRITE ? SC_WRITE : SC_READ, sip, 1); ! 220: if (rw < 0) ! 221: rw = 0; ! 222: return rw; ! 223: } ! 224: ! 225: /* ! 226: * Internal interface to the disk command set ! 227: * ! 228: * Returns the character count read (or 1 if count==0) for success, ! 229: * returns 0 for failure, or -1 for severe unretryable failure. ! 230: */ ! 231: int ! 232: sdcmd(cmd, sip, errprint) ! 233: int cmd; ! 234: register struct saioreq *sip; ! 235: int errprint; ! 236: { ! 237: int blkno, acount; ! 238: register char *buf; ! 239: register struct sdparam *sdp; ! 240: struct scsi_cdb cdb, scdb; ! 241: struct scsi_scb scb, sscb; ! 242: register int retry, r, i, count; ! 243: ! 244: blkno = sip->si_bn; ! 245: acount = sip->si_cc; ! 246: buf = sip->si_ma; ! 247: sdp = (struct sdparam *)sip->si_devdata; ! 248: ! 249: if (cmd == SC_WRITE) ! 250: bcopy(buf, SDBUF, (unsigned)acount); ! 251: ! 252: /* set up cdb */ ! 253: bzero((char *) &cdb, sizeof cdb); ! 254: cdb.cmd = cmd; ! 255: cdb.lun = sdp->sd_unit; ! 256: blkno += sdp->sd_boff; ! 257: cdbaddr(&cdb, blkno); ! 258: count = (acount + SECSIZE -1) & ~(SECSIZE-1); ! 259: cdb.count = count / SECSIZE; ! 260: retry = 0; ! 261: do { ! 262: sdp->subsip->si_cc = count; ! 263: sdp->subsip->si_ma = SDBUF; ! 264: #ifdef SUN3 ! 265: if (sdp->sd_ha_type) ! 266: r = sidoit(&cdb, &scb, sdp->subsip); ! 267: else ! 268: #endif ! 269: r = scdoit(&cdb, &scb, sdp->subsip); ! 270: if (r < 0) ! 271: return -1; /* Major SCSI bus error, already printed */ ! 272: if (scb.chk) { ! 273: bzero((char *) &scdb, sizeof scdb); ! 274: scdb.cmd = SC_REQUEST_SENSE; ! 275: scdb.lun = sdp->sd_unit; ! 276: scdb.count = sizeof (struct scsi_sense); ! 277: sdp->subsip->si_cc = scdb.count; ! 278: sdp->subsip->si_ma = SDBUF; ! 279: #ifdef SUN3 ! 280: if (sdp->sd_ha_type) ! 281: i = sidoit(&scdb, &sscb, sdp->subsip); ! 282: else ! 283: #endif ! 284: i = scdoit(&scdb, &sscb, sdp->subsip); ! 285: if (i >= 4) { /* all the sense Adaptec gives us */ ! 286: #ifndef DEFERRED_ERRORS ! 287: if (errprint) sd_pr_sense(SDBUF, i); ! 288: #endif ! 289: continue; ! 290: } else { /* can't get sense, give up */ ! 291: if (errprint) { ! 292: printf("sd: scsi %s\n", ! 293: #ifdef DEFERRED_ERRORS ! 294: scerrmsg ? scerrmsg : ! 295: #endif ! 296: "sense failed"); ! 297: } ! 298: return (0); ! 299: } ! 300: } else if (scb.busy) { ! 301: sc_error("disk busy"); ! 302: DELAY(100000); ! 303: continue; ! 304: } ! 305: if (r != count) { ! 306: #ifndef DEFERRED_ERRORS ! 307: if (errprint) ! 308: printf("sd: dma count is %d wanted %d\n", ! 309: r, count); ! 310: #endif ! 311: continue; ! 312: } ! 313: if (cmd == SC_READ) ! 314: bcopy(SDBUF, buf, (unsigned)acount); ! 315: #ifdef DEFERRED_ERRORS ! 316: scerrmsg = 0; ! 317: #endif ! 318: return (count ? count : 1); ! 319: } while (retry++ < 16); ! 320: #ifdef DEFERRED_ERRORS ! 321: if (errprint) { ! 322: if (scb.chk) { ! 323: sd_pr_sense(SDBUF, i); ! 324: } else if (scerrmsg) { ! 325: printf("sd: scsi %s\n", scerrmsg); ! 326: } else if (r != count) { ! 327: printf("sd: dma count is %d wanted %d\n", r, count); ! 328: } else { ! 329: /* we should never get this far */ ! 330: printf("sd: retry count exceeded\n"); ! 331: } ! 332: } ! 333: #endif ! 334: return (0); ! 335: } ! 336: ! 337: #ifdef SDERRORS ! 338: char *class_00_errors[] = { ! 339: "No sense", ! 340: "No index signal", ! 341: "No seek complete", ! 342: "Write fault", ! 343: "Drive not ready", ! 344: "Drive not selected", ! 345: "No track 00", ! 346: "Multiple drives selected", ! 347: "No address acknowledged", ! 348: "Media not loaded", ! 349: "Insufficient capacity", ! 350: }; ! 351: ! 352: char *class_01_errors[] = { ! 353: "I.D. CRC error", ! 354: "Unrecoverable data error", ! 355: "I.D. address mark not found", ! 356: "Data address mark not found", ! 357: "Record not found", ! 358: "Seek error", ! 359: "DMA timeout error", ! 360: "Write protected", ! 361: "Correctable data check", ! 362: "Bad block found", ! 363: "Interleave error", ! 364: "Data transfer incomplete", ! 365: "Unformatted or bad format on drive", ! 366: "Self test failed", ! 367: "Defective track (media errors)", ! 368: }; ! 369: ! 370: char *class_02_errors[] = { ! 371: "Invalid command", ! 372: "Illegal block address", ! 373: "Aborted", ! 374: "Volume overflow", ! 375: }; ! 376: ! 377: char **sc_errors[] = { ! 378: class_00_errors, ! 379: class_01_errors, ! 380: class_02_errors, ! 381: 0, 0, 0, 0, ! 382: }; ! 383: ! 384: int sc_errct[] = { ! 385: sizeof class_00_errors / sizeof (char *), ! 386: sizeof class_01_errors / sizeof (char *), ! 387: sizeof class_02_errors / sizeof (char *), ! 388: 0, 0, 0, 0, ! 389: }; ! 390: ! 391: char *sc_sense7_keys [] = { ! 392: "No sense", ! 393: "Recoverable error", ! 394: "Not ready", ! 395: "Media error", ! 396: "Hardware error", ! 397: "Illegal request", ! 398: "Media change", ! 399: "Write protect", ! 400: "Diagnostic unique", ! 401: "Vendor unique", ! 402: "Power up failed", ! 403: "Aborted command", ! 404: "Equal", ! 405: "Volume overflow", ! 406: }; ! 407: #endif SDERRORS ! 408: ! 409: /* ! 410: * Print out sense info. ! 411: */ ! 412: sd_pr_sense(sp, len) ! 413: register unsigned char *sp; ! 414: register int len; ! 415: { ! 416: ! 417: #ifndef SDERRORS ! 418: printf("sd: error"); ! 419: while (--len >= 0) { ! 420: printf(" %x", *sp++); ! 421: } ! 422: printf("\n"); ! 423: #else SDERRORS ! 424: #ifdef lint ! 425: len = len; /* Avoid spurious "len unused" messages */ ! 426: #endif lint ! 427: printf("sd: "); ! 428: if (((struct scsi_sense *)sp)->class <= 6) { ! 429: register struct scsi_sense *sense; ! 430: ! 431: sense = (struct scsi_sense *) sp; ! 432: if (sense->code < sc_errct[sense->class]) { ! 433: printf("%s", sc_errors[sense->class][sense->code]); ! 434: } else { ! 435: printf("error %x", *sp); ! 436: } ! 437: if (sense->adr_val) { ! 438: printf("- block no. %d", (sense->high_addr << 16) | ! 439: (sense->mid_addr << 8) | sense->low_addr); ! 440: } ! 441: } else { /* Sense class 7: the standardized one */ ! 442: register struct scsi_ext_sense *sense7; ! 443: ! 444: sense7 = (struct scsi_ext_sense *) sp; ! 445: if (sense7->fil_mk) { ! 446: printf("file mark "); ! 447: } ! 448: if (sense7->eom) { ! 449: printf("end of medium "); ! 450: } ! 451: if (sense7->key ! 452: < sizeof (sc_sense7_keys) / sizeof (sc_sense7_keys[0])) { ! 453: printf("%s", sc_sense7_keys[sense7->key]); ! 454: } else { ! 455: printf("sense key %x", sense7->key); ! 456: } ! 457: printf(" block no. %x", (sense7->info_1 << 24) | ! 458: (sense7->info_2 << 16) | (sense7->info_3 << 8) | ! 459: sense7->info_4); ! 460: } ! 461: printf("\n"); ! 462: #endif SDERRORS ! 463: } ! 464: ! 465: ! 466: /* ! 467: * Close scsi disk ! 468: * ! 469: * We must close the host adapter too. ! 470: */ ! 471: int ! 472: sdclose(sip) ! 473: struct saioreq *sip; ! 474: { ! 475: devclose(((struct sdparam *)sip->si_devdata)->subsip); ! 476: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.