FreeBSD/Linux Kernel Cross Reference
sys/scsi/od.c
1 /*
2 * Copyright (c) 1995,1996 Shunsuke Akiyama. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Shunsuke Akiyama.
15 * 4. Neither the name of the author nor the names of any co-contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY Shunsuke Akiyama AND CONTRIBUTORS ``AS IS''
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL Shunsuke Akiyama OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $FreeBSD: src/sys/scsi/od.c,v 1.22.2.4 1999/09/05 08:21:36 peter Exp $
32 */
33
34 /*
35 * Compile option defines:
36 */
37
38 /*
39 * If drive returns sense key as 0x02 with vendor specific additional
40 * sense code (ASC) and additional sense code qualifier (ASCQ), or
41 * illegal ASC and ASCQ. This cause an error (NOT READY) and retrying.
42 * To suppress this, uncomment following.
43 * Or put "options OD_BOGUS_NOT_READY" entry into your kernel
44 * configuration file.
45 *
46 #define OD_BOGUS_NOT_READY
47 */
48
49 /*
50 * For an automatic spindown, try this. Again, preferrably as an
51 * option in your config file.
52 * WARNING! Use at your own risk. Joerg's ancient SONY SMO drive
53 * groks it fine, while Shunsuke's Fujitsu chokes on it and times
54 * out.
55 #define OD_AUTO_TURNOFF
56 */
57
58 #include "opt_bounce.h"
59 #include "opt_scsi.h"
60 #include "opt_od.h"
61
62 #define SPLOD splbio
63 #include <sys/types.h>
64 #include <sys/param.h>
65 #include <sys/kernel.h>
66 #include <sys/dkbad.h>
67 #include <sys/systm.h>
68 #include <sys/conf.h>
69 #include <sys/file.h>
70 #include <sys/stat.h>
71 #include <sys/ioctl.h>
72 #include <sys/buf.h>
73 #include <sys/uio.h>
74 #include <sys/malloc.h>
75 #include <sys/cdio.h>
76 #include <sys/errno.h>
77 #include <sys/dkstat.h>
78 #include <sys/disklabel.h>
79 #include <sys/diskslice.h>
80 #ifdef DEVFS
81 #include <sys/devfsext.h>
82 #endif /*DEVFS*/
83 #include <scsi/scsi_all.h>
84 #include <scsi/scsi_disk.h>
85 #include <scsi/scsiconf.h>
86 #include <vm/vm.h>
87 #include <sys/dkstat.h>
88 #include <machine/md_var.h>
89
90 static u_int32_t odstrats, odqueues;
91
92 #define SECSIZE 512 /* default sector size */
93 #define ODOUTSTANDING 4
94 #define OD_RETRIES 4
95
96 #define PARTITION(dev) dkpart(dev)
97 #define ODUNIT(dev) dkunit(dev)
98
99 /* XXX introduce a dkmodunit() macro for this. */
100 #define ODSETUNIT(DEV, U) \
101 makedev(major(DEV), dkmakeminor((U), dkslice(DEV), dkpart(DEV)))
102
103 struct scsi_data {
104 u_int32_t flags;
105 #define ODINIT 0x04 /* device has been init'd */
106 struct disk_parms {
107 u_char heads; /* Number of heads */
108 u_int16_t cyls; /* Number of cylinders (fictitious) */
109 u_int16_t sectors; /* Number of sectors/track */
110 u_int16_t secsiz; /* Number of bytes/sector */
111 u_int32_t disksize; /* total number sectors */
112 u_int16_t rpm; /* medium rotation rate */
113 } params;
114 struct diskslices *dk_slices; /* virtual drives */
115 struct buf_queue_head buf_queue;
116 int dkunit; /* disk stats unit number */
117 #ifdef DEVFS
118 /* Eventually move all these to common disk struct. */
119 void *b_devfs_token;
120 void *c_devfs_token;
121 void *ctl_devfs_token;
122 #endif
123 };
124
125 static errval od_get_parms __P((int unit, int flags));
126 #ifdef notyet
127 static errval od_reassign_blocks __P((int unit, int block));
128 #endif
129 static u_int32_t od_size __P((int unit, int flags));
130 static int od_sense_handler __P((struct scsi_xfer *));
131 static void odstart __P((u_int32_t, u_int32_t));
132 static void odstrategy1 __P((struct buf *));
133
134 static dev_t odsetunit(dev_t dev, int unit) { return ODSETUNIT(dev, unit); }
135 static int odunit(dev_t dev) { return ODUNIT(dev); }
136
137 static errval od_open __P((dev_t dev, int mode, int fmt, struct proc *p,
138 struct scsi_link *sc_link));
139 static errval od_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
140 struct proc *p, struct scsi_link *sc_link);
141 static errval od_close __P((dev_t dev, int fflag, int fmt, struct proc *p,
142 struct scsi_link *sc_link));
143 static void od_strategy(struct buf *bp, struct scsi_link *sc_link);
144
145 static d_open_t odopen;
146 static d_close_t odclose;
147 static d_ioctl_t odioctl;
148 static d_strategy_t odstrategy;
149
150 #define CDEV_MAJOR 70
151 #define BDEV_MAJOR 20
152 static struct cdevsw od_cdevsw;
153 static struct bdevsw od_bdevsw =
154 { odopen, odclose, odstrategy, odioctl, /*20*/
155 nodump, nopsize, 0, "od", &od_cdevsw, -1 };
156
157
158 /*
159 * Actually include the interface routines
160 */
161 SCSI_DEVICE_ENTRIES(od)
162
163 static struct scsi_device od_switch =
164 {
165 od_sense_handler,
166 odstart, /* have a queue, served by this */
167 NULL, /* have no async handler */
168 NULL, /* Use default 'done' routine */
169 "od",
170 0,
171 {0, 0},
172 0, /* Link flags */
173 odattach,
174 "Optical",
175 odopen,
176 sizeof(struct scsi_data),
177 T_OPTICAL,
178 odunit,
179 odsetunit,
180 od_open,
181 od_ioctl,
182 od_close,
183 od_strategy,
184 };
185
186 static inline void
187 od_registerdev(int unit)
188 {
189 if(dk_ndrive < DK_NDRIVE) {
190 sprintf(dk_names[dk_ndrive], "od%d", unit);
191 dk_wpms[dk_ndrive] = (4*1024*1024/2); /* 4MB/sec */
192 SCSI_DATA(&od_switch, unit)->dkunit = dk_ndrive++;
193 } else {
194 SCSI_DATA(&od_switch, unit)->dkunit = -1;
195 }
196 }
197
198
199 /*
200 * The routine called by the low level scsi routine when it discovers
201 * a device suitable for this driver.
202 */
203 static errval
204 odattach(struct scsi_link *sc_link)
205 {
206 u_int32_t unit;
207 struct disk_parms *dp;
208 #ifdef DEVFS
209 int mynor;
210 #endif
211
212 struct scsi_data *od = sc_link->sd;
213
214 unit = sc_link->dev_unit;
215
216 dp = &(od->params);
217
218 if (sc_link->opennings > ODOUTSTANDING)
219 sc_link->opennings = ODOUTSTANDING;
220
221 bufq_init(&od->buf_queue);
222 /*
223 * Use the subdriver to request information regarding
224 * the drive. We cannot use interrupts yet, so the
225 * request must specify this.
226 */
227 scsi_start_unit(sc_link, SCSI_NOSLEEP | SCSI_NOMASK
228 | SCSI_ERR_OK | SCSI_SILENT);
229 od_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
230 /*
231 * if we don't have actual parameters, assume 512 bytes/sec
232 * (could happen on removable media - MOD)
233 * -- this avoids the division below from falling over
234 */
235 if(dp->secsiz == 0) dp->secsiz = SECSIZE;
236 if (dp->disksize != 0) {
237 printf("%ldMB (%ld %d byte sectors)",
238 dp->disksize / ((1024L * 1024L) / dp->secsiz),
239 dp->disksize,
240 dp->secsiz);
241 } else {
242 printf("od not present");
243 }
244
245 #ifndef SCSI_REPORT_GEOMETRY
246 if ( (sc_link->flags & SDEV_BOOTVERBOSE) )
247 #endif
248 {
249 sc_print_addr(sc_link);
250 printf("with approximate %d cyls, %d heads, and %d sectors/track",
251 dp->cyls, dp->heads, dp->sectors);
252 }
253 #ifdef OD_AUTO_TURNOFF
254 scsi_stop_unit(sc_link, 0, SCSI_ERR_OK | SCSI_SILENT);
255 #endif /* OD_AUTO_TURNOFF */
256
257 od->flags |= ODINIT;
258 od_registerdev(unit);
259
260 #ifdef DEVFS
261 mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
262 od->b_devfs_token = devfs_add_devswf(&od_bdevsw, mynor, DV_BLK,
263 UID_ROOT, GID_OPERATOR, 0640,
264 "od%d", unit);
265 od->c_devfs_token = devfs_add_devswf(&od_cdevsw, mynor, DV_CHR,
266 UID_ROOT, GID_OPERATOR, 0640,
267 "rod%d", unit);
268 mynor = dkmakeminor(unit, 0, 0); /* XXX */
269 od->ctl_devfs_token = devfs_add_devswf(&od_cdevsw,
270 mynor | SCSI_CONTROL_MASK,
271 DV_CHR,
272 UID_ROOT, GID_WHEEL, 0600,
273 "rod%d.ctl", unit);
274 #endif
275
276 return 0;
277 }
278
279 /*
280 * open the device. Make sure the partition info is a up-to-date as can be.
281 */
282 static errval
283 od_open(dev, mode, fmt, p, sc_link)
284 dev_t dev;
285 int mode;
286 int fmt;
287 struct proc *p;
288 struct scsi_link *sc_link;
289 {
290 errval errcode = 0;
291 u_int32_t unit;
292 struct disklabel label;
293 struct scsi_data *od;
294
295 unit = ODUNIT(dev);
296 od = sc_link->sd;
297
298 /*
299 * Make sure the disk has been initialized
300 * At some point in the future, get the scsi driver
301 * to look for a new device if we are not initted
302 */
303 if ((!od) || (!(od->flags & ODINIT))) {
304 return ENXIO;
305 }
306
307 SC_DEBUG(sc_link, SDEV_DB1,
308 ("od_open: dev=0x%lx (unit %ld, partition %d)\n",
309 dev, unit, PARTITION(dev)));
310
311 /*
312 * Try to start the drive, and try to clear "Unit Attention"
313 * condition, when media had been changed before.
314 * This operation also clears the SDEV_MEDIA_LOADED flag in its
315 * error handling routine.
316 */
317 scsi_start_unit(sc_link, SCSI_SILENT);
318 scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
319
320 /*
321 * Make sure the drive is ready.
322 */
323 scsi_test_unit_ready(sc_link, 0);
324
325 SC_DEBUG(sc_link, SDEV_DB3, ("'start' attempted "));
326
327 sc_link->flags |= SDEV_OPEN; /* unit attn becomes an err now */
328 /*
329 * If it's been invalidated, then forget the label.
330 */
331 if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
332 /*
333 * If somebody still has it open, then forbid re-entry.
334 */
335 if (dsisopen(od->dk_slices)) {
336 errcode = ENXIO;
337 goto bad;
338 }
339
340 if (od->dk_slices != NULL)
341 dsgone(&od->dk_slices);
342 }
343
344 /*
345 * This time actually take notice of error returns
346 */
347 if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
348 SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
349 errcode = ENXIO;
350 goto bad;
351 }
352 SC_DEBUG(sc_link, SDEV_DB3, ("device present\n"));
353
354 /*
355 * Load the physical device parameters
356 */
357 errcode = od_get_parms(unit, 0); /* sets SDEV_MEDIA_LOADED */
358 if (errcode) {
359 goto bad;
360 }
361 switch (od->params.secsiz) {
362 case SECSIZE :
363 case 1024 :
364 case 2048 :
365 break;
366 default :
367 printf("od%ld: Can't deal with %d bytes logical blocks\n",
368 unit, od->params.secsiz);
369 Debugger("od");
370 errcode = ENXIO;
371 goto bad;
372 }
373 SC_DEBUG(sc_link, SDEV_DB3, ("params loaded "));
374
375 /* Build label for whole disk. */
376 bzero(&label, sizeof label);
377 label.d_secsize = od->params.secsiz;
378 label.d_nsectors = od->params.sectors;
379 label.d_ntracks = od->params.heads;
380 label.d_ncylinders = od->params.cyls;
381 label.d_secpercyl = od->params.heads * od->params.sectors;
382 label.d_rpm = od->params.rpm; /* maybe wrong */
383 if (label.d_secpercyl == 0)
384 label.d_secpercyl = 64*32;
385 /* XXX as long as it's not 0
386 * - readdisklabel divides by it (?)
387 */
388 label.d_secperunit = od->params.disksize;
389
390 /* Initialize slice tables. */
391 errcode = dsopen("od", dev, fmt, &od->dk_slices, &label, odstrategy1,
392 (ds_setgeom_t *)NULL, &od_bdevsw, &od_cdevsw);
393 if (errcode != 0)
394 goto bad;
395 SC_DEBUG(sc_link, SDEV_DB3, ("Slice tables initialized "));
396
397 SC_DEBUG(sc_link, SDEV_DB3, ("open %ld %ld\n", odstrats, odqueues));
398
399 return 0;
400
401 bad:
402 if (!dsisopen(od->dk_slices)) {
403 scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
404 #ifdef OD_AUTO_TURNOFF
405 scsi_stop_unit(sc_link, 0, SCSI_ERR_OK | SCSI_SILENT);
406 #endif /* OD_AUTO_TURNOFF */
407 sc_link->flags &= ~SDEV_OPEN;
408 }
409 return errcode;
410 }
411
412 /*
413 * close the device.. only called if we are the LAST occurence of an open
414 * device. Convenient now but usually a pain.
415 */
416 static errval
417 od_close(dev, fflag, fmt, p, sc_link)
418 dev_t dev;
419 int fflag;
420 int fmt;
421 struct proc *p;
422 struct scsi_link *sc_link;
423 {
424 struct scsi_data *od;
425
426 od = sc_link->sd;
427 dsclose(dev, fmt, od->dk_slices);
428 if (!dsisopen(od->dk_slices)) {
429 scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
430 #ifdef OD_AUTO_TURNOFF
431 scsi_stop_unit(sc_link, 0, SCSI_ERR_OK | SCSI_SILENT);
432 #endif /* OD_AUTO_TURNOFF */
433 sc_link->flags &= ~SDEV_OPEN;
434 }
435 return 0;
436 }
437
438 /*
439 * Actually translate the requested transfer into one the physical driver
440 * can understand. The transfer is described by a buf and will include
441 * only one physical transfer.
442 */
443 static void
444 od_strategy(struct buf *bp, struct scsi_link *sc_link)
445 {
446 u_int32_t opri;
447 struct scsi_data *od;
448 u_int32_t unit;
449
450 odstrats++;
451 unit = ODUNIT((bp->b_dev));
452 od = sc_link->sd;
453
454 /*
455 * If the device has been made invalid, error out
456 */
457 if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
458 bp->b_error = EIO;
459 goto bad;
460 }
461
462 /*
463 * Odd number of bytes or negative offset
464 */
465 if (bp->b_blkno < 0 || bp->b_bcount % DEV_BSIZE != 0) {
466 bp->b_error = EINVAL;
467 goto bad;
468 }
469 /*
470 * Do bounds checking, adjust transfer, set b_cylin and b_pbklno.
471 */
472 if (dscheck(bp, od->dk_slices) <= 0)
473 goto done; /* XXX check b_resid */
474
475 opri = SPLOD();
476
477 /*
478 * Use a bounce buffer if necessary
479 */
480 #ifdef BOUNCE_BUFFERS
481 if (sc_link->flags & SDEV_BOUNCE)
482 vm_bounce_alloc(bp);
483 #endif
484
485 /*
486 * Place it in the queue of disk activities for this disk
487 */
488 bufq_insert_tail(&od->buf_queue, bp);
489
490 /*
491 * Tell the device to get going on the transfer if it's
492 * not doing anything, otherwise just wait for completion
493 */
494 odstart(unit, 0);
495
496 splx(opri);
497 return /**/;
498 bad:
499 bp->b_flags |= B_ERROR;
500 done:
501
502 /*
503 * Correctly set the buf to indicate a completed xfer
504 */
505 bp->b_resid = bp->b_bcount;
506 biodone(bp);
507 return /**/;
508 }
509
510 static void
511 odstrategy1(struct buf *bp)
512 {
513 /*
514 * XXX - do something to make odstrategy() but not this block while
515 * we're doing dsinit() and dsioctl().
516 */
517 odstrategy(bp);
518 }
519
520 /*
521 * odstart looks to see if there is a buf waiting for the device
522 * and that the device is not already busy. If both are true,
523 * It dequeues the buf and creates a scsi command to perform the
524 * transfer in the buf. The transfer request will call scsi_done
525 * on completion, which will in turn call this routine again
526 * so that the next queued transfer is performed.
527 * The bufs are queued by the strategy routine (odstrategy)
528 *
529 * This routine is also called after other non-queued requests
530 * have been made of the scsi driver, to ensure that the queue
531 * continues to be drained.
532 *
533 * must be called at the correct (highish) spl level
534 * odstart() is called at SPLOD from odstrategy and scsi_done
535 */
536 static void
537 odstart(u_int32_t unit, u_int32_t flags)
538 {
539 register struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
540 register struct scsi_data *od = sc_link->sd;
541 struct buf *bp = 0;
542 struct scsi_rw_big cmd;
543 u_int32_t blkno, nblk;
544 u_int32_t secsize;
545
546 SC_DEBUG(sc_link, SDEV_DB2, ("odstart "));
547 /*
548 * Check if the device has room for another command
549 */
550 while (sc_link->opennings) {
551
552 /*
553 * there is excess capacity, but a special waits
554 * It'll need the adapter as soon as we clear out of the
555 * way and let it run (user level wait).
556 */
557 if (sc_link->flags & SDEV_WAITING) {
558 return;
559 }
560 /*
561 * See if there is a buf with work for us to do..
562 */
563 bp = bufq_first(&od->buf_queue);
564 if (bp == NULL) { /* yes, an assign */
565 return;
566 }
567 bufq_remove(&od->buf_queue, bp);
568
569 /*
570 * If the device has become invalid, abort all the
571 * reads and writes until all files have been closed and
572 * re-openned
573 */
574 if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
575 goto bad;
576 }
577 /*
578 * We have a buf, now we know we are going to go through
579 * With this thing..
580 */
581 secsize = od->params.secsiz;
582 blkno = bp->b_pblkno / (secsize / DEV_BSIZE);
583 if (bp->b_bcount & (secsize - 1))
584 {
585 goto bad;
586 }
587 nblk = (bp->b_bcount + (secsize - 1)) / secsize;
588
589 /*
590 * Fill out the scsi command
591 */
592 cmd.op_code = (bp->b_flags & B_READ)
593 ? READ_BIG : WRITE_BIG;
594 scsi_uto4b(blkno, &cmd.addr_3);
595 scsi_uto2b(nblk, &cmd.length2);
596 cmd.byte2 = cmd.reserved = cmd.control = 0;
597 /*
598 * Call the routine that chats with the adapter.
599 * Note: we cannot sleep as we may be an interrupt
600 */
601 if (scsi_scsi_cmd(sc_link,
602 (struct scsi_generic *) &cmd,
603 sizeof(cmd),
604 (u_char *) bp->b_un.b_addr,
605 bp->b_bcount,
606 OD_RETRIES,
607 100000,
608 bp,
609 flags | ((bp->b_flags & B_READ) ?
610 SCSI_DATA_IN : SCSI_DATA_OUT))
611 == SUCCESSFULLY_QUEUED) {
612 odqueues++;
613 if(od->dkunit >= 0) {
614 dk_xfer[od->dkunit]++;
615 dk_seek[od->dkunit]++; /* don't know */
616 dk_wds[od->dkunit] += bp->b_bcount >> 6;
617 }
618 } else {
619 bad:
620 printf("od%ld: oops not queued\n", unit);
621 bp->b_error = EIO;
622 bp->b_flags |= B_ERROR;
623 biodone(bp);
624 }
625 }
626 }
627
628 /*
629 * Perform special action on behalf of the user
630 * Knows about the internals of this device
631 */
632 static errval
633 od_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
634 struct scsi_link *sc_link)
635 {
636 /* struct od_cmd_buf *args; */
637 errval error;
638 struct scsi_data *od;
639
640 /*
641 * Find the device that the user is talking about
642 */
643 od = sc_link->sd;
644 SC_DEBUG(sc_link, SDEV_DB1, ("odioctl (0x%x)", cmd));
645
646 /*
647 * If the device is not valid.. abandon ship
648 */
649 if (!(sc_link->flags & SDEV_MEDIA_LOADED))
650 return EIO;
651
652 switch (cmd) {
653 case DIOCSBAD:
654 error = EINVAL;
655 break;
656 case CDIOCEJECT:
657 error = scsi_stop_unit(sc_link, 1, 0);
658 sc_link->flags &= ~SDEV_MEDIA_LOADED;
659 break;
660 case CDIOCALLOW:
661 error = scsi_prevent(sc_link, PR_ALLOW, 0);
662 break;
663 case CDIOCPREVENT:
664 error = scsi_prevent(sc_link, PR_PREVENT, 0);
665 break;
666 default:
667 error = dsioctl("od", dev, cmd, addr, flag, &od->dk_slices,
668 odstrategy1, (ds_setgeom_t *)NULL);
669 if (error == -1) {
670 if (PARTITION(dev) != RAW_PART) {
671 error = ENOTTY;
672 } else {
673 error = scsi_do_ioctl(dev, cmd, addr,
674 flag, p, sc_link);
675 }
676 }
677 break;
678 }
679 return error;
680 }
681
682 /*
683 * Find out from the device what it's capacity is
684 */
685 static u_int32_t
686 od_size(unit, flags)
687 int unit, flags;
688 {
689 struct scsi_read_cap_data rdcap;
690 struct scsi_read_capacity rdcap_cmd;
691 struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
692 struct scsi_data *od = sc_link->sd;
693 struct scsi_mode_sense mdsense_cmd;
694 struct scsi_mode_sense_data {
695 struct scsi_mode_header header;
696 struct blk_desc blk_desc;
697 union disk_pages pages;
698 } scsi_sense;
699
700 /*
701 * make up a scsi command and ask the scsi driver to do
702 * it for you.
703 */
704 bzero(&rdcap_cmd, sizeof(rdcap_cmd));
705 rdcap_cmd.op_code = READ_CAPACITY;
706
707 /*
708 * If the command works, interpret the result as a 4 byte
709 * number of blocks
710 */
711 if (scsi_scsi_cmd(sc_link,
712 (struct scsi_generic *) &rdcap_cmd,
713 sizeof(rdcap_cmd),
714 (u_char *) & rdcap,
715 sizeof(rdcap),
716 OD_RETRIES,
717 10000,
718 NULL,
719 flags | SCSI_DATA_IN) != 0) {
720 return 0;
721 } else {
722 od->params.disksize = scsi_4btou(&rdcap.addr_3) + 1;
723 od->params.secsiz = scsi_4btou(&rdcap.length_3);
724 }
725
726 /*
727 * do a "mode sense page 4" (rigid disk drive geometry)
728 */
729 bzero(&mdsense_cmd, sizeof(mdsense_cmd));
730 mdsense_cmd.op_code = MODE_SENSE;
731 mdsense_cmd.page = 4;
732 mdsense_cmd.length = 0x20;
733 /*
734 * If the command worked, use the results to fill out
735 * the parameter structure
736 */
737 if (scsi_scsi_cmd(sc_link,
738 (struct scsi_generic *) &mdsense_cmd,
739 sizeof(mdsense_cmd),
740 (u_char *) & scsi_sense,
741 sizeof(scsi_sense),
742 OD_RETRIES,
743 10000,
744 NULL,
745 flags | SCSI_SILENT | SCSI_DATA_IN) != 0) {
746
747 /* default to a fictitious geometry */
748 od->params.heads = 64;
749 } else {
750 SC_DEBUG(sc_link, SDEV_DB3,
751 ("%ld cyls, %d heads, %d rpm\n",
752 scsi_3btou(&scsi_sense.pages.rigid_geometry.ncyl_2),
753 scsi_sense.pages.rigid_geometry.nheads,
754 scsi_2btou(&scsi_sense.pages.rigid_geometry.medium_rot_rate_1)));
755
756 od->params.heads = scsi_sense.pages.rigid_geometry.nheads;
757 if (od->params.heads == 0)
758 od->params.heads = 64; /* fictitious */
759 od->params.rpm =
760 scsi_2btou(&scsi_sense.pages.rigid_geometry.medium_rot_rate_1);
761 }
762
763 /*
764 * do a "mode sense page 3" (format device)
765 */
766 bzero(&mdsense_cmd, sizeof(mdsense_cmd));
767 mdsense_cmd.op_code = MODE_SENSE;
768 mdsense_cmd.page = 3;
769 mdsense_cmd.length = 0x20;
770 /*
771 * If the command worked, use the results to fill out
772 * the parameter structure
773 */
774 if (scsi_scsi_cmd(sc_link,
775 (struct scsi_generic *) &mdsense_cmd,
776 sizeof(mdsense_cmd),
777 (u_char *) & scsi_sense,
778 sizeof(scsi_sense),
779 OD_RETRIES,
780 10000,
781 NULL,
782 flags | SCSI_SILENT | SCSI_DATA_IN) != 0) {
783
784 /* default to a fictitious geometry */
785 od->params.sectors = 32;
786 } else {
787 SC_DEBUG(sc_link, SDEV_DB3,
788 ("%d secs\n",
789 scsi_2btou(&scsi_sense.pages.disk_format.ph_sec_t_1)));
790
791 od->params.sectors =
792 scsi_2btou(&scsi_sense.pages.disk_format.ph_sec_t_1);
793 if (od->params.sectors == 0)
794 od->params.sectors = 32; /* fictitious */
795 }
796
797 return od->params.disksize;
798 }
799
800 #ifdef notyet
801 /*
802 * Tell the device to map out a defective block
803 */
804 static errval
805 od_reassign_blocks(unit, block)
806 int unit, block;
807 {
808 struct scsi_reassign_blocks scsi_cmd;
809 struct scsi_reassign_blocks_data rbdata;
810 struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
811
812 bzero(&scsi_cmd, sizeof(scsi_cmd));
813 bzero(&rbdata, sizeof(rbdata));
814 scsi_cmd.op_code = REASSIGN_BLOCKS;
815
816 rbdata.length_msb = 0;
817 rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
818 scsi_uto4b(block, &rbdata.defect_descriptor[0].dlbaddr_3);
819
820 return scsi_scsi_cmd(sc_link,
821 (struct scsi_generic *) &scsi_cmd,
822 sizeof(scsi_cmd),
823 (u_char *) & rbdata,
824 sizeof(rbdata),
825 OD_RETRIES,
826 20000,
827 NULL,
828 SCSI_DATA_OUT);
829 }
830 #endif
831
832 /*
833 * Get the scsi driver to send a full inquiry to the
834 * device and use the results to fill out the disk
835 * parameter structure.
836 */
837 static errval
838 od_get_parms(unit, flags)
839 int unit, flags;
840 {
841 struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
842 struct scsi_data *od = sc_link->sd;
843 struct disk_parms *disk_parms = &od->params;
844 u_int32_t sectors;
845 errval retval;
846
847 /*
848 * First check if we have it all loaded
849 */
850 if (sc_link->flags & SDEV_MEDIA_LOADED)
851 return 0;
852
853 /*
854 * Use fictitious geometry, this depends on the size of medium.
855 */
856 sectors = od_size(unit, flags);
857 /* od_size() sets secsiz, disksize, sectors, and heads */
858
859 /* fictitious number of cylinders, so that C*H*S <= total */
860 if (disk_parms->sectors != 0 && disk_parms->heads != 0) {
861 disk_parms->cyls =
862 sectors / (disk_parms->sectors * disk_parms->heads);
863 } else {
864 disk_parms->cyls = 0;
865 }
866
867 if (sectors != 0) {
868 sc_link->flags |= SDEV_MEDIA_LOADED;
869 retval = 0;
870 } else {
871 retval = ENXIO;
872 }
873 return retval;
874 }
875
876 /*
877 * sense handler: Called to determine what to do when the
878 * device returns a CHECK CONDITION.
879 */
880
881 static int
882 od_sense_handler(struct scsi_xfer *xs)
883 {
884 struct scsi_sense_data *sense;
885 struct scsi_sense_extended *ext;
886 int asc, ascq;
887
888 sense = &(xs->sense);
889 ext = (struct scsi_sense_extended *)&(sense->ext.extended);
890
891 /* I don't know what the heck to do with a deferred error,
892 * so I'll just kick it back to the caller.
893 */
894 if ((sense->error_code & SSD_ERRCODE) == 0x71)
895 return SCSIRET_CONTINUE;
896
897 #ifdef OD_BOGUS_NOT_READY
898 if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
899 ((sense->ext.extended.flags & SSD_KEY) == 0x02))
900 /* No point in retrying Not Ready */
901 return SCSIRET_CONTINUE;
902 #endif
903
904 if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
905 ((sense->ext.extended.flags & SSD_KEY) == 0x04))
906 /* No point in retrying Hardware Failure */
907 return SCSIRET_CONTINUE;
908
909 if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
910 ((sense->ext.extended.flags & SSD_KEY) == 0x05))
911 /* No point in retrying Illegal Requests */
912 return SCSIRET_CONTINUE;
913
914 asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0;
915 ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0;
916
917 if (asc == 0x11 || asc == 0x30 || asc == 0x31 || asc == 0x53
918 || asc == 0x5a) {
919 /* Unrecovered errors */
920 return SCSIRET_CONTINUE;
921 }
922 if (asc == 0x21 && ascq == 0) {
923 /* Logical block address out of range */
924 return SCSIRET_CONTINUE;
925 }
926 if (asc == 0x27 && ascq == 0) {
927 /* Write protected */
928 return SCSIRET_CONTINUE;
929 }
930 if (asc == 0x28 && ascq == 0) {
931 /* Not ready to ready transition */
932 /* (medium may have changed) */
933 return SCSIRET_CONTINUE;
934 }
935 if (asc == 0x3a && ascq == 0) {
936 /* Medium not present */
937 return SCSIRET_CONTINUE;
938 }
939
940 /* Retry all disk errors.
941 */
942 scsi_sense_print(xs);
943 if (xs->retries)
944 printf(", retries:%d\n", xs->retries);
945 else
946 printf(", FAILURE\n");
947
948 return SCSIRET_DO_RETRY;
949 }
950
951 static od_devsw_installed = 0;
952
953 static void od_drvinit(void *unused)
954 {
955
956 if( ! od_devsw_installed ) {
957 bdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &od_bdevsw);
958 od_devsw_installed = 1;
959 }
960 }
961
962 SYSINIT(oddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,od_drvinit,NULL)
Cache object: ac70c26e409f9272c25fd093909c3ef1
|