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