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