|
|
1.1 ! root 1: /* ! 2: * Written by Julian Elischer ([email protected]) ! 3: * for TRW Financial Systems for use under the MACH(2.5) operating system. ! 4: * ! 5: * TRW Financial Systems, in accordance with their agreement with Carnegie ! 6: * Mellon University, makes this software available to CMU to distribute ! 7: * or use in any manner that they see fit as long as this message is kept with ! 8: * the software. For this reason TFS also grants any other persons or ! 9: * organisations permission to use or modify this software. ! 10: * ! 11: * TFS supplies this software to be publicly redistributed ! 12: * on the understanding that TFS is not responsible for the correct ! 13: * functioning of this software in any circumstances. ! 14: * ! 15: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE ! 16: * -------------------- ----- ---------------------- ! 17: * CURRENT PATCH LEVEL: 1 00098 ! 18: * -------------------- ----- ---------------------- ! 19: * ! 20: * 16 Feb 93 Julian Elischer ADDED for SCSI system ! 21: * ! 22: */ ! 23: ! 24: /* ! 25: * Ported to run under 386BSD by Julian Elischer ([email protected]) Sept 1992 ! 26: */ ! 27: ! 28: #define SPLSD splbio ! 29: #define ESUCCESS 0 ! 30: #include <sd.h> ! 31: #include <sys/types.h> ! 32: #include <sys/param.h> ! 33: #include <sys/dkbad.h> ! 34: #include <sys/systm.h> ! 35: #include <sys/conf.h> ! 36: #include <sys/file.h> ! 37: #include <sys/stat.h> ! 38: #include <sys/ioctl.h> ! 39: #include <sys/buf.h> ! 40: #include <sys/uio.h> ! 41: #include <sys/malloc.h> ! 42: #include <sys/errno.h> ! 43: #include <sys/disklabel.h> ! 44: #include <scsi/scsi_all.h> ! 45: #include <scsi/scsi_disk.h> ! 46: #include <scsi/scsiconf.h> ! 47: ! 48: long int sdstrats,sdqueues; ! 49: ! 50: ! 51: #ifdef DDB ! 52: int Debugger(); ! 53: #else ! 54: #define Debugger() ! 55: #endif ! 56: ! 57: ! 58: #define PAGESIZ 4096 ! 59: #define SECSIZE 512 ! 60: #define PDLOCATION 29 ! 61: #define BOOTRECORDSIGNATURE (0x55aa & 0x00ff) ! 62: #define SDOUTSTANDING 2 ! 63: #define SDQSIZE 4 ! 64: #define SD_RETRIES 4 ! 65: ! 66: #define MAKESDDEV(maj, unit, part) (makedev(maj,((unit<<3)+part))) ! 67: #define UNITSHIFT 3 ! 68: #define PARTITION(z) (minor(z) & 0x07) ! 69: #define RAW_PART 3 ! 70: #define UNIT(z) ( (minor(z) >> UNITSHIFT) ) ! 71: ! 72: #define WHOLE_DISK(unit) ( (unit << UNITSHIFT) + RAW_PART ) ! 73: ! 74: struct buf sd_buf_queue[NSD]; ! 75: int sd_done(); ! 76: int sdstrategy(); ! 77: ! 78: int sd_debug = 0; ! 79: ! 80: struct scsi_xfer *sd_free_xfer[NSD]; ! 81: int sd_xfer_block_wait[NSD]; ! 82: ! 83: struct sd_data ! 84: { ! 85: int flags; ! 86: #define SDVALID 0x02 /* PARAMS LOADED */ ! 87: #define SDINIT 0x04 /* device has been init'd */ ! 88: #define SDWAIT 0x08 /* device has someone waiting */ ! 89: #define SDHAVELABEL 0x10 /* have read the label */ ! 90: #define SDDOSPART 0x20 /* Have read the DOS partition table */ ! 91: #define SDWRITEPROT 0x40 /* Device in readonly mode (S/W)*/ ! 92: struct scsi_switch *sc_sw; /* address of scsi low level switch */ ! 93: int ctlr; /* so they know which one we want */ ! 94: int targ; /* our scsi target ID */ ! 95: int lu; /* out scsi lu */ ! 96: long int ad_info; /* info about the adapter */ ! 97: int cmdscount; /* cmds allowed outstanding by board*/ ! 98: int wlabel; /* label is writable */ ! 99: struct disk_parms ! 100: { ! 101: u_char heads; /* Number of heads */ ! 102: u_short cyls; /* Number of cylinders */ ! 103: u_char sectors;/*dubious*/ /* Number of sectors/track */ ! 104: u_short secsiz; /* Number of bytes/sector */ ! 105: u_long disksize; /* total number sectors */ ! 106: }params; ! 107: struct disklabel disklabel; ! 108: struct dos_partition dosparts[NDOSPART]; /* DOS view of disk */ ! 109: int partflags[MAXPARTITIONS]; /* per partition flags */ ! 110: #define SDOPEN 0x01 ! 111: int openparts; /* one bit for each open partition */ ! 112: unsigned int sd_start_of_unix; /* unix vs dos partitions */ ! 113: }sd_data[NSD]; ! 114: ! 115: ! 116: static int next_sd_unit = 0; ! 117: /***********************************************************************\ ! 118: * The routine called by the low level scsi routine when it discovers * ! 119: * A device suitable for this driver * ! 120: \***********************************************************************/ ! 121: ! 122: int sdattach(ctlr,targ,lu,scsi_switch) ! 123: struct scsi_switch *scsi_switch; ! 124: { ! 125: int unit,i; ! 126: unsigned char *tbl; ! 127: struct sd_data *sd; ! 128: struct disk_parms *dp; ! 129: long int ad_info; ! 130: struct scsi_xfer *sd_scsi_xfer; ! 131: ! 132: unit = next_sd_unit++; ! 133: sd = sd_data + unit; ! 134: dp = &(sd->params); ! 135: if(scsi_debug & PRINTROUTINES) printf("sdattach: "); ! 136: /*******************************************************\ ! 137: * Check we have the resources for another drive * ! 138: \*******************************************************/ ! 139: if( unit >= NSD) ! 140: { ! 141: printf("Too many scsi disks..(%d > %d) reconfigure kernel",(unit + 1),NSD); ! 142: return(0); ! 143: } ! 144: /*******************************************************\ ! 145: * Store information needed to contact our base driver * ! 146: \*******************************************************/ ! 147: sd->sc_sw = scsi_switch; ! 148: sd->ctlr = ctlr; ! 149: sd->targ = targ; ! 150: sd->lu = lu; ! 151: if(sd->sc_sw->adapter_info) ! 152: { ! 153: sd->ad_info = ( (*(sd->sc_sw->adapter_info))(ctlr)); ! 154: sd->cmdscount = sd->ad_info & AD_INF_MAX_CMDS; ! 155: if(sd->cmdscount > SDOUTSTANDING) ! 156: { ! 157: sd->cmdscount = SDOUTSTANDING; ! 158: } ! 159: } ! 160: else ! 161: { ! 162: sd->ad_info = 1; ! 163: sd->cmdscount = 1; ! 164: } ! 165: ! 166: i = sd->cmdscount; ! 167: sd_scsi_xfer = (struct scsi_xfer *)malloc(sizeof(struct scsi_xfer) * i ! 168: ,M_TEMP, M_NOWAIT); ! 169: while(i-- ) ! 170: { ! 171: sd_scsi_xfer->next = sd_free_xfer[unit]; ! 172: sd_free_xfer[unit] = sd_scsi_xfer; ! 173: sd_scsi_xfer++; ! 174: } ! 175: /*******************************************************\ ! 176: * Use the subdriver to request information regarding * ! 177: * the drive. We cannot use interrupts yet, so the * ! 178: * request must specify this. * ! 179: \*******************************************************/ ! 180: sd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK); ! 181: printf(" sd%d: %dMB, cyls %d, heads %d, secs %d, bytes/sec %d\n", ! 182: unit, ! 183: ( dp->cyls ! 184: * dp->heads ! 185: * dp->sectors ! 186: * dp->secsiz ! 187: ) ! 188: / (1024 * 1024), ! 189: dp->cyls, ! 190: dp->heads, ! 191: dp->sectors, ! 192: dp->secsiz); ! 193: /*******************************************************\ ! 194: * Set up the bufs for this device * ! 195: \*******************************************************/ ! 196: sd->flags |= SDINIT; ! 197: return; ! 198: ! 199: } ! 200: ! 201: ! 202: ! 203: /*******************************************************\ ! 204: * open the device. Make sure the partition info * ! 205: * is a up-to-date as can be. * ! 206: \*******************************************************/ ! 207: sdopen(dev) ! 208: { ! 209: int errcode = 0; ! 210: int unit, part; ! 211: struct disk_parms disk_parms; ! 212: struct sd_data *sd ; ! 213: ! 214: unit = UNIT(dev); ! 215: part = PARTITION(dev); ! 216: sd = sd_data + unit; ! 217: if(scsi_debug & (PRINTROUTINES | TRACEOPENS)) ! 218: printf("sdopen: dev=0x%x (unit %d (of %d),partition %d)\n" ! 219: , dev, unit, NSD, part); ! 220: /*******************************************************\ ! 221: * Check the unit is legal * ! 222: \*******************************************************/ ! 223: if ( unit >= NSD ) ! 224: { ! 225: return(ENXIO); ! 226: } ! 227: /*******************************************************\ ! 228: * Make sure the disk has been initialised * ! 229: * At some point in the future, get the scsi driver * ! 230: * to look for a new device if we are not initted * ! 231: \*******************************************************/ ! 232: if (! (sd->flags & SDINIT)) ! 233: { ! 234: return(ENXIO); ! 235: } ! 236: ! 237: /*******************************************************\ ! 238: * If it's been invalidated, and not everybody has * ! 239: * closed it then forbid re-entry. * ! 240: \*******************************************************/ ! 241: if ((! (sd->flags & SDVALID)) ! 242: && ( sd->openparts)) ! 243: return(ENXIO); ! 244: /*******************************************************\ ! 245: * Check that it is still responding and ok. * ! 246: * "unit attention errors should occur here if the drive * ! 247: * has been restarted or the pack changed * ! 248: \*******************************************************/ ! 249: ! 250: if(scsi_debug & TRACEOPENS) ! 251: printf("device is "); ! 252: if (sd_test_unit_ready(unit,0)) ! 253: { ! 254: if(scsi_debug & TRACEOPENS) printf("not reponding\n"); ! 255: return(ENXIO); ! 256: } ! 257: if(scsi_debug & TRACEOPENS) ! 258: printf("ok\n"); ! 259: /*******************************************************\ ! 260: * In case it is a funny one, tell it to start * ! 261: * not needed for most hard drives (ignore failure) * ! 262: \*******************************************************/ ! 263: sd_start_unit(unit,SCSI_ERR_OK|SCSI_SILENT); ! 264: if(scsi_debug & TRACEOPENS) ! 265: printf("started "); ! 266: /*******************************************************\ ! 267: * Load the physical device parameters * ! 268: \*******************************************************/ ! 269: sd_get_parms(unit, 0); /* sets SDVALID */ ! 270: if (sd->params.secsiz != SECSIZE) ! 271: { ! 272: printf("sd%d: Can't deal with %d bytes logical blocks\n" ! 273: ,unit, sd->params.secsiz); ! 274: Debugger(); ! 275: return(ENXIO); ! 276: } ! 277: if(scsi_debug & TRACEOPENS) ! 278: printf("Params loaded "); ! 279: /*******************************************************\ ! 280: * Load the partition info if not already loaded * ! 281: \*******************************************************/ ! 282: sd_prevent(unit,PR_PREVENT,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */ ! 283: if((errcode = sdgetdisklabel(unit)) && (part != RAW_PART)) ! 284: { ! 285: sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */ ! 286: return(errcode); ! 287: } ! 288: if(scsi_debug & TRACEOPENS) ! 289: printf("Disklabel loaded "); ! 290: /*******************************************************\ ! 291: * Check the partition is legal * ! 292: \*******************************************************/ ! 293: if ( part >= MAXPARTITIONS ) { ! 294: sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */ ! 295: return(ENXIO); ! 296: } ! 297: if(scsi_debug & TRACEOPENS) ! 298: printf("ok"); ! 299: /*******************************************************\ ! 300: * Check that the partition exists * ! 301: \*******************************************************/ ! 302: if (( sd->disklabel.d_partitions[part].p_size == 0 ) ! 303: && (part != RAW_PART)) ! 304: { ! 305: sd_prevent(unit,PR_ALLOW,SCSI_ERR_OK|SCSI_SILENT); /* who cares if it fails? */ ! 306: return(ENXIO); ! 307: } ! 308: sd->partflags[part] |= SDOPEN; ! 309: sd->openparts |= (1 << part); ! 310: if(scsi_debug & TRACEOPENS) ! 311: printf("open %d %d\n",sdstrats,sdqueues); ! 312: return(0); ! 313: } ! 314: ! 315: /*******************************************************\ ! 316: * Get ownership of a scsi_xfer * ! 317: * If need be, sleep on it, until it comes free * ! 318: \*******************************************************/ ! 319: struct scsi_xfer *sd_get_xs(unit,flags) ! 320: int flags; ! 321: int unit; ! 322: { ! 323: struct scsi_xfer *xs; ! 324: int s; ! 325: ! 326: if(flags & (SCSI_NOSLEEP | SCSI_NOMASK)) ! 327: { ! 328: if (xs = sd_free_xfer[unit]) ! 329: { ! 330: sd_free_xfer[unit] = xs->next; ! 331: xs->flags = 0; ! 332: } ! 333: } ! 334: else ! 335: { ! 336: s = SPLSD(); ! 337: while (!(xs = sd_free_xfer[unit])) ! 338: { ! 339: sd_xfer_block_wait[unit]++; /* someone waiting! */ ! 340: sleep((caddr_t)&sd_free_xfer[unit], PRIBIO+1); ! 341: sd_xfer_block_wait[unit]--; ! 342: } ! 343: sd_free_xfer[unit] = xs->next; ! 344: splx(s); ! 345: xs->flags = 0; ! 346: } ! 347: return(xs); ! 348: } ! 349: ! 350: /*******************************************************\ ! 351: * Free a scsi_xfer, wake processes waiting for it * ! 352: \*******************************************************/ ! 353: sd_free_xs(unit,xs,flags) ! 354: struct scsi_xfer *xs; ! 355: int unit; ! 356: int flags; ! 357: { ! 358: int s; ! 359: ! 360: if(flags & SCSI_NOMASK) ! 361: { ! 362: if (sd_xfer_block_wait[unit]) ! 363: { ! 364: printf("doing a wakeup from NOMASK mode\n"); ! 365: wakeup((caddr_t)&sd_free_xfer[unit]); ! 366: } ! 367: xs->next = sd_free_xfer[unit]; ! 368: sd_free_xfer[unit] = xs; ! 369: } ! 370: else ! 371: { ! 372: s = SPLSD(); ! 373: if (sd_xfer_block_wait[unit]) ! 374: wakeup((caddr_t)&sd_free_xfer[unit]); ! 375: xs->next = sd_free_xfer[unit]; ! 376: sd_free_xfer[unit] = xs; ! 377: splx(s); ! 378: } ! 379: } ! 380: ! 381: /*******************************************************\ ! 382: * trim the size of the transfer if needed, * ! 383: * called by physio * ! 384: * basically the smaller of our max and the scsi driver's* ! 385: * minphys (note we have no max) * ! 386: \*******************************************************/ ! 387: /* Trim buffer length if buffer-size is bigger than page size */ ! 388: void sdminphys(bp) ! 389: struct buf *bp; ! 390: { ! 391: (*(sd_data[UNIT(bp->b_dev)].sc_sw->scsi_minphys))(bp); ! 392: } ! 393: ! 394: /*******************************************************\ ! 395: * Actually translate the requested transfer into * ! 396: * one the physical driver can understand * ! 397: * The transfer is described by a buf and will include * ! 398: * only one physical transfer. * ! 399: \*******************************************************/ ! 400: ! 401: int sdstrategy(bp) ! 402: struct buf *bp; ! 403: { ! 404: struct buf *dp; ! 405: unsigned int opri; ! 406: struct sd_data *sd ; ! 407: int unit; ! 408: ! 409: sdstrats++; ! 410: unit = UNIT((bp->b_dev)); ! 411: sd = sd_data + unit; ! 412: if(scsi_debug & PRINTROUTINES) printf("\nsdstrategy "); ! 413: if(scsi_debug & SHOWREQUESTS) printf("sd%d: %d bytes @ blk%d\n", ! 414: unit,bp->b_bcount,bp->b_blkno); ! 415: sdminphys(bp); ! 416: /*******************************************************\ ! 417: * If the device has been made invalid, error out * ! 418: \*******************************************************/ ! 419: if(!(sd->flags & SDVALID)) ! 420: { ! 421: bp->b_error = EIO; ! 422: goto bad; ! 423: } ! 424: /*******************************************************\ ! 425: * "soft" write protect check * ! 426: \*******************************************************/ ! 427: if ((sd->flags & SDWRITEPROT) && (bp->b_flags & B_READ) == 0) { ! 428: bp->b_error = EROFS; ! 429: goto bad; ! 430: } ! 431: /*******************************************************\ ! 432: * If it's a null transfer, return immediatly * ! 433: \*******************************************************/ ! 434: if (bp->b_bcount == 0) ! 435: { ! 436: goto done; ! 437: } ! 438: ! 439: /*******************************************************\ ! 440: * Decide which unit and partition we are talking about * ! 441: * only raw is ok if no label * ! 442: \*******************************************************/ ! 443: if(PARTITION(bp->b_dev) != RAW_PART) ! 444: { ! 445: if (!(sd->flags & SDHAVELABEL)) ! 446: { ! 447: bp->b_error = EIO; ! 448: goto bad; ! 449: } ! 450: ! 451: /* ! 452: * do bounds checking, adjust transfer. if error, process. ! 453: * if end of partition, just return ! 454: */ ! 455: if (bounds_check_with_label(bp,&sd->disklabel,sd->wlabel) <= 0) ! 456: goto done; ! 457: /* otherwise, process transfer request */ ! 458: } ! 459: ! 460: opri = SPLSD(); ! 461: dp = &sd_buf_queue[unit]; ! 462: ! 463: /*******************************************************\ ! 464: * Place it in the queue of disk activities for this disk* ! 465: \*******************************************************/ ! 466: disksort(dp, bp); ! 467: ! 468: /*******************************************************\ ! 469: * Tell the device to get going on the transfer if it's * ! 470: * not doing anything, otherwise just wait for completion* ! 471: \*******************************************************/ ! 472: sdstart(unit); ! 473: ! 474: splx(opri); ! 475: return; ! 476: bad: ! 477: bp->b_flags |= B_ERROR; ! 478: done: ! 479: ! 480: /*******************************************************\ ! 481: * Correctly set the buf to indicate a completed xfer * ! 482: \*******************************************************/ ! 483: bp->b_resid = bp->b_bcount; ! 484: biodone(bp); ! 485: return; ! 486: } ! 487: ! 488: /***************************************************************\ ! 489: * sdstart looks to see if there is a buf waiting for the device * ! 490: * and that the device is not already busy. If both are true, * ! 491: * It deques the buf and creates a scsi command to perform the * ! 492: * transfer in the buf. The transfer request will call sd_done * ! 493: * on completion, which will in turn call this routine again * ! 494: * so that the next queued transfer is performed. * ! 495: * The bufs are queued by the strategy routine (sdstrategy) * ! 496: * * ! 497: * This routine is also called after other non-queued requests * ! 498: * have been made of the scsi driver, to ensure that the queue * ! 499: * continues to be drained. * ! 500: * * ! 501: * must be called at the correct (highish) spl level * ! 502: \***************************************************************/ ! 503: /* sdstart() is called at SPLSD from sdstrategy and sd_done*/ ! 504: sdstart(unit) ! 505: int unit; ! 506: { ! 507: int drivecount; ! 508: register struct buf *bp = 0; ! 509: register struct buf *dp; ! 510: struct scsi_xfer *xs; ! 511: struct scsi_rw_big cmd; ! 512: int blkno, nblk; ! 513: struct sd_data *sd = sd_data + unit; ! 514: struct partition *p ; ! 515: ! 516: if(scsi_debug & PRINTROUTINES) printf("sdstart%d ",unit); ! 517: /*******************************************************\ ! 518: * See if there is a buf to do and we are not already * ! 519: * doing one * ! 520: \*******************************************************/ ! 521: if(!sd_free_xfer[unit]) ! 522: { ! 523: return; /* none for us, unit already underway */ ! 524: } ! 525: ! 526: if(sd_xfer_block_wait[unit]) /* there is one, but a special waits */ ! 527: { ! 528: return; /* give the special that's waiting a chance to run */ ! 529: } ! 530: ! 531: ! 532: dp = &sd_buf_queue[unit]; ! 533: if ((bp = dp->b_actf) != NULL) /* yes, an assign */ ! 534: { ! 535: dp->b_actf = bp->av_forw; ! 536: } ! 537: else ! 538: { ! 539: return; ! 540: } ! 541: ! 542: xs=sd_get_xs(unit,0); /* ok we can grab it */ ! 543: xs->flags = INUSE; /* Now ours */ ! 544: /*******************************************************\ ! 545: * If the device has become invalid, abort all the * ! 546: * reads and writes until all files have been closed and * ! 547: * re-openned * ! 548: \*******************************************************/ ! 549: if(!(sd->flags & SDVALID)) ! 550: { ! 551: xs->error = XS_DRIVER_STUFFUP; ! 552: sd_done(unit,xs); /* clean up (calls sdstart) */ ! 553: return ; ! 554: } ! 555: /*******************************************************\ ! 556: * We have a buf, now we should move the data into * ! 557: * a scsi_xfer definition and try start it * ! 558: \*******************************************************/ ! 559: /*******************************************************\ ! 560: * First, translate the block to absolute * ! 561: \*******************************************************/ ! 562: p = sd->disklabel.d_partitions + PARTITION(bp->b_dev); ! 563: blkno = bp->b_blkno + p->p_offset; ! 564: nblk = (bp->b_bcount + 511) >> 9; ! 565: ! 566: /*******************************************************\ ! 567: * Fill out the scsi command * ! 568: \*******************************************************/ ! 569: bzero(&cmd, sizeof(cmd)); ! 570: cmd.op_code = (bp->b_flags & B_READ) ! 571: ? READ_BIG : WRITE_BIG; ! 572: cmd.addr_3 = (blkno & 0xff000000) >> 24; ! 573: cmd.addr_2 = (blkno & 0xff0000) >> 16; ! 574: cmd.addr_1 = (blkno & 0xff00) >> 8; ! 575: cmd.addr_0 = blkno & 0xff; ! 576: cmd.length2 = (nblk & 0xff00) >> 8; ! 577: cmd.length1 = (nblk & 0xff); ! 578: /*******************************************************\ ! 579: * Fill out the scsi_xfer structure * ! 580: * Note: we cannot sleep as we may be an interrupt * ! 581: \*******************************************************/ ! 582: xs->flags |= SCSI_NOSLEEP; ! 583: xs->adapter = sd->ctlr; ! 584: xs->targ = sd->targ; ! 585: xs->lu = sd->lu; ! 586: xs->retries = SD_RETRIES; ! 587: xs->timeout = 10000;/* 10000 millisecs for a disk !*/ ! 588: xs->cmd = (struct scsi_generic *)&cmd; ! 589: xs->cmdlen = sizeof(cmd); ! 590: xs->resid = bp->b_bcount; ! 591: xs->when_done = sd_done; ! 592: xs->done_arg = unit; ! 593: xs->done_arg2 = (int)xs; ! 594: xs->error = XS_NOERROR; ! 595: xs->bp = bp; ! 596: xs->data = (u_char *)bp->b_un.b_addr; ! 597: xs->datalen = bp->b_bcount; ! 598: /*******************************************************\ ! 599: * Pass all this info to the scsi driver. * ! 600: \*******************************************************/ ! 601: ! 602: ! 603: ! 604: if ( (*(sd->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED) ! 605: { ! 606: printf("sd%d: oops not queued",unit); ! 607: xs->error = XS_DRIVER_STUFFUP; ! 608: sd_done(unit,xs); /* clean up (calls sdstart) */ ! 609: } ! 610: sdqueues++; ! 611: } ! 612: ! 613: /*******************************************************\ ! 614: * This routine is called by the scsi interrupt when * ! 615: * the transfer is complete. ! 616: \*******************************************************/ ! 617: int sd_done(unit,xs) ! 618: int unit; ! 619: struct scsi_xfer *xs; ! 620: { ! 621: struct buf *bp; ! 622: int retval; ! 623: int retries = 0; ! 624: ! 625: if(scsi_debug & PRINTROUTINES) printf("sd_done%d ",unit); ! 626: if (! (xs->flags & INUSE)) ! 627: panic("scsi_xfer not in use!"); ! 628: if(bp = xs->bp) ! 629: { ! 630: switch(xs->error) ! 631: { ! 632: case XS_NOERROR: ! 633: bp->b_error = 0; ! 634: bp->b_resid = 0; ! 635: break; ! 636: ! 637: case XS_SENSE: ! 638: retval = (sd_interpret_sense(unit,xs)); ! 639: if(retval) ! 640: { ! 641: bp->b_flags |= B_ERROR; ! 642: bp->b_error = retval; ! 643: } ! 644: break; ! 645: ! 646: case XS_TIMEOUT: ! 647: printf("sd%d timeout\n",unit); ! 648: ! 649: case XS_BUSY: /* should retry */ /* how? */ ! 650: /************************************************/ ! 651: /* SHOULD put buf back at head of queue */ ! 652: /* and decrement retry count in (*xs) */ ! 653: /* HOWEVER, this should work as a kludge */ ! 654: /************************************************/ ! 655: if(xs->retries--) ! 656: { ! 657: xs->error = XS_NOERROR; ! 658: xs->flags &= ~ITSDONE; ! 659: if ( (*(sd_data[unit].sc_sw->scsi_cmd))(xs) ! 660: == SUCCESSFULLY_QUEUED) ! 661: { /* don't wake the job, ok? */ ! 662: return; ! 663: } ! 664: xs->flags |= ITSDONE; ! 665: } /* fall through */ ! 666: ! 667: case XS_DRIVER_STUFFUP: ! 668: bp->b_flags |= B_ERROR; ! 669: bp->b_error = EIO; ! 670: break; ! 671: default: ! 672: printf("sd%d: unknown error category from scsi driver\n" ! 673: ,unit); ! 674: } ! 675: biodone(bp); ! 676: sd_free_xs(unit,xs,0); ! 677: sdstart(unit); /* If there's anything waiting.. do it */ ! 678: } ! 679: else /* special has finished */ ! 680: { ! 681: wakeup(xs); ! 682: } ! 683: } ! 684: /*******************************************************\ ! 685: * Perform special action on behalf of the user * ! 686: * Knows about the internals of this device * ! 687: \*******************************************************/ ! 688: sdioctl(dev_t dev, int cmd, caddr_t addr, int flag) ! 689: { ! 690: /* struct sd_cmd_buf *args;*/ ! 691: int error = 0; ! 692: unsigned int opri; ! 693: unsigned char unit, part; ! 694: register struct sd_data *sd; ! 695: ! 696: ! 697: /*******************************************************\ ! 698: * Find the device that the user is talking about * ! 699: \*******************************************************/ ! 700: unit = UNIT(dev); ! 701: part = PARTITION(dev); ! 702: sd = &sd_data[unit]; ! 703: if(scsi_debug & PRINTROUTINES) printf("sdioctl%d ",unit); ! 704: ! 705: /*******************************************************\ ! 706: * If the device is not valid.. abandon ship * ! 707: \*******************************************************/ ! 708: if (!(sd_data[unit].flags & SDVALID)) ! 709: return(EIO); ! 710: switch(cmd) ! 711: { ! 712: ! 713: case DIOCSBAD: ! 714: error = EINVAL; ! 715: break; ! 716: ! 717: case DIOCGDINFO: ! 718: *(struct disklabel *)addr = sd->disklabel; ! 719: break; ! 720: ! 721: case DIOCGPART: ! 722: ((struct partinfo *)addr)->disklab = &sd->disklabel; ! 723: ((struct partinfo *)addr)->part = ! 724: &sd->disklabel.d_partitions[PARTITION(dev)]; ! 725: break; ! 726: ! 727: case DIOCSDINFO: ! 728: if ((flag & FWRITE) == 0) ! 729: error = EBADF; ! 730: else ! 731: error = setdisklabel(&sd->disklabel, ! 732: (struct disklabel *)addr, ! 733: /*(sd->flags & DKFL_BSDLABEL) ? sd->openparts : */0, ! 734: sd->dosparts); ! 735: if (error == 0) { ! 736: sd->flags |= SDHAVELABEL; ! 737: } ! 738: break; ! 739: ! 740: case DIOCWLABEL: ! 741: sd->flags &= ~SDWRITEPROT; ! 742: if ((flag & FWRITE) == 0) ! 743: error = EBADF; ! 744: else ! 745: sd->wlabel = *(int *)addr; ! 746: break; ! 747: ! 748: case DIOCWDINFO: ! 749: sd->flags &= ~SDWRITEPROT; ! 750: if ((flag & FWRITE) == 0) ! 751: error = EBADF; ! 752: else ! 753: { ! 754: if ((error = setdisklabel(&sd->disklabel ! 755: , (struct disklabel *)addr ! 756: , /*(sd->flags & SDHAVELABEL) ? sd->openparts :*/ 0 ! 757: , sd->dosparts)) == 0) ! 758: { ! 759: int wlab; ! 760: ! 761: sd->flags |= SDHAVELABEL; /* ok write will succeed */ ! 762: ! 763: /* simulate opening partition 0 so write succeeds */ ! 764: sd->openparts |= (1 << 0); /* XXX */ ! 765: wlab = sd->wlabel; ! 766: sd->wlabel = 1; ! 767: error = writedisklabel(dev, sdstrategy, ! 768: &sd->disklabel, sd->dosparts); ! 769: sd->wlabel = wlab; ! 770: } ! 771: } ! 772: break; ! 773: ! 774: ! 775: default: ! 776: error = ENOTTY; ! 777: break; ! 778: } ! 779: return (error); ! 780: } ! 781: ! 782: ! 783: /*******************************************************\ ! 784: * Load the label information on the named device * ! 785: \*******************************************************/ ! 786: int sdgetdisklabel(unit) ! 787: unsigned char unit; ! 788: { ! 789: /*unsigned int n, m;*/ ! 790: char *errstring; ! 791: struct dos_partition *dos_partition_p; ! 792: struct sd_data *sd = sd_data + unit; ! 793: ! 794: /*******************************************************\ ! 795: * If the inflo is already loaded, use it * ! 796: \*******************************************************/ ! 797: if(sd->flags & SDHAVELABEL) return(ESUCCESS); ! 798: ! 799: bzero(&sd->disklabel,sizeof(struct disklabel)); ! 800: /*******************************************************\ ! 801: * make partition 3 the whole disk in case of failure * ! 802: * then get pdinfo * ! 803: \*******************************************************/ ! 804: sd->disklabel.d_partitions[0].p_offset = 0; ! 805: sd->disklabel.d_partitions[0].p_size = sd->params.disksize; ! 806: sd->disklabel.d_partitions[RAW_PART].p_offset = 0; ! 807: sd->disklabel.d_partitions[RAW_PART].p_size = sd->params.disksize; ! 808: sd->disklabel.d_npartitions = MAXPARTITIONS; ! 809: sd->disklabel.d_secsize = 512; /* as long as it's not 0 */ ! 810: sd->disklabel.d_ntracks = sd->params.heads; ! 811: sd->disklabel.d_nsectors = sd->params.sectors; ! 812: sd->disklabel.d_ncylinders = sd->params.cyls; ! 813: sd->disklabel.d_secpercyl = sd->params.heads * sd->params.sectors; ! 814: if (sd->disklabel.d_secpercyl == 0) ! 815: { ! 816: sd->disklabel.d_secpercyl = 100; ! 817: /* as long as it's not 0 */ ! 818: /* readdisklabel divides by it */ ! 819: } ! 820: ! 821: /*******************************************************\ ! 822: * all the generic bisklabel extraction routine * ! 823: \*******************************************************/ ! 824: if(errstring = readdisklabel(makedev(0 ,(unit<<UNITSHIFT )+3) ! 825: , sdstrategy ! 826: , &sd->disklabel ! 827: , sd->dosparts ! 828: , 0 ! 829: , 0)) ! 830: { ! 831: printf("sd%d: %s\n",unit, errstring); ! 832: return(ENXIO); ! 833: } ! 834: /*******************************************************\ ! 835: * leave partition 2 "open" for raw I/O * ! 836: \*******************************************************/ ! 837: ! 838: sd->flags |= SDHAVELABEL; /* WE HAVE IT ALL NOW */ ! 839: return(ESUCCESS); ! 840: } ! 841: ! 842: /*******************************************************\ ! 843: * Find out from the device what it's capacity is * ! 844: \*******************************************************/ ! 845: sd_size(unit, flags) ! 846: { ! 847: struct scsi_read_cap_data rdcap; ! 848: struct scsi_read_capacity scsi_cmd; ! 849: int size; ! 850: ! 851: /*******************************************************\ ! 852: * make up a scsi command and ask the scsi driver to do * ! 853: * it for you. * ! 854: \*******************************************************/ ! 855: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 856: scsi_cmd.op_code = READ_CAPACITY; ! 857: ! 858: /*******************************************************\ ! 859: * If the command works, interpret the result as a 4 byte* ! 860: * number of blocks * ! 861: \*******************************************************/ ! 862: if (sd_scsi_cmd(unit, ! 863: &scsi_cmd, ! 864: sizeof(scsi_cmd), ! 865: &rdcap, ! 866: sizeof(rdcap), ! 867: 2000, ! 868: flags) != 0) ! 869: { ! 870: printf("could not get size of unit %d\n", unit); ! 871: return(0); ! 872: } else { ! 873: size = rdcap.addr_0 + 1 ; ! 874: size += rdcap.addr_1 << 8; ! 875: size += rdcap.addr_2 << 16; ! 876: size += rdcap.addr_3 << 24; ! 877: } ! 878: return(size); ! 879: } ! 880: ! 881: /*******************************************************\ ! 882: * Get scsi driver to send a "are you ready?" command * ! 883: \*******************************************************/ ! 884: sd_test_unit_ready(unit,flags) ! 885: int unit,flags; ! 886: { ! 887: struct scsi_test_unit_ready scsi_cmd; ! 888: ! 889: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 890: scsi_cmd.op_code = TEST_UNIT_READY; ! 891: ! 892: return (sd_scsi_cmd(unit, ! 893: &scsi_cmd, ! 894: sizeof(scsi_cmd), ! 895: 0, ! 896: 0, ! 897: 100000, ! 898: flags)); ! 899: } ! 900: ! 901: /*******************************************************\ ! 902: * Prevent or allow the user to remove the tape * ! 903: \*******************************************************/ ! 904: sd_prevent(unit,type,flags) ! 905: int unit,type,flags; ! 906: { ! 907: struct scsi_prevent scsi_cmd; ! 908: ! 909: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 910: scsi_cmd.op_code = PREVENT_ALLOW; ! 911: scsi_cmd.prevent=type; ! 912: return (sd_scsi_cmd(unit, ! 913: &scsi_cmd, ! 914: sizeof(scsi_cmd), ! 915: 0, ! 916: 0, ! 917: 5000, ! 918: flags) ); ! 919: } ! 920: /*******************************************************\ ! 921: * Get scsi driver to send a "start up" command * ! 922: \*******************************************************/ ! 923: sd_start_unit(unit,flags) ! 924: int unit,flags; ! 925: { ! 926: struct scsi_start_stop scsi_cmd; ! 927: ! 928: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 929: scsi_cmd.op_code = START_STOP; ! 930: scsi_cmd.start = 1; ! 931: ! 932: return (sd_scsi_cmd(unit, ! 933: &scsi_cmd, ! 934: sizeof(scsi_cmd), ! 935: 0, ! 936: 0, ! 937: 2000, ! 938: flags)); ! 939: } ! 940: ! 941: /*******************************************************\ ! 942: * Tell the device to map out a defective block * ! 943: \*******************************************************/ ! 944: sd_reassign_blocks(unit,block) ! 945: { ! 946: struct scsi_reassign_blocks scsi_cmd; ! 947: struct scsi_reassign_blocks_data rbdata; ! 948: ! 949: ! 950: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 951: bzero(&rbdata, sizeof(rbdata)); ! 952: scsi_cmd.op_code = REASSIGN_BLOCKS; ! 953: ! 954: rbdata.length_msb = 0; ! 955: rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]); ! 956: rbdata.defect_descriptor[0].dlbaddr_3 = ((block >> 24) & 0xff); ! 957: rbdata.defect_descriptor[0].dlbaddr_2 = ((block >> 16) & 0xff); ! 958: rbdata.defect_descriptor[0].dlbaddr_1 = ((block >> 8) & 0xff); ! 959: rbdata.defect_descriptor[0].dlbaddr_0 = ((block ) & 0xff); ! 960: ! 961: return(sd_scsi_cmd(unit, ! 962: &scsi_cmd, ! 963: sizeof(scsi_cmd), ! 964: &rbdata, ! 965: sizeof(rbdata), ! 966: 5000, ! 967: 0)); ! 968: } ! 969: ! 970: #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 ) ! 971: ! 972: /*******************************************************\ ! 973: * Get the scsi driver to send a full inquiry to the * ! 974: * device and use the results to fill out the disk * ! 975: * parameter structure. * ! 976: \*******************************************************/ ! 977: ! 978: int sd_get_parms(unit, flags) ! 979: { ! 980: struct sd_data *sd = sd_data + unit; ! 981: struct disk_parms *disk_parms = &sd->params; ! 982: struct scsi_mode_sense scsi_cmd; ! 983: struct scsi_mode_sense_data ! 984: { ! 985: struct scsi_mode_header header; ! 986: struct blk_desc blk_desc; ! 987: union disk_pages pages; ! 988: }scsi_sense; ! 989: int sectors; ! 990: ! 991: /*******************************************************\ ! 992: * First check if we have it all loaded * ! 993: \*******************************************************/ ! 994: if(sd->flags & SDVALID) return(0); ! 995: /*******************************************************\ ! 996: * First do a mode sense page 3 * ! 997: \*******************************************************/ ! 998: if (sd_debug) ! 999: { ! 1000: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1001: scsi_cmd.op_code = MODE_SENSE; ! 1002: scsi_cmd.page_code = 3; ! 1003: scsi_cmd.length = 0x24; ! 1004: /*******************************************************\ ! 1005: * do the command, but we don't need the results * ! 1006: * just print them for our interest's sake * ! 1007: \*******************************************************/ ! 1008: if (sd_scsi_cmd(unit, ! 1009: &scsi_cmd, ! 1010: sizeof(scsi_cmd), ! 1011: &scsi_sense, ! 1012: sizeof(scsi_sense), ! 1013: 2000, ! 1014: flags) != 0) ! 1015: { ! 1016: printf("could not mode sense (3) for unit %d\n", unit); ! 1017: return(ENXIO); ! 1018: } ! 1019: printf("unit %d: %d trk/zone, %d alt_sec/zone, %d alt_trk/zone, %d alt_trk/lun\n", ! 1020: unit, ! 1021: b2tol(scsi_sense.pages.disk_format.trk_z), ! 1022: b2tol(scsi_sense.pages.disk_format.alt_sec), ! 1023: b2tol(scsi_sense.pages.disk_format.alt_trk_z), ! 1024: b2tol(scsi_sense.pages.disk_format.alt_trk_v)); ! 1025: printf(" %d sec/trk, %d bytes/sec, %d interleave, %d %d bytes/log_blk\n", ! 1026: b2tol(scsi_sense.pages.disk_format.ph_sec_t), ! 1027: b2tol(scsi_sense.pages.disk_format.bytes_s), ! 1028: b2tol(scsi_sense.pages.disk_format.interleave), ! 1029: sd_size(unit, flags), ! 1030: _3btol(scsi_sense.blk_desc.blklen)); ! 1031: } ! 1032: ! 1033: ! 1034: /*******************************************************\ ! 1035: * do a "mode sense page 4" * ! 1036: \*******************************************************/ ! 1037: bzero(&scsi_cmd, sizeof(scsi_cmd)); ! 1038: scsi_cmd.op_code = MODE_SENSE; ! 1039: scsi_cmd.page_code = 4; ! 1040: scsi_cmd.length = 0x20; ! 1041: /*******************************************************\ ! 1042: * If the command worked, use the results to fill out * ! 1043: * the parameter structure * ! 1044: \*******************************************************/ ! 1045: if (sd_scsi_cmd(unit, ! 1046: &scsi_cmd, ! 1047: sizeof(scsi_cmd), ! 1048: &scsi_sense, ! 1049: sizeof(scsi_sense), ! 1050: 2000, ! 1051: flags) != 0) ! 1052: { ! 1053: printf("could not mode sense (4) for unit %d\n", unit); ! 1054: printf(" using ficticious geometry\n"); ! 1055: /* use adaptec standard ficticious geometry */ ! 1056: sectors = sd_size(unit, flags); ! 1057: disk_parms->heads = 64; ! 1058: disk_parms->sectors = 32; ! 1059: disk_parms->cyls = sectors/(64 * 32); ! 1060: disk_parms->secsiz = SECSIZE; ! 1061: } ! 1062: else ! 1063: { ! 1064: ! 1065: if (sd_debug) ! 1066: { ! 1067: printf(" %d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n", ! 1068: _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2), ! 1069: scsi_sense.pages.rigid_geometry.nheads, ! 1070: b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp), ! 1071: b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc), ! 1072: b2tol(scsi_sense.pages.rigid_geometry.land_zone)); ! 1073: } ! 1074: ! 1075: /*******************************************************\ ! 1076: * KLUDGE!!(for zone recorded disks) * ! 1077: * give a number of sectors so that sec * trks * cyls * ! 1078: * is <= disk_size * ! 1079: \*******************************************************/ ! 1080: disk_parms->heads = scsi_sense.pages.rigid_geometry.nheads; ! 1081: disk_parms->cyls = _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2); ! 1082: disk_parms->secsiz = _3btol(&scsi_sense.blk_desc.blklen); ! 1083: ! 1084: sectors = sd_size(unit, flags); ! 1085: sectors /= disk_parms->cyls; ! 1086: sectors /= disk_parms->heads; ! 1087: disk_parms->sectors = sectors; /* dubious on SCSI*/ ! 1088: } ! 1089: ! 1090: sd->flags |= SDVALID; ! 1091: return(0); ! 1092: } ! 1093: ! 1094: /*******************************************************\ ! 1095: * close the device.. only called if we are the LAST * ! 1096: * occurence of an open device * ! 1097: \*******************************************************/ ! 1098: sdclose(dev) ! 1099: dev_t dev; ! 1100: { ! 1101: unsigned char unit, part; ! 1102: unsigned int old_priority; ! 1103: ! 1104: unit = UNIT(dev); ! 1105: part = PARTITION(dev); ! 1106: sd_data[unit].partflags[part] &= ~SDOPEN; ! 1107: sd_data[unit].openparts &= ~(1 << part); ! 1108: if(sd_data[unit].openparts == 0) /* if all partitions closed */ ! 1109: { ! 1110: sd_prevent(unit,PR_ALLOW,SCSI_SILENT|SCSI_ERR_OK); ! 1111: } ! 1112: return(0); ! 1113: } ! 1114: ! 1115: /*******************************************************\ ! 1116: * ask the scsi driver to perform a command for us. * ! 1117: * Call it through the switch table, and tell it which * ! 1118: * sub-unit we want, and what target and lu we wish to * ! 1119: * talk to. Also tell it where to find the command * ! 1120: * how long int is. * ! 1121: * Also tell it where to read/write the data, and how * ! 1122: * long the data is supposed to be * ! 1123: \*******************************************************/ ! 1124: int sd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags) ! 1125: ! 1126: int unit,flags; ! 1127: struct scsi_generic *scsi_cmd; ! 1128: int cmdlen; ! 1129: int timeout; ! 1130: u_char *data_addr; ! 1131: int datalen; ! 1132: { ! 1133: struct scsi_xfer *xs; ! 1134: int retval; ! 1135: int s; ! 1136: struct sd_data *sd = sd_data + unit; ! 1137: ! 1138: if(scsi_debug & PRINTROUTINES) printf("\nsd_scsi_cmd%d ",unit); ! 1139: if(sd->sc_sw) /* If we have a scsi driver */ ! 1140: { ! 1141: xs = sd_get_xs(unit,flags); /* should wait unless booting */ ! 1142: if(!xs) ! 1143: { ! 1144: printf("sd_scsi_cmd%d: controller busy" ! 1145: " (this should never happen)\n",unit); ! 1146: return(EBUSY); ! 1147: } ! 1148: xs->flags |= INUSE; ! 1149: /*******************************************************\ ! 1150: * Fill out the scsi_xfer structure * ! 1151: \*******************************************************/ ! 1152: xs->flags |= flags; ! 1153: xs->adapter = sd->ctlr; ! 1154: xs->targ = sd->targ; ! 1155: xs->lu = sd->lu; ! 1156: xs->retries = SD_RETRIES; ! 1157: xs->timeout = timeout; ! 1158: xs->cmd = scsi_cmd; ! 1159: xs->cmdlen = cmdlen; ! 1160: xs->data = data_addr; ! 1161: xs->datalen = datalen; ! 1162: xs->resid = datalen; ! 1163: xs->when_done = (flags & SCSI_NOMASK) ! 1164: ?(int (*)())0 ! 1165: :sd_done; ! 1166: xs->done_arg = unit; ! 1167: xs->done_arg2 = (int)xs; ! 1168: retry: xs->error = XS_NOERROR; ! 1169: xs->bp = 0; ! 1170: retval = (*(sd->sc_sw->scsi_cmd))(xs); ! 1171: switch(retval) ! 1172: { ! 1173: case SUCCESSFULLY_QUEUED: ! 1174: s = splbio(); ! 1175: while(!(xs->flags & ITSDONE)) ! 1176: sleep(xs,PRIBIO+1); ! 1177: splx(s); ! 1178: ! 1179: case HAD_ERROR: ! 1180: /*printf("err = %d ",xs->error);*/ ! 1181: switch(xs->error) ! 1182: { ! 1183: case XS_NOERROR: ! 1184: retval = ESUCCESS; ! 1185: break; ! 1186: case XS_SENSE: ! 1187: retval = (sd_interpret_sense(unit,xs)); ! 1188: break; ! 1189: case XS_DRIVER_STUFFUP: ! 1190: retval = EIO; ! 1191: break; ! 1192: case XS_TIMEOUT: ! 1193: if(xs->retries-- ) ! 1194: { ! 1195: xs->flags &= ~ITSDONE; ! 1196: goto retry; ! 1197: } ! 1198: retval = EIO; ! 1199: break; ! 1200: case XS_BUSY: ! 1201: if(xs->retries-- ) ! 1202: { ! 1203: xs->flags &= ~ITSDONE; ! 1204: goto retry; ! 1205: } ! 1206: retval = EIO; ! 1207: break; ! 1208: default: ! 1209: retval = EIO; ! 1210: printf("sd%d: unknown error category from scsi driver\n" ! 1211: ,unit); ! 1212: } ! 1213: break; ! 1214: case COMPLETE: ! 1215: retval = ESUCCESS; ! 1216: break; ! 1217: case TRY_AGAIN_LATER: ! 1218: if(xs->retries-- ) ! 1219: { ! 1220: xs->flags &= ~ITSDONE; ! 1221: goto retry; ! 1222: } ! 1223: retval = EIO; ! 1224: break; ! 1225: default: ! 1226: retval = EIO; ! 1227: } ! 1228: sd_free_xs(unit,xs,flags); ! 1229: sdstart(unit); /* check if anything is waiting fr the xs */ ! 1230: } ! 1231: else ! 1232: { ! 1233: printf("sd%d: not set up\n",unit); ! 1234: return(EINVAL); ! 1235: } ! 1236: return(retval); ! 1237: } ! 1238: /***************************************************************\ ! 1239: * Look at the returned sense and act on the error and detirmine * ! 1240: * The unix error number to pass back... (0 = report no error) * ! 1241: \***************************************************************/ ! 1242: ! 1243: int sd_interpret_sense(unit,xs) ! 1244: int unit; ! 1245: struct scsi_xfer *xs; ! 1246: { ! 1247: struct scsi_sense_data *sense; ! 1248: int key; ! 1249: int silent; ! 1250: ! 1251: /***************************************************************\ ! 1252: * If the flags say errs are ok, then always return ok. * ! 1253: \***************************************************************/ ! 1254: if (xs->flags & SCSI_ERR_OK) return(ESUCCESS); ! 1255: silent = (xs->flags & SCSI_SILENT); ! 1256: ! 1257: sense = &(xs->sense); ! 1258: switch(sense->error_class) ! 1259: { ! 1260: case 7: ! 1261: { ! 1262: key=sense->ext.extended.sense_key; ! 1263: switch(key) ! 1264: { ! 1265: case 0x0: ! 1266: return(ESUCCESS); ! 1267: case 0x1: ! 1268: if(!silent) ! 1269: { ! 1270: printf("sd%d: soft error(corrected) ", unit); ! 1271: if(sense->valid) ! 1272: { ! 1273: printf("block no. %d (decimal)", ! 1274: (sense->ext.extended.info[0] <<24), ! 1275: (sense->ext.extended.info[1] <<16), ! 1276: (sense->ext.extended.info[2] <<8), ! 1277: (sense->ext.extended.info[3] )); ! 1278: } ! 1279: printf("\n"); ! 1280: } ! 1281: return(ESUCCESS); ! 1282: case 0x2: ! 1283: if(!silent)printf("sd%d: not ready\n ", ! 1284: unit); ! 1285: return(ENODEV); ! 1286: case 0x3: ! 1287: if(!silent) ! 1288: { ! 1289: printf("sd%d: medium error ", unit); ! 1290: if(sense->valid) ! 1291: { ! 1292: printf("block no. %d (decimal)", ! 1293: (sense->ext.extended.info[0] <<24), ! 1294: (sense->ext.extended.info[1] <<16), ! 1295: (sense->ext.extended.info[2] <<8), ! 1296: (sense->ext.extended.info[3] )); ! 1297: } ! 1298: printf("\n"); ! 1299: } ! 1300: return(EIO); ! 1301: case 0x4: ! 1302: if(!silent)printf("sd%d: non-media hardware failure\n ", ! 1303: unit); ! 1304: return(EIO); ! 1305: case 0x5: ! 1306: if(!silent)printf("sd%d: illegal request\n ", ! 1307: unit); ! 1308: return(EINVAL); ! 1309: case 0x6: ! 1310: /***********************************************\ ! 1311: * If we are not open, then this is not an error * ! 1312: * as we don't have state yet. Either way, make * ! 1313: * sure that we don't have any residual state * ! 1314: \***********************************************/ ! 1315: if(!silent)printf("sd%d: Unit attention.\n ", unit); ! 1316: sd_data[unit].flags &= ~(SDVALID | SDHAVELABEL); ! 1317: if (sd_data[unit].openparts) ! 1318: { ! 1319: return(EIO); ! 1320: } ! 1321: return(ESUCCESS); /* not an error if nothing's open */ ! 1322: case 0x7: ! 1323: if(!silent) ! 1324: { ! 1325: printf("sd%d: attempted protection violation ", ! 1326: unit); ! 1327: if(sense->valid) ! 1328: { ! 1329: printf("block no. %d (decimal)\n", ! 1330: (sense->ext.extended.info[0] <<24), ! 1331: (sense->ext.extended.info[1] <<16), ! 1332: (sense->ext.extended.info[2] <<8), ! 1333: (sense->ext.extended.info[3] )); ! 1334: } ! 1335: printf("\n"); ! 1336: } ! 1337: return(EACCES); ! 1338: case 0x8: ! 1339: if(!silent) ! 1340: { ! 1341: printf("sd%d: block wrong state (worm)\n ", ! 1342: unit); ! 1343: if(sense->valid) ! 1344: { ! 1345: printf("block no. %d (decimal)\n", ! 1346: (sense->ext.extended.info[0] <<24), ! 1347: (sense->ext.extended.info[1] <<16), ! 1348: (sense->ext.extended.info[2] <<8), ! 1349: (sense->ext.extended.info[3] )); ! 1350: } ! 1351: printf("\n"); ! 1352: } ! 1353: return(EIO); ! 1354: case 0x9: ! 1355: if(!silent)printf("sd%d: vendor unique\n", ! 1356: unit); ! 1357: return(EIO); ! 1358: case 0xa: ! 1359: if(!silent)printf("sd%d: copy aborted\n ", ! 1360: unit); ! 1361: return(EIO); ! 1362: case 0xb: ! 1363: if(!silent)printf("sd%d: command aborted\n ", ! 1364: unit); ! 1365: return(EIO); ! 1366: case 0xc: ! 1367: if(!silent) ! 1368: { ! 1369: printf("sd%d: search returned\n ", ! 1370: unit); ! 1371: if(sense->valid) ! 1372: { ! 1373: printf("block no. %d (decimal)\n", ! 1374: (sense->ext.extended.info[0] <<24), ! 1375: (sense->ext.extended.info[1] <<16), ! 1376: (sense->ext.extended.info[2] <<8), ! 1377: (sense->ext.extended.info[3] )); ! 1378: } ! 1379: printf("\n"); ! 1380: } ! 1381: return(ESUCCESS); ! 1382: case 0xd: ! 1383: if(!silent)printf("sd%d: volume overflow\n ", ! 1384: unit); ! 1385: return(ENOSPC); ! 1386: case 0xe: ! 1387: if(!silent) ! 1388: { ! 1389: printf("sd%d: verify miscompare\n ", ! 1390: unit); ! 1391: if(sense->valid) ! 1392: { ! 1393: printf("block no. %d (decimal)\n", ! 1394: (sense->ext.extended.info[0] <<24), ! 1395: (sense->ext.extended.info[1] <<16), ! 1396: (sense->ext.extended.info[2] <<8), ! 1397: (sense->ext.extended.info[3] )); ! 1398: } ! 1399: printf("\n"); ! 1400: } ! 1401: return(EIO); ! 1402: case 0xf: ! 1403: if(!silent)printf("sd%d: unknown error key\n ", ! 1404: unit); ! 1405: return(EIO); ! 1406: } ! 1407: break; ! 1408: } ! 1409: case 0: ! 1410: case 1: ! 1411: case 2: ! 1412: case 3: ! 1413: case 4: ! 1414: case 5: ! 1415: case 6: ! 1416: { ! 1417: if(!silent)printf("sd%d: error class %d code %d\n", ! 1418: unit, ! 1419: sense->error_class, ! 1420: sense->error_code); ! 1421: if(sense->valid) ! 1422: if(!silent)printf("block no. %d (decimal)\n", ! 1423: (sense->ext.unextended.blockhi <<16), ! 1424: + (sense->ext.unextended.blockmed <<8), ! 1425: + (sense->ext.unextended.blocklow )); ! 1426: } ! 1427: return(EIO); ! 1428: } ! 1429: } ! 1430: ! 1431: ! 1432: ! 1433: ! 1434: int ! 1435: sdsize(dev_t dev) ! 1436: { ! 1437: int unit = UNIT(dev), part = PARTITION(dev), val; ! 1438: struct sd_data *sd; ! 1439: ! 1440: if (unit >= NSD) ! 1441: return(-1); ! 1442: ! 1443: sd = &sd_data[unit]; ! 1444: if((sd->flags & SDINIT) == 0) return(-1); ! 1445: if (sd == 0 || (sd->flags & SDHAVELABEL) == 0) ! 1446: val = sdopen (MAKESDDEV(major(dev), unit, RAW_PART), FREAD, S_IFBLK, 0); ! 1447: if ( val != 0 || sd->flags & SDWRITEPROT) ! 1448: return (-1); ! 1449: ! 1450: return((int)sd->disklabel.d_partitions[part].p_size); ! 1451: } ! 1452: ! 1453: sddump() ! 1454: { ! 1455: printf("sddump() -- not implemented\n"); ! 1456: return(-1); ! 1457: } ! 1458: ! 1459: ! 1460: ! 1461: ! 1462:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.