sd.c revision 1.18.2.2 1 /*
2 * Written by Julian Elischer (julian (at) dialix.oz.au)
3 * for TRW Financial Systems for use under the MACH(2.5) operating system.
4 *
5 * TRW Financial Systems, in accordance with their agreement with Carnegie
6 * Mellon University, makes this software available to CMU to distribute
7 * or use in any manner that they see fit as long as this message is kept with
8 * the software. For this reason TFS also grants any other persons or
9 * organisations permission to use or modify this software.
10 *
11 * TFS supplies this software to be publicly redistributed
12 * on the understanding that TFS is not responsible for the correct
13 * functioning of this software in any circumstances.
14 *
15 * Ported to run under 386BSD by Julian Elischer (julian (at) dialix.oz.au) Sept 1992
16 *
17 * $Id: sd.c,v 1.18.2.2 1993/11/24 05:03:10 mycroft Exp $
18 */
19
20 #define NSD 8 /* XXX kluge */
21
22 #include <sys/types.h>
23 #include <sys/param.h>
24 #include <sys/dkbad.h>
25 #include <sys/systm.h>
26 #include <sys/conf.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/device.h>
35 #include <sys/disklabel.h>
36
37 #include <scsi/scsi_all.h>
38 #include <scsi/scsi_disk.h>
39 #include <scsi/scsiconf.h>
40
41 #ifdef DDB
42 int Debugger();
43 #else /* DDB */
44 #define Debugger()
45 #endif /* DDB */
46
47 #define PAGESIZ 4096
48 #define SECSIZE 512
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 #define WHOLE_DISK(unit) ( (unit << UNITSHIFT) + RAW_PART )
60
61 int sdgetdisklabel __P((unsigned char unit));
62 int sd_get_parms __P((int unit, int flags));
63 void dstrategy();
64 void sdstart();
65
66 struct scsi_device sd_switch =
67 {
68 NULL, /* Use default error handler */
69 sdstart, /* have a queue, served by this */
70 NULL, /* have no async handler */
71 NULL, /* Use default 'done' routine */
72 "sd",
73 0,
74 { 0, 0 }
75 };
76
77 int
78 sdnull()
79 {
80 printf("sdnull called ");
81 return 0;
82 }
83 void
84 sdnullattach()
85 {
86 printf("sdnullattach called ");
87 }
88
89 struct cfdriver sdcd =
90 { NULL, "sd", sdnull, sdnullattach, DV_DISK, 0 };
91
92 struct sd_data {
93 u_int32 flags;
94 #define SDINIT 0x04 /* device has been init'd */
95 #define SDHAVELABEL 0x10 /* have read the label */
96 #define SDDOSPART 0x20 /* Have read the DOS partition table */
97 #define SDWRITEPROT 0x40 /* Device in readonly mode (S/W) */
98 struct scsi_link *sc_link; /* contains our targ, lun etc. */
99 u_int32 ad_info; /* info about the adapter */
100 u_int32 cmdscount; /* cmds allowed outstanding by board */
101 boolean wlabel; /* label is writable */
102 struct disk_parms {
103 u_char heads; /* Number of heads */
104 u_int16 cyls; /* Number of cylinders */
105 u_char sectors; /*dubious *//* Number of sectors/track */
106 u_int16 secsiz; /* Number of bytes/sector */
107 u_int32 disksize; /* total number sectors */
108 } params;
109 struct disklabel disklabel;
110 #ifdef __NetBSD__
111 struct cpu_disklabel cpudisklabel;
112 #else
113 struct dos_partition dosparts[NDOSPART]; /* DOS view of disk */
114 #endif /* __NetBSD__ */
115 u_int32 partflags[MAXPARTITIONS]; /* per partition flags */
116 #define SDOPEN 0x01
117 u_int32 openparts; /* one bit for each open partition */
118 u_int32 sd_start_of_unix; /* unix vs dos partitions */
119 struct buf buf_queue;
120 u_int32 xfer_block_wait;
121 } *sd_data[NSD];
122
123 static u_int32 next_sd_unit = 0;
124
125 /*
126 * The routine called by the low level scsi routine when it discovers
127 * a device suitable for this driver.
128 */
129 int
130 sdattach(sc_link)
131 struct scsi_link *sc_link;
132 {
133 u_int32 unit;
134 struct sd_data *sd;
135 struct disk_parms *dp;
136
137 unit = next_sd_unit++;
138 SC_DEBUG(sc_link, SDEV_DB2, ("sdattach: "));
139 /*
140 * Check we have the resources for another drive
141 */
142 if (unit >= NSD) {
143 printf("Too many scsi disks..(%d > %d) reconfigure kernel\n",
144 (unit + 1), NSD);
145 return 0;
146 }
147 if (sd_data[unit]) {
148 printf("sd%d: unit already has storage allocated!\n", unit);
149 return 0;
150 }
151 sd = sd_data[unit] = malloc(sizeof(struct sd_data), M_DEVBUF, M_NOWAIT);
152 if (!sd) {
153 printf("malloc failed in sd.c\n");
154 return (0);
155 }
156 bzero(sd, sizeof(struct sd_data));
157
158 dp = &(sd->params);
159 /*
160 * Store information needed to contact our base driver
161 */
162 sd->sc_link = sc_link;
163 sc_link->device = &sd_switch;
164 sc_link->dev_unit = unit;
165
166 if (sd->sc_link->adapter->adapter_info) {
167 sd->ad_info = ((*(sd->sc_link->adapter->adapter_info)) (sc_link->adapter_softc));
168 sd->cmdscount = sd->ad_info & AD_INF_MAX_CMDS;
169 if (sd->cmdscount > SDOUTSTANDING) {
170 sd->cmdscount = SDOUTSTANDING;
171 }
172 } else {
173 sd->ad_info = 1;
174 sd->cmdscount = 1;
175 }
176 sc_link->opennings = sd->cmdscount;
177 /*
178 * Use the subdriver to request information regarding
179 * the drive. We cannot use interrupts yet, so the
180 * request must specify this.
181 */
182 sd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK);
183 printf("sd%d: %dMB (%d total sec), %d cyl, %d head, %d sec, bytes/sec %d\n",
184 unit,
185 dp->disksize / ((1024L * 1024L) / dp->secsiz),
186 dp->disksize,
187 dp->cyls,
188 dp->heads,
189 dp->sectors,
190 dp->secsiz);
191 sd->flags |= SDINIT;
192 return 0;
193 }
194
195 /*
196 * open the device. Make sure the partition info is a up-to-date as can be.
197 */
198 int
199 sdopen(dev)
200 int dev; /* XXX should be dev_t, but avoid promotion problems for now */
201 {
202 int errcode = 0;
203 u_int32 unit, part;
204 struct sd_data *sd;
205 struct scsi_link *sc_link;
206
207 unit = UNIT(dev);
208 part = PARTITION(dev);
209 sd = sd_data[unit];
210 /*
211 * Check the unit is legal
212 */
213 if (unit >= NSD) {
214 return (ENXIO);
215 }
216 /*
217 * Make sure the disk has been initialised
218 * At some point in the future, get the scsi driver
219 * to look for a new device if we are not initted
220 */
221 if ((!sd) || (!(sd->flags & SDINIT))) {
222 return (ENXIO);
223 }
224 sc_link = sd->sc_link;
225
226 SC_DEBUG(sc_link, SDEV_DB1,
227 ("sdopen: dev=0x%x (unit %d (of %d),partition %d)\n"
228 ,dev, unit, NSD, part));
229
230 /*
231 * "unit attention" errors should occur here if the
232 * drive has been restarted or the pack changed.
233 * just ingnore the result, it's a decoy instruction
234 * The error code will act on the error though
235 * and invalidate any media information we had.
236 */
237 scsi_test_unit_ready(sc_link, 0);
238
239 /*
240 * If it's been invalidated, then forget the label
241 */
242 sc_link->flags |= SDEV_OPEN; /* unit attn becomes an err now */
243 if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
244 sd->flags &= ~SDHAVELABEL;
245
246 /*
247 * If somebody still has it open, then forbid re-entry.
248 */
249 if (sd->openparts) {
250 errcode = ENXIO;
251 goto bad;
252 }
253 }
254 /*
255 * In case it is a funny one, tell it to start
256 * not needed for most hard drives (ignore failure)
257 */
258 scsi_start_unit(sc_link, SCSI_ERR_OK | SCSI_SILENT);
259
260 /*
261 * Check that it is still responding and ok.
262 */
263 if (scsi_test_unit_ready(sc_link, 0)) {
264 SC_DEBUG(sc_link, SDEV_DB3, ("device not reponding\n"));
265 errcode = ENXIO;
266 goto bad;
267 }
268 SC_DEBUG(sc_link, SDEV_DB3, ("device ok\n"));
269
270 /*
271 * Load the physical device parameters
272 */
273 sd_get_parms(unit, 0); /* sets SDEV_MEDIA_LOADED */
274 if (sd->params.secsiz != SECSIZE) { /* XXX One day... */
275 printf("sd%d: Can't deal with %d bytes logical blocks\n",
276 unit, sd->params.secsiz);
277 Debugger();
278 errcode = ENXIO;
279 goto bad;
280 }
281 SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
282
283 /* Lock the pack in. */
284 scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
285
286 /*
287 * Load the partition info if not already loaded.
288 */
289 if ((errcode = sdgetdisklabel(unit)) && (part != RAW_PART)) {
290 goto bad;
291 }
292 SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel loaded "));
293 /*
294 * Check the partition is legal
295 */
296 if (part >= MAXPARTITIONS) {
297 errcode = ENXIO;
298 goto bad;
299 }
300 SC_DEBUG(sc_link, SDEV_DB3, ("partition ok"));
301
302 /*
303 * Check that the partition exists
304 */
305 if ((sd->disklabel.d_partitions[part].p_size == 0)
306 && (part != RAW_PART)) {
307 errcode = ENXIO;
308 goto bad;
309 }
310 sd->partflags[part] |= SDOPEN;
311 sd->openparts |= (1 << part);
312 SC_DEBUG(sc_link, SDEV_DB3, ("open\n"));
313 return 0;
314
315 bad:
316 if (!(sd->openparts)) {
317 scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
318 sc_link->flags &= ~SDEV_OPEN;
319 }
320 return errcode;
321 }
322
323 /*
324 * close the device.. only called if we are the LAST occurence of an open
325 * device. Convenient now but usually a pain.
326 */
327 int
328 sdclose(dev)
329 dev_t dev;
330 {
331 unsigned char unit, part;
332 struct sd_data *sd;
333
334 unit = UNIT(dev);
335 part = PARTITION(dev);
336 sd = sd_data[unit];
337 sd->partflags[part] &= ~SDOPEN;
338 sd->openparts &= ~(1 << part);
339 scsi_prevent(sd->sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
340 if (!(sd->openparts))
341 sd->sc_link->flags &= ~SDEV_OPEN;
342 return 0;
343 }
344
345 /*
346 * trim the size of the transfer if needed, called by physio
347 * basically the smaller of our max and the scsi driver's
348 * minphys (note we have no max)
349 *
350 * Trim buffer length if buffer-size is bigger than page size
351 */
352 void
353 sdminphys(bp)
354 struct buf *bp;
355 {
356 (*(sd_data[UNIT(bp->b_dev)]->sc_link->adapter->scsi_minphys)) (bp);
357 }
358
359 /*
360 * Actually translate the requested transfer into one the physical driver
361 * can understand. The transfer is described by a buf and will include
362 * only one physical transfer.
363 */
364 void
365 sdstrategy(bp)
366 struct buf *bp;
367 {
368 struct buf *dp;
369 u_int32 opri;
370 struct sd_data *sd;
371 u_int32 unit;
372
373 unit = UNIT((bp->b_dev));
374 sd = sd_data[unit];
375 SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdstrategy "));
376 SC_DEBUG(sd->sc_link, SDEV_DB1,
377 (" %d bytes @ blk%d\n", bp->b_bcount, bp->b_blkno));
378 sdminphys(bp);
379 /*
380 * If the device has been made invalid, error out
381 */
382 if (!(sd->sc_link->flags & SDEV_MEDIA_LOADED)) {
383 sd->flags &= ~SDHAVELABEL;
384 bp->b_error = EIO;
385 goto bad;
386 }
387 /*
388 * "soft" write protect check
389 */
390 if ((sd->flags & SDWRITEPROT) && (bp->b_flags & B_READ) == 0) {
391 bp->b_error = EROFS;
392 goto bad;
393 }
394 /*
395 * If it's a null transfer, return immediatly
396 */
397 if (bp->b_bcount == 0) {
398 goto done;
399 }
400 /*
401 * Decide which unit and partition we are talking about
402 * only raw is ok if no label
403 */
404 if (PARTITION(bp->b_dev) != RAW_PART) {
405 if (!(sd->flags & SDHAVELABEL)) {
406 bp->b_error = EIO;
407 goto bad;
408 }
409 /*
410 * do bounds checking, adjust transfer. if error, process.
411 * if end of partition, just return
412 */
413 if (bounds_check_with_label(bp, &sd->disklabel, sd->wlabel) <= 0)
414 goto done;
415 /* otherwise, process transfer request */
416 }
417 opri = splbio();
418 dp = &sd->buf_queue;
419
420 /*
421 * Place it in the queue of disk activities for this disk
422 */
423 disksort(dp, bp);
424
425 /*
426 * Tell the device to get going on the transfer if it's
427 * not doing anything, otherwise just wait for completion
428 */
429 sdstart(unit);
430
431 splx(opri);
432 bad:
433 bp->b_flags |= B_ERROR;
434 done:
435
436 /*
437 * Correctly set the buf to indicate a completed xfer
438 */
439 bp->b_resid = bp->b_bcount;
440 biodone(bp);
441 }
442
443 /*
444 * sdstart looks to see if there is a buf waiting for the device
445 * and that the device is not already busy. If both are true,
446 * It dequeues the buf and creates a scsi command to perform the
447 * transfer in the buf. The transfer request will call scsi_done
448 * on completion, which will in turn call this routine again
449 * so that the next queued transfer is performed.
450 * The bufs are queued by the strategy routine (sdstrategy)
451 *
452 * This routine is also called after other non-queued requests
453 * have been made of the scsi driver, to ensure that the queue
454 * continues to be drained.
455 *
456 * must be called at the correct (highish) spl level
457 * sdstart() is called at splbio from sdstrategy and scsi_done
458 */
459 void
460 sdstart(unit)
461 u_int32 unit;
462 {
463 register struct sd_data *sd = sd_data[unit];
464 register struct scsi_link *sc_link = sd->sc_link;
465 struct buf *bp = 0;
466 struct buf *dp;
467 struct scsi_rw_big cmd;
468 u_int32 blkno, nblk;
469 struct partition *p;
470
471 SC_DEBUG(sc_link, SDEV_DB2, ("sdstart "));
472 /*
473 * Check if the device has room for another command
474 */
475 while (sc_link->opennings) {
476
477 /*
478 * there is excess capacity, but a special waits
479 * It'll need the adapter as soon as we clear out of the
480 * way and let it run (user level wait).
481 */
482 if (sc_link->flags & SDEV_WAITING) {
483 return;
484 }
485 /*
486 * See if there is a buf with work for us to do..
487 */
488 dp = &sd->buf_queue;
489 if ((bp = dp->b_actf) == NULL) { /* yes, an assign */
490 return;
491 }
492 dp->b_actf = bp->av_forw;
493
494 /*
495 * If the device has become invalid, abort all the
496 * reads and writes until all files have been closed and
497 * re-openned
498 */
499 if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
500 sd->flags &= ~SDHAVELABEL;
501 goto bad;
502 }
503 /*
504 * We have a buf, now we know we are going to go through
505 * With this thing..
506 *
507 * First, translate the block to absolute
508 */
509 p = sd->disklabel.d_partitions + PARTITION(bp->b_dev);
510 blkno = bp->b_blkno + p->p_offset;
511 nblk = (bp->b_bcount + 511) >> 9;
512
513 /*
514 * Fill out the scsi command
515 */
516 bzero(&cmd, sizeof(cmd));
517 cmd.op_code = (bp->b_flags & B_READ)
518 ? READ_BIG : WRITE_BIG;
519 cmd.addr_3 = (blkno & 0xff000000) >> 24;
520 cmd.addr_2 = (blkno & 0xff0000) >> 16;
521 cmd.addr_1 = (blkno & 0xff00) >> 8;
522 cmd.addr_0 = blkno & 0xff;
523 cmd.length2 = (nblk & 0xff00) >> 8;
524 cmd.length1 = (nblk & 0xff);
525 /*
526 * Call the routine that chats with the adapter.
527 * Note: we cannot sleep as we may be an interrupt
528 */
529 if (scsi_scsi_cmd(sc_link,
530 (struct scsi_generic *) &cmd,
531 sizeof(cmd),
532 (u_char *) bp->b_un.b_addr,
533 bp->b_bcount,
534 SD_RETRIES,
535 10000,
536 bp,
537 SCSI_NOSLEEP | ((bp->b_flags & B_READ) ?
538 SCSI_DATA_IN : SCSI_DATA_OUT))
539 == SUCCESSFULLY_QUEUED) {
540 } else {
541 bad:
542 printf("sd%d: oops not queued", unit);
543 bp->b_error = EIO;
544 bp->b_flags |= B_ERROR;
545 biodone(bp);
546 }
547 }
548 }
549
550 /*
551 * Perform special action on behalf of the user
552 * Knows about the internals of this device
553 */
554 int
555 sdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
556 {
557 /* struct sd_cmd_buf *args; */
558 int error = 0;
559 unsigned char unit, part;
560 register struct sd_data *sd;
561
562 /*
563 * Find the device that the user is talking about
564 */
565 unit = UNIT(dev);
566 part = PARTITION(dev);
567 sd = sd_data[unit];
568 SC_DEBUG(sd->sc_link, SDEV_DB1, ("sdioctl (0x%x)", cmd));
569
570 /*
571 * If the device is not valid.. abandon ship
572 */
573 if (!(sd->sc_link->flags & SDEV_MEDIA_LOADED))
574 return (EIO);
575 switch (cmd) {
576
577 case DIOCSBAD:
578 error = EINVAL;
579 break;
580
581 case DIOCGDINFO:
582 *(struct disklabel *) addr = sd->disklabel;
583 break;
584
585 case DIOCGPART:
586 ((struct partinfo *) addr)->disklab = &sd->disklabel;
587 ((struct partinfo *) addr)->part =
588 &sd->disklabel.d_partitions[PARTITION(dev)];
589 break;
590
591 case DIOCSDINFO:
592 if ((flag & FWRITE) == 0)
593 error = EBADF;
594 else
595 error = setdisklabel(&sd->disklabel,
596 (struct disklabel *)addr,
597 /*(sd->flags & DKFL_BSDLABEL) ? sd->openparts : */ 0,
598 #ifdef __NetBSD__
599 &sd->cpudisklabel
600 #else
601 sd->dosparts
602 #endif
603 );
604 if (error == 0) {
605 sd->flags |= SDHAVELABEL;
606 }
607 break;
608
609 case DIOCWLABEL:
610 sd->flags &= ~SDWRITEPROT;
611 if ((flag & FWRITE) == 0)
612 error = EBADF;
613 else
614 sd->wlabel = *(boolean *) addr;
615 break;
616
617 case DIOCWDINFO:
618 sd->flags &= ~SDWRITEPROT;
619 if ((flag & FWRITE) == 0)
620 error = EBADF;
621 else {
622 error = setdisklabel(&sd->disklabel,
623 (struct disklabel *)addr,
624 /*(sd->flags & SDHAVELABEL) ? sd->openparts : */ 0,
625 #ifdef __NetBSD__
626 &sd->cpudisklabel
627 #else
628 sd->dosparts
629 #endif
630 );
631 if (!error) {
632 boolean wlab;
633
634 /* ok - write will succeed */
635 sd->flags |= SDHAVELABEL;
636
637 /* simulate opening partition 0 so write succeeds */
638 sd->openparts |= (1 << 0); /* XXX */
639 wlab = sd->wlabel;
640 sd->wlabel = 1;
641 error = writedisklabel(dev, sdstrategy,
642 &sd->disklabel,
643 &sd->cpudisklabel);
644 sd->wlabel = wlab;
645 }
646 }
647 break;
648
649 default:
650 if (part == RAW_PART)
651 error = scsi_do_ioctl(sd->sc_link, cmd, addr, flag);
652 else
653 error = ENOTTY;
654 break;
655 }
656 return error;
657 }
658
659 /*
660 * Load the label information on the named device
661 */
662 int
663 sdgetdisklabel(unsigned char unit)
664 {
665 char *errstring;
666 struct sd_data *sd = sd_data[unit];
667
668 /*
669 * If the inflo is already loaded, use it
670 */
671 if (sd->flags & SDHAVELABEL)
672 return (0);
673
674 bzero(&sd->disklabel, sizeof(struct disklabel));
675 /*
676 * make partition 3 the whole disk in case of failure then get pdinfo
677 * for historical reasons, make part a same as raw part
678 */
679 sd->disklabel.d_partitions[0].p_offset = 0;
680 sd->disklabel.d_partitions[0].p_size = sd->params.disksize;
681 sd->disklabel.d_partitions[RAW_PART].p_offset = 0;
682 sd->disklabel.d_partitions[RAW_PART].p_size = sd->params.disksize;
683 sd->disklabel.d_npartitions = MAXPARTITIONS;
684 sd->disklabel.d_secsize = SECSIZE; /* as long as it's not 0 */
685 sd->disklabel.d_ntracks = sd->params.heads;
686 sd->disklabel.d_nsectors = sd->params.sectors;
687 sd->disklabel.d_ncylinders = sd->params.cyls;
688 sd->disklabel.d_secpercyl = sd->params.heads * sd->params.sectors;
689 if (sd->disklabel.d_secpercyl == 0) {
690 sd->disklabel.d_secpercyl = 100;
691 /* as long as it's not 0 - readdisklabel divides by it (?) */
692 }
693 /*
694 * Call the generic disklabel extraction routine
695 */
696 if (errstring = readdisklabel(makedev(0, (unit << UNITSHIFT) + 3),
697 sdstrategy,
698 &sd->disklabel,
699 &sd->cpudisklabel)) {
700 printf("sd%d: %s\n", unit, errstring);
701 return ENXIO;
702 }
703 sd->flags |= SDHAVELABEL; /* WE HAVE IT ALL NOW */
704 return 0;
705 }
706
707 /*
708 * Find out from the device what it's capacity is
709 */
710 u_int32
711 sd_size(unit, flags)
712 int unit, flags;
713 {
714 struct scsi_read_cap_data rdcap;
715 struct scsi_read_capacity scsi_cmd;
716 u_int32 size;
717
718 /*
719 * make up a scsi command and ask the scsi driver to do
720 * it for you.
721 */
722 bzero(&scsi_cmd, sizeof(scsi_cmd));
723 scsi_cmd.op_code = READ_CAPACITY;
724
725 /*
726 * If the command works, interpret the result as a 4 byte
727 * number of blocks
728 */
729 if (scsi_scsi_cmd(sd_data[unit]->sc_link,
730 (struct scsi_generic *) &scsi_cmd,
731 sizeof(scsi_cmd),
732 (u_char *) & rdcap,
733 sizeof(rdcap),
734 SD_RETRIES,
735 2000,
736 NULL,
737 flags | SCSI_DATA_IN) != 0) {
738 printf("sd%d: could not get size\n", unit);
739 return (0);
740 } else {
741 size = rdcap.addr_0 + 1;
742 size += rdcap.addr_1 << 8;
743 size += rdcap.addr_2 << 16;
744 size += rdcap.addr_3 << 24;
745 }
746 return (size);
747 }
748
749 /*
750 * Tell the device to map out a defective block
751 */
752 int
753 sd_reassign_blocks(unit, block)
754 int unit, block;
755 {
756 struct scsi_reassign_blocks scsi_cmd;
757 struct scsi_reassign_blocks_data rbdata;
758
759 bzero(&scsi_cmd, sizeof(scsi_cmd));
760 bzero(&rbdata, sizeof(rbdata));
761 scsi_cmd.op_code = REASSIGN_BLOCKS;
762
763 rbdata.length_msb = 0;
764 rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
765 rbdata.defect_descriptor[0].dlbaddr_3 = ((block >> 24) & 0xff);
766 rbdata.defect_descriptor[0].dlbaddr_2 = ((block >> 16) & 0xff);
767 rbdata.defect_descriptor[0].dlbaddr_1 = ((block >> 8) & 0xff);
768 rbdata.defect_descriptor[0].dlbaddr_0 = ((block) & 0xff);
769
770 return (scsi_scsi_cmd(sd_data[unit]->sc_link,
771 (struct scsi_generic *) &scsi_cmd,
772 sizeof(scsi_cmd),
773 (u_char *) & rbdata,
774 sizeof(rbdata),
775 SD_RETRIES,
776 5000,
777 NULL,
778 SCSI_DATA_OUT));
779 }
780 #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
781
782 /*
783 * Get the scsi driver to send a full inquiry to the
784 * device and use the results to fill out the disk
785 * parameter structure.
786 */
787 int
788 sd_get_parms(unit, flags)
789 int unit, flags;
790 {
791 struct sd_data *sd = sd_data[unit];
792 struct disk_parms *disk_parms = &sd->params;
793 struct scsi_mode_sense scsi_cmd;
794 struct scsi_mode_sense_data {
795 struct scsi_mode_header header;
796 struct blk_desc blk_desc;
797 union disk_pages pages;
798 } scsi_sense;
799 u_int32 sectors;
800
801 /*
802 * First check if we have it all loaded
803 */
804 if (sd->flags & SDEV_MEDIA_LOADED)
805 return 0;
806
807 /*
808 * do a "mode sense page 4"
809 */
810 bzero(&scsi_cmd, sizeof(scsi_cmd));
811 scsi_cmd.op_code = MODE_SENSE;
812 scsi_cmd.page = 4;
813 scsi_cmd.length = 0x20;
814 /*
815 * If the command worked, use the results to fill out
816 * the parameter structure
817 */
818 if (scsi_scsi_cmd(sd->sc_link,
819 (struct scsi_generic *) &scsi_cmd,
820 sizeof(scsi_cmd),
821 (u_char *) & scsi_sense,
822 sizeof(scsi_sense),
823 SD_RETRIES,
824 2000,
825 NULL,
826 flags | SCSI_DATA_IN) != 0) {
827
828 printf("sd%d could not mode sense (4).", unit);
829 printf(" Using ficticious geometry\n");
830 /*
831 * use adaptec standard ficticious geometry
832 * this depends on which controller (e.g. 1542C is
833 * different. but we have to put SOMETHING here..)
834 */
835 sectors = sd_size(unit, flags);
836 disk_parms->heads = 64;
837 disk_parms->sectors = 32;
838 disk_parms->cyls = sectors / (64 * 32);
839 disk_parms->secsiz = SECSIZE;
840 disk_parms->disksize = sectors;
841 } else {
842
843 SC_DEBUG(sd->sc_link, SDEV_DB3,
844 ("%d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n",
845 _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2),
846 scsi_sense.pages.rigid_geometry.nheads,
847 b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp),
848 b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc),
849 b2tol(scsi_sense.pages.rigid_geometry.land_zone)));
850
851 /*
852 * KLUDGE!!(for zone recorded disks)
853 * give a number of sectors so that sec * trks * cyls
854 * is <= disk_size
855 * can lead to wasted space! THINK ABOUT THIS !
856 */
857 disk_parms->heads = scsi_sense.pages.rigid_geometry.nheads;
858 disk_parms->cyls = _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2);
859 disk_parms->secsiz = _3btol(scsi_sense.blk_desc.blklen);
860
861 sectors = sd_size(unit, flags);
862 disk_parms->disksize = sectors;
863 sectors /= (disk_parms->heads * disk_parms->cyls);
864 disk_parms->sectors = sectors; /* dubious on SCSI *//*XXX */
865 }
866 sd->sc_link->flags |= SDEV_MEDIA_LOADED;
867 return 0;
868 }
869
870 int
871 sdsize(dev_t dev)
872 {
873 u_int32 unit = UNIT(dev), part = PARTITION(dev), val;
874 struct sd_data *sd;
875
876 if (unit >= NSD)
877 return -1;
878
879 sd = sd_data[unit];
880 if (!sd)
881 return -1;
882 if ((sd->flags & SDINIT) == 0)
883 return -1;
884 if (sd == 0 || (sd->flags & SDHAVELABEL) == 0) {
885 val = sdopen(MAKESDDEV(major(dev), unit, RAW_PART), FREAD, S_IFBLK, 0);
886 if (val != 0)
887 return -1;
888 }
889 if (sd->flags & SDWRITEPROT)
890 return -1;
891
892 return (int)sd->disklabel.d_partitions[part].p_size;
893 }
894
895
896 #define SCSIDUMP 1
897 #undef SCSIDUMP
898 #define NOT_TRUSTED 1
899
900 #ifdef SCSIDUMP
901 #include <vm/vm.h>
902
903 static struct scsi_xfer sx;
904 #define MAXTRANSFER 8 /* 1 page at a time */
905
906 /*
907 * dump all of physical memory into the partition specified, starting
908 * at offset 'dumplo' into the partition.
909 */
910 int
911 sddump(dev_t dev)
912 { /* dump core after a system crash */
913 register struct sd_data *sd; /* disk unit to do the IO */
914 int32 num; /* number of sectors to write */
915 u_int32 unit, part;
916 int32 blkoff, blknum, blkcnt = MAXTRANSFER;
917 int32 nblocks;
918 char *addr;
919 struct scsi_rw_big cmd;
920 extern int Maxmem;
921 static int sddoingadump = 0;
922 #define MAPTO CADDR1
923 extern caddr_t MAPTO; /* map the page we are about to write, here */
924 struct scsi_xfer *xs = &sx;
925 int retval;
926 int c;
927
928 addr = (char *) 0; /* starting address */
929
930 /* toss any characters present prior to dump */
931 while ((c = sgetc(1)) && (c != 0x100)); /*syscons and pccons differ */
932
933 /* size of memory to dump */
934 num = Maxmem;
935 unit = UNIT(dev); /* eventually support floppies? */
936 part = PARTITION(dev); /* file system */
937 /* check for acceptable drive number */
938 if (unit >= NSD)
939 return (ENXIO); /* 31 Jul 92 */
940
941 sd = sd_data[unit];
942 if (!sd)
943 return (ENXIO);
944 /* was it ever initialized etc. ? */
945 if (!(sd->flags & SDINIT))
946 return (ENXIO);
947 if (sd->sc_link->flags & SDEV_MEDIA_LOADED != SDEV_MEDIA_LOADED)
948 return (ENXIO);
949 if (sd->flags & SDWRITEPROT)
950 return (ENXIO);
951
952 /* Convert to disk sectors */
953 num = (u_int32) num * NBPG / sd->disklabel.d_secsize;
954
955 /* check if controller active */
956 if (sddoingadump)
957 return (EFAULT);
958
959 nblocks = sd->disklabel.d_partitions[part].p_size;
960 blkoff = sd->disklabel.d_partitions[part].p_offset;
961
962 /* check transfer bounds against partition size */
963 if ((dumplo < 0) || ((dumplo + num) > nblocks))
964 return (EINVAL);
965
966 sddoingadump = 1;
967
968 blknum = dumplo + blkoff;
969 /* blkcnt = initialise_me; */
970 while (num > 0) {
971 pmap_enter(kernel_pmap,
972 MAPTO,
973 trunc_page(addr),
974 VM_PROT_READ,
975 TRUE);
976 #ifndef NOT_TRUSTED
977 /*
978 * Fill out the scsi command
979 */
980 bzero(&cmd, sizeof(cmd));
981 cmd.op_code = WRITE_BIG;
982 cmd.addr_3 = (blknum & 0xff000000) >> 24;
983 cmd.addr_2 = (blknum & 0xff0000) >> 16;
984 cmd.addr_1 = (blknum & 0xff00) >> 8;
985 cmd.addr_0 = blknum & 0xff;
986 cmd.length2 = (blkcnt & 0xff00) >> 8;
987 cmd.length1 = (blkcnt & 0xff);
988 /*
989 * Fill out the scsi_xfer structure
990 * Note: we cannot sleep as we may be an interrupt
991 * don't use scsi_scsi_cmd() as it may want
992 * to wait for an xs.
993 */
994 bzero(xs, sizeof(sx));
995 xs->flags |= SCSI_NOMASK | SCSI_NOSLEEP | INUSE;
996 xs->sc_link = sd->sc_link;
997 xs->retries = SD_RETRIES;
998 xs->timeout = 10000; /* 10000 millisecs for a disk ! */
999 xs->cmd = (struct scsi_generic *) &cmd;
1000 xs->cmdlen = sizeof(cmd);
1001 xs->resid = blkcnt * 512;
1002 xs->error = XS_NOERROR;
1003 xs->bp = 0;
1004 xs->data = (u_char *) MAPTO;
1005 xs->datalen = blkcnt * 512;
1006
1007 /*
1008 * Pass all this info to the scsi driver.
1009 */
1010 retval = (*(sd->sc_link->adapter->scsi_cmd)) (xs);
1011 switch (retval) {
1012 case SUCCESSFULLY_QUEUED:
1013 case HAD_ERROR:
1014 return (ENXIO); /* we said not to sleep! */
1015 case COMPLETE:
1016 break;
1017 default:
1018 return (ENXIO); /* we said not to sleep! */
1019 }
1020 #else /* NOT_TRUSTED */
1021 /* lets just talk about this first... */
1022 printf("sd%d: dump addr 0x%x, blk %d\n", unit, addr, blknum);
1023 #endif /* NOT_TRUSTED */
1024
1025 if ((unsigned) addr % (1024 * 1024) == 0)
1026 printf("%d ", num / 2048);
1027 /* update block count */
1028 num -= blkcnt;
1029 blknum += blkcnt;
1030 (int) addr += 512 * blkcnt;
1031
1032 /* operator aborting dump? */
1033 if ((c = sgetc(1)) && (c != 0x100))
1034 return (EINTR);
1035 }
1036 return (0);
1037 }
1038 #else /* SCSIDUMP */
1039 int
1040 sddump()
1041 {
1042 printf("\nsddump() -- not implemented\n");
1043 DELAY(60000000); /* 60 seconds */
1044 return -1;
1045 }
1046 #endif /* SCSIDUMP */
1047