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