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