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