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