File:
[DragonFly] /
src /
sys /
bus /
cam /
scsi /
scsi_da.c
Revision
1.16:
download - view:
text,
annotated -
select for diffs
Thu May 13 23:49:11 2004 UTC (9 years ago) by
dillon
Branches:
MAIN
CVS tags:
HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).
d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device. It was never
used for that purpose.
d_clone will be more fully implemented as work continues. We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads. This is something we will be needing later
on.
1: /*
2: * Implementation of SCSI Direct Access Peripheral driver for CAM.
3: *
4: * Copyright (c) 1997 Justin T. Gibbs.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions, and the following disclaimer,
12: * without modification, immediately at the beginning of the file.
13: * 2. The name of the author may not be used to endorse or promote products
14: * derived from this software without specific prior written permission.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: *
28: * $FreeBSD: src/sys/cam/scsi/scsi_da.c,v 1.42.2.46 2003/10/21 22:18:19 thomas Exp $
29: * $DragonFly: src/sys/bus/cam/scsi/scsi_da.c,v 1.16 2004/05/13 23:49:11 dillon Exp $
30: */
31:
32: #ifdef _KERNEL
33: #include "opt_hw_wdog.h"
34: #endif /* _KERNEL */
35:
36: #include <sys/param.h>
37: #include <sys/bootmaj.h>
38:
39: #ifdef _KERNEL
40: #include <sys/systm.h>
41: #include <sys/kernel.h>
42: #include <sys/buf.h>
43: #include <sys/sysctl.h>
44: #include <sys/taskqueue.h>
45: #endif /* _KERNEL */
46:
47: #include <sys/devicestat.h>
48: #include <sys/conf.h>
49: #include <sys/disk.h>
50: #include <sys/eventhandler.h>
51: #ifdef _KERNEL
52: #include <sys/malloc.h>
53: #include <sys/cons.h>
54: #include <sys/proc.h>
55: #endif
56: #include <sys/buf2.h>
57:
58: #include <machine/md_var.h>
59:
60: #ifdef _KERNEL
61: #include <vm/vm.h>
62: #include <vm/pmap.h>
63: #endif
64:
65: #ifndef _KERNEL
66: #include <stdio.h>
67: #include <string.h>
68: #endif /* _KERNEL */
69:
70: #include "../cam.h"
71: #include "../cam_ccb.h"
72: #include "../cam_extend.h"
73: #include "../cam_periph.h"
74: #include "../cam_xpt_periph.h"
75:
76: #include "scsi_message.h"
77:
78: #ifndef _KERNEL
79: #include "scsi_da.h"
80: #endif /* !_KERNEL */
81:
82: #ifdef _KERNEL
83: typedef enum {
84: DA_STATE_PROBE,
85: DA_STATE_NORMAL
86: } da_state;
87:
88: typedef enum {
89: DA_FLAG_PACK_INVALID = 0x001,
90: DA_FLAG_NEW_PACK = 0x002,
91: DA_FLAG_PACK_LOCKED = 0x004,
92: DA_FLAG_PACK_REMOVABLE = 0x008,
93: DA_FLAG_TAGGED_QUEUING = 0x010,
94: DA_FLAG_NEED_OTAG = 0x020,
95: DA_FLAG_WENT_IDLE = 0x040,
96: DA_FLAG_RETRY_UA = 0x080,
97: DA_FLAG_OPEN = 0x100,
98: DA_FLAG_SCTX_INIT = 0x200
99: } da_flags;
100:
101: typedef enum {
102: DA_Q_NONE = 0x00,
103: DA_Q_NO_SYNC_CACHE = 0x01,
104: DA_Q_NO_6_BYTE = 0x02,
105: DA_Q_NO_PREVENT = 0x04
106: } da_quirks;
107:
108: typedef enum {
109: DA_CCB_PROBE = 0x01,
110: DA_CCB_BUFFER_IO = 0x02,
111: DA_CCB_WAITING = 0x03,
112: DA_CCB_DUMP = 0x04,
113: DA_CCB_TYPE_MASK = 0x0F,
114: DA_CCB_RETRY_UA = 0x10
115: } da_ccb_state;
116:
117: /* Offsets into our private area for storing information */
118: #define ccb_state ppriv_field0
119: #define ccb_bp ppriv_ptr1
120:
121: struct disk_params {
122: u_int8_t heads;
123: u_int16_t cylinders;
124: u_int8_t secs_per_track;
125: u_int32_t secsize; /* Number of bytes/sector */
126: u_int32_t sectors; /* total number sectors */
127: };
128:
129: struct da_softc {
130: struct buf_queue_head buf_queue;
131: struct devstat device_stats;
132: SLIST_ENTRY(da_softc) links;
133: LIST_HEAD(, ccb_hdr) pending_ccbs;
134: da_state state;
135: da_flags flags;
136: da_quirks quirks;
137: int minimum_cmd_size;
138: int ordered_tag_count;
139: struct disk_params params;
140: struct disk disk;
141: union ccb saved_ccb;
142: struct task sysctl_task;
143: struct sysctl_ctx_list sysctl_ctx;
144: struct sysctl_oid *sysctl_tree;
145: };
146:
147: struct da_quirk_entry {
148: struct scsi_inquiry_pattern inq_pat;
149: da_quirks quirks;
150: };
151:
152: static const char quantum[] = "QUANTUM";
153: static const char microp[] = "MICROP";
154:
155: static struct da_quirk_entry da_quirk_table[] =
156: {
157: /* SPI, FC devices */
158: {
159: /*
160: * Fujitsu M2513A MO drives.
161: * Tested devices: M2513A2 firmware versions 1200 & 1300.
162: * (dip switch selects whether T_DIRECT or T_OPTICAL device)
163: * Reported by: W.Scholten <whs@xs4all.nl>
164: */
165: {T_DIRECT, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
166: /*quirks*/ DA_Q_NO_SYNC_CACHE
167: },
168: {
169: /* See above. */
170: {T_OPTICAL, SIP_MEDIA_REMOVABLE, "FUJITSU", "M2513A", "*"},
171: /*quirks*/ DA_Q_NO_SYNC_CACHE
172: },
173: {
174: /*
175: * This particular Fujitsu drive doesn't like the
176: * synchronize cache command.
177: * Reported by: Tom Jackson <toj@gorilla.net>
178: */
179: {T_DIRECT, SIP_MEDIA_FIXED, "FUJITSU", "M2954*", "*"},
180: /*quirks*/ DA_Q_NO_SYNC_CACHE
181:
182: },
183: {
184: /*
185: * This drive doesn't like the synchronize cache command
186: * either. Reported by: Matthew Jacob <mjacob@feral.com>
187: * in NetBSD PR kern/6027, August 24, 1998.
188: */
189: {T_DIRECT, SIP_MEDIA_FIXED, microp, "2217*", "*"},
190: /*quirks*/ DA_Q_NO_SYNC_CACHE
191: },
192: {
193: /*
194: * This drive doesn't like the synchronize cache command
195: * either. Reported by: Hellmuth Michaelis (hm@kts.org)
196: * (PR 8882).
197: */
198: {T_DIRECT, SIP_MEDIA_FIXED, microp, "2112*", "*"},
199: /*quirks*/ DA_Q_NO_SYNC_CACHE
200: },
201: {
202: /*
203: * Doesn't like the synchronize cache command.
204: * Reported by: Blaz Zupan <blaz@gold.amis.net>
205: */
206: {T_DIRECT, SIP_MEDIA_FIXED, "NEC", "D3847*", "*"},
207: /*quirks*/ DA_Q_NO_SYNC_CACHE
208: },
209: {
210: /*
211: * Doesn't like the synchronize cache command.
212: */
213: {T_DIRECT, SIP_MEDIA_FIXED, quantum, "MAVERICK 540S", "*"},
214: /*quirks*/ DA_Q_NO_SYNC_CACHE
215: },
216: {
217: /*
218: * Doesn't like the synchronize cache command.
219: */
220: {T_DIRECT, SIP_MEDIA_FIXED, quantum, "LPS525S", "*"},
221: /*quirks*/ DA_Q_NO_SYNC_CACHE
222: },
223: {
224: /*
225: * Doesn't work correctly with 6 byte reads/writes.
226: * Returns illegal request, and points to byte 9 of the
227: * 6-byte CDB.
228: * Reported by: Adam McDougall <bsdx@spawnet.com>
229: */
230: {T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 4*", "*"},
231: /*quirks*/ DA_Q_NO_6_BYTE
232: },
233: {
234: /* See above. */
235: {T_DIRECT, SIP_MEDIA_FIXED, quantum, "VIKING 2*", "*"},
236: /*quirks*/ DA_Q_NO_6_BYTE
237: },
238: /* XXX USB floppy quirks temporarily enabled for 4.9R */
239: /* USB floppy devices supported by umass(4) */
240: {
241: /*
242: * This USB floppy drive uses the UFI command set. This
243: * command set is a derivative of the ATAPI command set and
244: * does not support READ_6 commands only READ_10. It also does
245: * not support sync cache (0x35).
246: */
247: {T_DIRECT, SIP_MEDIA_REMOVABLE, "Y-E DATA", "USB-FDU", "*"},
248: /*quirks*/ DA_Q_NO_SYNC_CACHE
249: },
250: {
251: /* Another USB floppy */
252: {T_DIRECT, SIP_MEDIA_REMOVABLE, "MATSHITA", "FDD CF-VFDU*","*"},
253: /*quirks*/ DA_Q_NO_SYNC_CACHE
254: },
255: {
256: /*
257: * The vendor, product and version strings coming from the
258: * controller are null terminated instead of being padded with
259: * spaces. The trailing wildcard character '*' is required.
260: */
261: {T_DIRECT, SIP_MEDIA_REMOVABLE, "SMSC*", "USB FDC*","*"},
262: /*quirks*/ DA_Q_NO_SYNC_CACHE
263: },
264: {
265: /*
266: * SmartDisk (Mitsumi) USB floppy drive
267: * PR: kern/50226
268: */
269: {T_DIRECT, SIP_MEDIA_REMOVABLE, "MITSUMI", "USB FDD", "*"},
270: /*quirks*/ DA_Q_NO_SYNC_CACHE
271: },
272: #ifdef DA_OLD_QUIRKS
273: /* USB mass storage devices supported by umass(4) */
274: {
275: /*
276: * Sony Memory Stick adapter MSAC-US1 and
277: * Sony PCG-C1VJ Internal Memory Stick Slot (MSC-U01).
278: * Make all sony MS* products use this quirk.
279: */
280: {T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "MS*", "*"},
281: /*quirks*/ DA_Q_NO_SYNC_CACHE
282: },
283: {
284: /*
285: * Sony Memory Stick adapter for the CLIE series
286: * of PalmOS PDA's
287: */
288: {T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "CLIE*", "*"},
289: /*quirks*/ DA_Q_NO_SYNC_CACHE
290: },
291: {
292: /*
293: * Intelligent Stick USB disk-on-key
294: * PR: kern/53005
295: */
296: {T_DIRECT, SIP_MEDIA_REMOVABLE, "USB Card",
297: "IntelligentStick*", "*"},
298: /*quirks*/ DA_Q_NO_SYNC_CACHE
299: },
300: {
301: /*
302: * Sony DSC cameras (DSC-S30, DSC-S50, DSC-S70)
303: */
304: {T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "Sony DSC", "*"},
305: /*quirks*/ DA_Q_NO_SYNC_CACHE
306: },
307: {
308: /*
309: * Microtech USB CameraMate
310: */
311: {T_DIRECT, SIP_MEDIA_REMOVABLE, "eUSB Compact*",
312: "Compact Flash*", "*"},
313: /*quirks*/ DA_Q_NO_SYNC_CACHE
314: },
315: {
316: /*
317: * Olympus digital cameras (C-3040ZOOM, C-2040ZOOM, C-1)
318: */
319: {T_DIRECT, SIP_MEDIA_REMOVABLE, "OLYMPUS", "C-*", "*"},
320: /*quirks*/ DA_Q_NO_SYNC_CACHE
321: },
322: {
323: /*
324: * Olympus digital cameras (E-100RS, E-10).
325: */
326: {T_DIRECT, SIP_MEDIA_REMOVABLE, "OLYMPUS", "E-*", "*"},
327: /*quirks*/ DA_Q_NO_SYNC_CACHE
328: },
329: {
330: /*
331: * KingByte Pen Drives
332: */
333: {T_DIRECT, SIP_MEDIA_REMOVABLE, "NO BRAND", "PEN DRIVE", "*"},
334: /*quirks*/ DA_Q_NO_SYNC_CACHE
335: },
336: {
337: /*
338: * FujiFilm Camera
339: */
340: {T_DIRECT, SIP_MEDIA_REMOVABLE, "FUJIFILMUSB-DRIVEUNIT",
341: "USB-DRIVEUNIT", "*"},
342: /*quirks*/ DA_Q_NO_SYNC_CACHE
343: },
344: {
345: /*
346: * Minolta Dimage E203
347: */
348: {T_DIRECT, SIP_MEDIA_REMOVABLE, "MINOLTA", "DiMAGE E203", "*"},
349: /*quirks*/ DA_Q_NO_SYNC_CACHE
350: },
351: {
352: /*
353: * Apacer HandyDrive
354: * PR: kern/43627
355: */
356: {T_DIRECT, SIP_MEDIA_REMOVABLE, "Apacer", "HandyDrive", "*"},
357: /*quirks*/ DA_Q_NO_SYNC_CACHE
358: },
359: {
360: /*
361: * Daisy Technology PhotoClip on Zoran chip
362: * PR: kern/43580
363: */
364: {T_DIRECT, SIP_MEDIA_REMOVABLE, "ZORAN", "COACH", "*"},
365: /*quirks*/ DA_Q_NO_SYNC_CACHE
366: },
367: {
368: /*
369: * Sony USB Key-Storage
370: * PR: kern/46386
371: */
372: {T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "Storage Media", "*"},
373: /*quirks*/ DA_Q_NO_SYNC_CACHE
374: },
375: #endif /* DA_OLD_QUIRKS */
376: {
377: /*
378: * EXATELECOM (Sigmatel) i-Bead 100/105 USB Flash MP3 Player
379: * PR: kern/51675
380: */
381: {T_DIRECT, SIP_MEDIA_REMOVABLE, "EXATEL", "i-BEAD10*", "*"},
382: /*quirks*/ DA_Q_NO_SYNC_CACHE
383: },
384: {
385: /*
386: * Jungsoft NEXDISK USB flash key
387: * PR: kern/54737
388: */
389: {T_DIRECT, SIP_MEDIA_REMOVABLE, "JUNGSOFT", "NEXDISK*", "*"},
390: /*quirks*/ DA_Q_NO_SYNC_CACHE
391: },
392: {
393: /*
394: * Creative Nomad MUVO mp3 player (USB)
395: * PR: kern/53094
396: */
397: {T_DIRECT, SIP_MEDIA_REMOVABLE, "CREATIVE", "NOMAD_MUVO", "*"},
398: /*quirks*/ DA_Q_NO_SYNC_CACHE|DA_Q_NO_PREVENT
399: },
400: };
401:
402: static d_open_t daopen;
403: static d_close_t daclose;
404: static d_strategy_t dastrategy;
405: static d_ioctl_t daioctl;
406: static d_dump_t dadump;
407: static periph_init_t dainit;
408: static void daasync(void *callback_arg, u_int32_t code,
409: struct cam_path *path, void *arg);
410: static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
411: static periph_ctor_t daregister;
412: static periph_dtor_t dacleanup;
413: static periph_start_t dastart;
414: static periph_oninv_t daoninvalidate;
415: static void dadone(struct cam_periph *periph,
416: union ccb *done_ccb);
417: static int daerror(union ccb *ccb, u_int32_t cam_flags,
418: u_int32_t sense_flags);
419: static void daprevent(struct cam_periph *periph, int action);
420: static void dasetgeom(struct cam_periph *periph,
421: struct scsi_read_capacity_data * rdcap);
422: static timeout_t dasendorderedtag;
423: static void dashutdown(void *arg, int howto);
424:
425: #ifndef DA_DEFAULT_TIMEOUT
426: #define DA_DEFAULT_TIMEOUT 60 /* Timeout in seconds */
427: #endif
428:
429: #ifndef DA_DEFAULT_RETRY
430: #define DA_DEFAULT_RETRY 4
431: #endif
432:
433: static int da_retry_count = DA_DEFAULT_RETRY;
434: static int da_default_timeout = DA_DEFAULT_TIMEOUT;
435:
436: SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0,
437: "CAM Direct Access Disk driver");
438: SYSCTL_INT(_kern_cam_da, OID_AUTO, retry_count, CTLFLAG_RW,
439: &da_retry_count, 0, "Normal I/O retry count");
440: TUNABLE_INT("kern.cam.da.retry_count", &da_retry_count);
441: SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RW,
442: &da_default_timeout, 0, "Normal I/O timeout (in seconds)");
443: TUNABLE_INT("kern.cam.da.default_timeout", &da_default_timeout);
444:
445: /*
446: * DA_ORDEREDTAG_INTERVAL determines how often, relative
447: * to the default timeout, we check to see whether an ordered
448: * tagged transaction is appropriate to prevent simple tag
449: * starvation. Since we'd like to ensure that there is at least
450: * 1/2 of the timeout length left for a starved transaction to
451: * complete after we've sent an ordered tag, we must poll at least
452: * four times in every timeout period. This takes care of the worst
453: * case where a starved transaction starts during an interval that
454: * meets the requirement "don't send an ordered tag" test so it takes
455: * us two intervals to determine that a tag must be sent.
456: */
457: #ifndef DA_ORDEREDTAG_INTERVAL
458: #define DA_ORDEREDTAG_INTERVAL 4
459: #endif
460:
461: static struct periph_driver dadriver =
462: {
463: dainit, "da",
464: TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
465: };
466:
467: DATA_SET(periphdriver_set, dadriver);
468:
469: /* For 2.2-stable support */
470: #ifndef D_DISK
471: #define D_DISK 0
472: #endif
473:
474: static struct cdevsw da_cdevsw = {
475: /* name */ "da",
476: /* maj */ DA_CDEV_MAJOR,
477: /* flags */ D_DISK,
478: /* port */ NULL,
479: /* clone */ NULL,
480:
481: /* open */ daopen,
482: /* close */ daclose,
483: /* read */ physread,
484: /* write */ physwrite,
485: /* ioctl */ daioctl,
486: /* poll */ nopoll,
487: /* mmap */ nommap,
488: /* strategy */ dastrategy,
489: /* dump */ dadump,
490: /* psize */ nopsize
491: };
492:
493: static SLIST_HEAD(,da_softc) softc_list;
494: static struct extend_array *daperiphs;
495:
496: static int
497: daopen(dev_t dev, int flags, int fmt, struct thread *td)
498: {
499: struct cam_periph *periph;
500: struct da_softc *softc;
501: struct disklabel *label;
502: int unit;
503: int part;
504: int error;
505: int s;
506:
507: unit = dkunit(dev);
508: part = dkpart(dev);
509: periph = cam_extend_get(daperiphs, unit);
510: if (periph == NULL)
511: return (ENXIO);
512:
513: softc = (struct da_softc *)periph->softc;
514:
515: CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
516: ("daopen: dev=%s (unit %d , partition %d)\n", devtoname(dev),
517: unit, part));
518:
519: if ((error = cam_periph_lock(periph, PCATCH)) != 0) {
520: return (error); /* error code from tsleep */
521: }
522:
523: if (cam_periph_acquire(periph) != CAM_REQ_CMP)
524: return(ENXIO);
525: softc->flags |= DA_FLAG_OPEN;
526:
527: s = splsoftcam();
528: if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
529: /* Invalidate our pack information. */
530: disk_invalidate(&softc->disk);
531: softc->flags &= ~DA_FLAG_PACK_INVALID;
532: }
533: splx(s);
534:
535: /* Do a read capacity */
536: {
537: struct scsi_read_capacity_data *rcap;
538: union ccb *ccb;
539:
540: rcap = malloc(sizeof(*rcap), M_TEMP, M_INTWAIT | M_ZERO);
541:
542: ccb = cam_periph_getccb(periph, /*priority*/1);
543: scsi_read_capacity(&ccb->csio,
544: /*retries*/1,
545: /*cbfncp*/dadone,
546: MSG_SIMPLE_Q_TAG,
547: rcap,
548: SSD_FULL_SIZE,
549: /*timeout*/60000);
550: ccb->ccb_h.ccb_bp = NULL;
551:
552: error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
553: /*sense_flags*/SF_RETRY_UA |
554: SF_RETRY_SELTO,
555: &softc->device_stats);
556:
557: xpt_release_ccb(ccb);
558:
559: if (error == 0) {
560: dasetgeom(periph, rcap);
561: }
562:
563: free(rcap, M_TEMP);
564: }
565:
566: if (error == 0) {
567: struct ccb_getdev cgd;
568:
569: /* Build label for whole disk. */
570: label = &softc->disk.d_label;
571: bzero(label, sizeof(*label));
572: label->d_type = DTYPE_SCSI;
573:
574: /*
575: * Grab the inquiry data to get the vendor and product names.
576: * Put them in the typename and packname for the label.
577: */
578: xpt_setup_ccb(&cgd.ccb_h, periph->path, /*priority*/ 1);
579: cgd.ccb_h.func_code = XPT_GDEV_TYPE;
580: xpt_action((union ccb *)&cgd);
581:
582: strncpy(label->d_typename, cgd.inq_data.vendor,
583: min(SID_VENDOR_SIZE, sizeof(label->d_typename)));
584: strncpy(label->d_packname, cgd.inq_data.product,
585: min(SID_PRODUCT_SIZE, sizeof(label->d_packname)));
586:
587: label->d_secsize = softc->params.secsize;
588: label->d_nsectors = softc->params.secs_per_track;
589: label->d_ntracks = softc->params.heads;
590: label->d_ncylinders = softc->params.cylinders;
591: label->d_secpercyl = softc->params.heads
592: * softc->params.secs_per_track;
593: label->d_secperunit = softc->params.sectors;
594:
595: if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
596: (softc->quirks & DA_Q_NO_PREVENT) == 0)
597: daprevent(periph, PR_PREVENT);
598:
599: /*
600: * Check to see whether or not the blocksize is set yet.
601: * If it isn't, set it and then clear the blocksize
602: * unavailable flag for the device statistics.
603: */
604: if ((softc->device_stats.flags & DEVSTAT_BS_UNAVAILABLE) != 0){
605: softc->device_stats.block_size = softc->params.secsize;
606: softc->device_stats.flags &= ~DEVSTAT_BS_UNAVAILABLE;
607: }
608: }
609:
610: if (error != 0) {
611: if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
612: (softc->quirks & DA_Q_NO_PREVENT) == 0)
613: daprevent(periph, PR_ALLOW);
614: softc->flags &= ~DA_FLAG_OPEN;
615: cam_periph_release(periph);
616: }
617: cam_periph_unlock(periph);
618: return (error);
619: }
620:
621: static int
622: daclose(dev_t dev, int flag, int fmt, struct thread *td)
623: {
624: struct cam_periph *periph;
625: struct da_softc *softc;
626: int unit;
627: int error;
628:
629: unit = dkunit(dev);
630: periph = cam_extend_get(daperiphs, unit);
631: if (periph == NULL)
632: return (ENXIO);
633:
634: softc = (struct da_softc *)periph->softc;
635:
636: if ((error = cam_periph_lock(periph, 0)) != 0) {
637: return (error); /* error code from tsleep */
638: }
639:
640: if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
641: union ccb *ccb;
642:
643: ccb = cam_periph_getccb(periph, /*priority*/1);
644:
645: scsi_synchronize_cache(&ccb->csio,
646: /*retries*/1,
647: /*cbfcnp*/dadone,
648: MSG_SIMPLE_Q_TAG,
649: /*begin_lba*/0,/* Cover the whole disk */
650: /*lb_count*/0,
651: SSD_FULL_SIZE,
652: 5 * 60 * 1000);
653:
654: cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
655: /*sense_flags*/SF_RETRY_UA,
656: &softc->device_stats);
657:
658: if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
659: if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
660: CAM_SCSI_STATUS_ERROR) {
661: int asc, ascq;
662: int sense_key, error_code;
663:
664: scsi_extract_sense(&ccb->csio.sense_data,
665: &error_code,
666: &sense_key,
667: &asc, &ascq);
668: if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
669: scsi_sense_print(&ccb->csio);
670: } else {
671: xpt_print_path(periph->path);
672: printf("Synchronize cache failed, status "
673: "== 0x%x, scsi status == 0x%x\n",
674: ccb->csio.ccb_h.status,
675: ccb->csio.scsi_status);
676: }
677: }
678:
679: if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
680: cam_release_devq(ccb->ccb_h.path,
681: /*relsim_flags*/0,
682: /*reduction*/0,
683: /*timeout*/0,
684: /*getcount_only*/0);
685:
686: xpt_release_ccb(ccb);
687:
688: }
689:
690: if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) {
691: if ((softc->quirks & DA_Q_NO_PREVENT) == 0)
692: daprevent(periph, PR_ALLOW);
693: /*
694: * If we've got removeable media, mark the blocksize as
695: * unavailable, since it could change when new media is
696: * inserted.
697: */
698: softc->device_stats.flags |= DEVSTAT_BS_UNAVAILABLE;
699: }
700:
701: softc->flags &= ~DA_FLAG_OPEN;
702: cam_periph_unlock(periph);
703: cam_periph_release(periph);
704: return (0);
705: }
706:
707: /*
708: * Actually translate the requested transfer into one the physical driver
709: * can understand. The transfer is described by a buf and will include
710: * only one physical transfer.
711: */
712: static void
713: dastrategy(struct buf *bp)
714: {
715: struct cam_periph *periph;
716: struct da_softc *softc;
717: u_int unit;
718: u_int part;
719: int s;
720:
721: unit = dkunit(bp->b_dev);
722: part = dkpart(bp->b_dev);
723: periph = cam_extend_get(daperiphs, unit);
724: if (periph == NULL) {
725: bp->b_error = ENXIO;
726: goto bad;
727: }
728: softc = (struct da_softc *)periph->softc;
729: #if 0
730: /*
731: * check it's not too big a transfer for our adapter
732: */
733: scsi_minphys(bp,&sd_switch);
734: #endif
735:
736: /*
737: * Mask interrupts so that the pack cannot be invalidated until
738: * after we are in the queue. Otherwise, we might not properly
739: * clean up one of the buffers.
740: */
741: s = splbio();
742:
743: /*
744: * If the device has been made invalid, error out
745: */
746: if ((softc->flags & DA_FLAG_PACK_INVALID)) {
747: splx(s);
748: bp->b_error = ENXIO;
749: goto bad;
750: }
751:
752: /*
753: * Place it in the queue of disk activities for this disk
754: */
755: bufqdisksort(&softc->buf_queue, bp);
756:
757: splx(s);
758:
759: /*
760: * Schedule ourselves for performing the work.
761: */
762: xpt_schedule(periph, /* XXX priority */1);
763:
764: return;
765: bad:
766: bp->b_flags |= B_ERROR;
767:
768: /*
769: * Correctly set the buf to indicate a completed xfer
770: */
771: bp->b_resid = bp->b_bcount;
772: biodone(bp);
773: return;
774: }
775:
776: /* For 2.2-stable support */
777: #ifndef ENOIOCTL
778: #define ENOIOCTL -1
779: #endif
780:
781: static int
782: daioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
783: {
784: struct cam_periph *periph;
785: struct da_softc *softc;
786: int unit;
787: int error;
788:
789: unit = dkunit(dev);
790: periph = cam_extend_get(daperiphs, unit);
791: if (periph == NULL)
792: return (ENXIO);
793:
794: softc = (struct da_softc *)periph->softc;
795:
796: CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("daioctl\n"));
797:
798: if ((error = cam_periph_lock(periph, PCATCH)) != 0) {
799: return (error); /* error code from tsleep */
800: }
801:
802: error = cam_periph_ioctl(periph, cmd, addr, daerror);
803:
804: cam_periph_unlock(periph);
805:
806: return (error);
807: }
808:
809: static int
810: dadump(dev_t dev)
811: {
812: struct cam_periph *periph;
813: struct da_softc *softc;
814: u_int unit;
815: u_int part;
816: u_int secsize;
817: u_int num; /* number of sectors to write */
818: u_int blknum;
819: long blkcnt;
820: vm_paddr_t addr;
821: struct ccb_scsiio csio;
822: int dumppages = MAXDUMPPGS;
823: int error;
824: int i;
825:
826: /* toss any characters present prior to dump */
827: while (cncheckc() != -1)
828: ;
829:
830: unit = dkunit(dev);
831: part = dkpart(dev);
832: periph = cam_extend_get(daperiphs, unit);
833: if (periph == NULL) {
834: return (ENXIO);
835: }
836: softc = (struct da_softc *)periph->softc;
837:
838: if ((softc->flags & DA_FLAG_PACK_INVALID) != 0)
839: return (ENXIO);
840:
841: error = disk_dumpcheck(dev, &num, &blknum, &secsize);
842: if (error)
843: return (error);
844:
845: addr = 0; /* starting address */
846: blkcnt = howmany(PAGE_SIZE, secsize);
847:
848: while (num > 0) {
849: caddr_t va = NULL;
850:
851: if ((num / blkcnt) < dumppages)
852: dumppages = num / blkcnt;
853:
854: for (i = 0; i < dumppages; ++i) {
855: vm_paddr_t a = addr + (i * PAGE_SIZE);
856: if (is_physical_memory(a))
857: va = pmap_kenter_temporary(trunc_page(a), i);
858: else
859: va = pmap_kenter_temporary(trunc_page(0), i);
860: }
861:
862: xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
863: csio.ccb_h.ccb_state = DA_CCB_DUMP;
864: scsi_read_write(&csio,
865: /*retries*/1,
866: dadone,
867: MSG_ORDERED_Q_TAG,
868: /*read*/FALSE,
869: /*byte2*/0,
870: /*minimum_cmd_size*/ softc->minimum_cmd_size,
871: blknum,
872: blkcnt * dumppages,
873: /*data_ptr*/(u_int8_t *) va,
874: /*dxfer_len*/blkcnt * secsize * dumppages,
875: /*sense_len*/SSD_FULL_SIZE,
876: DA_DEFAULT_TIMEOUT * 1000);
877: xpt_polled_action((union ccb *)&csio);
878:
879: if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
880: printf("Aborting dump due to I/O error.\n");
881: if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
882: CAM_SCSI_STATUS_ERROR)
883: scsi_sense_print(&csio);
884: else
885: printf("status == 0x%x, scsi status == 0x%x\n",
886: csio.ccb_h.status, csio.scsi_status);
887: return(EIO);
888: }
889:
890: if (dumpstatus(addr, (off_t)num * softc->params.secsize) < 0)
891: return (EINTR);
892:
893: /* update block count */
894: num -= blkcnt * dumppages;
895: blknum += blkcnt * dumppages;
896: addr += PAGE_SIZE * dumppages;
897: }
898:
899: /*
900: * Sync the disk cache contents to the physical media.
901: */
902: if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
903:
904: xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
905: csio.ccb_h.ccb_state = DA_CCB_DUMP;
906: scsi_synchronize_cache(&csio,
907: /*retries*/1,
908: /*cbfcnp*/dadone,
909: MSG_SIMPLE_Q_TAG,
910: /*begin_lba*/0,/* Cover the whole disk */
911: /*lb_count*/0,
912: SSD_FULL_SIZE,
913: 5 * 60 * 1000);
914: xpt_polled_action((union ccb *)&csio);
915:
916: if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
917: if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
918: CAM_SCSI_STATUS_ERROR) {
919: int asc, ascq;
920: int sense_key, error_code;
921:
922: scsi_extract_sense(&csio.sense_data,
923: &error_code,
924: &sense_key,
925: &asc, &ascq);
926: if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
927: scsi_sense_print(&csio);
928: } else {
929: xpt_print_path(periph->path);
930: printf("Synchronize cache failed, status "
931: "== 0x%x, scsi status == 0x%x\n",
932: csio.ccb_h.status, csio.scsi_status);
933: }
934: }
935: }
936: return (0);
937: }
938:
939: static void
940: dainit(void)
941: {
942: cam_status status;
943: struct cam_path *path;
944:
945: /*
946: * Create our extend array for storing the devices we attach to.
947: */
948: daperiphs = cam_extend_new();
949: SLIST_INIT(&softc_list);
950: if (daperiphs == NULL) {
951: printf("da: Failed to alloc extend array!\n");
952: return;
953: }
954:
955: /*
956: * Install a global async callback. This callback will
957: * receive async callbacks like "new device found".
958: */
959: status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
960: CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
961:
962: if (status == CAM_REQ_CMP) {
963: struct ccb_setasync csa;
964:
965: xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
966: csa.ccb_h.func_code = XPT_SASYNC_CB;
967: csa.event_enable = AC_FOUND_DEVICE;
968: csa.callback = daasync;
969: csa.callback_arg = NULL;
970: xpt_action((union ccb *)&csa);
971: status = csa.ccb_h.status;
972: xpt_free_path(path);
973: }
974:
975: if (status != CAM_REQ_CMP) {
976: printf("da: Failed to attach master async callback "
977: "due to status 0x%x!\n", status);
978: } else {
979:
980: /*
981: * Schedule a periodic event to occasionally send an
982: * ordered tag to a device.
983: */
984: timeout(dasendorderedtag, NULL,
985: (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL);
986:
987: /* Register our shutdown event handler */
988: if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown,
989: NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
990: printf("dainit: shutdown event registration failed!\n");
991: }
992: }
993:
994: static void
995: daoninvalidate(struct cam_periph *periph)
996: {
997: int s;
998: struct da_softc *softc;
999: struct buf *q_bp;
1000: struct ccb_setasync csa;
1001:
1002: softc = (struct da_softc *)periph->softc;
1003:
1004: /*
1005: * De-register any async callbacks.
1006: */
1007: xpt_setup_ccb(&csa.ccb_h, periph->path,
1008: /* priority */ 5);
1009: csa.ccb_h.func_code = XPT_SASYNC_CB;
1010: csa.event_enable = 0;
1011: csa.callback = daasync;
1012: csa.callback_arg = periph;
1013: xpt_action((union ccb *)&csa);
1014:
1015: softc->flags |= DA_FLAG_PACK_INVALID;
1016:
1017: /*
1018: * Although the oninvalidate() routines are always called at
1019: * splsoftcam, we need to be at splbio() here to keep the buffer
1020: * queue from being modified while we traverse it.
1021: */
1022: s = splbio();
1023:
1024: /*
1025: * Return all queued I/O with ENXIO.
1026: * XXX Handle any transactions queued to the card
1027: * with XPT_ABORT_CCB.
1028: */
1029: while ((q_bp = bufq_first(&softc->buf_queue)) != NULL){
1030: bufq_remove(&softc->buf_queue, q_bp);
1031: q_bp->b_resid = q_bp->b_bcount;
1032: q_bp->b_error = ENXIO;
1033: q_bp->b_flags |= B_ERROR;
1034: biodone(q_bp);
1035: }
1036: splx(s);
1037:
1038: SLIST_REMOVE(&softc_list, softc, da_softc, links);
1039:
1040: xpt_print_path(periph->path);
1041: printf("lost device\n");
1042: }
1043:
1044: static void
1045: dacleanup(struct cam_periph *periph)
1046: {
1047: struct da_softc *softc;
1048:
1049: softc = (struct da_softc *)periph->softc;
1050:
1051: devstat_remove_entry(&softc->device_stats);
1052: cam_extend_release(daperiphs, periph->unit_number);
1053: xpt_print_path(periph->path);
1054: printf("removing device entry\n");
1055: /*
1056: * If we can't free the sysctl tree, oh well...
1057: */
1058: if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
1059: && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
1060: xpt_print_path(periph->path);
1061: printf("can't remove sysctl context\n");
1062: }
1063: if (softc->disk.d_dev) {
1064: disk_destroy(&softc->disk);
1065: }
1066: free(softc, M_DEVBUF);
1067: }
1068:
1069: static void
1070: daasync(void *callback_arg, u_int32_t code,
1071: struct cam_path *path, void *arg)
1072: {
1073: struct cam_periph *periph;
1074:
1075: periph = (struct cam_periph *)callback_arg;
1076: switch (code) {
1077: case AC_FOUND_DEVICE:
1078: {
1079: struct ccb_getdev *cgd;
1080: cam_status status;
1081:
1082: cgd = (struct ccb_getdev *)arg;
1083:
1084: if (SID_TYPE(&cgd->inq_data) != T_DIRECT
1085: && SID_TYPE(&cgd->inq_data) != T_RBC
1086: && SID_TYPE(&cgd->inq_data) != T_OPTICAL)
1087: break;
1088:
1089: /*
1090: * Allocate a peripheral instance for
1091: * this device and start the probe
1092: * process.
1093: */
1094: status = cam_periph_alloc(daregister, daoninvalidate,
1095: dacleanup, dastart,
1096: "da", CAM_PERIPH_BIO,
1097: cgd->ccb_h.path, daasync,
1098: AC_FOUND_DEVICE, cgd);
1099:
1100: if (status != CAM_REQ_CMP
1101: && status != CAM_REQ_INPROG)
1102: printf("daasync: Unable to attach to new device "
1103: "due to status 0x%x\n", status);
1104: break;
1105: }
1106: case AC_SENT_BDR:
1107: case AC_BUS_RESET:
1108: {
1109: struct da_softc *softc;
1110: struct ccb_hdr *ccbh;
1111: int s;
1112:
1113: softc = (struct da_softc *)periph->softc;
1114: s = splsoftcam();
1115: /*
1116: * Don't fail on the expected unit attention
1117: * that will occur.
1118: */
1119: softc->flags |= DA_FLAG_RETRY_UA;
1120: for (ccbh = LIST_FIRST(&softc->pending_ccbs);
1121: ccbh != NULL; ccbh = LIST_NEXT(ccbh, periph_links.le))
1122: ccbh->ccb_state |= DA_CCB_RETRY_UA;
1123: splx(s);
1124: /* FALLTHROUGH*/
1125: }
1126: default:
1127: cam_periph_async(periph, code, path, arg);
1128: break;
1129: }
1130: }
1131:
1132: static void
1133: dasysctlinit(void *context, int pending)
1134: {
1135: struct cam_periph *periph;
1136: struct da_softc *softc;
1137: char tmpstr[80], tmpstr2[80];
1138:
1139: periph = (struct cam_periph *)context;
1140: softc = (struct da_softc *)periph->softc;
1141:
1142: snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
1143: snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
1144:
1145: sysctl_ctx_init(&softc->sysctl_ctx);
1146: softc->flags |= DA_FLAG_SCTX_INIT;
1147: softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
1148: SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
1149: CTLFLAG_RD, 0, tmpstr);
1150: if (softc->sysctl_tree == NULL) {
1151: printf("dasysctlinit: unable to allocate sysctl tree\n");
1152: return;
1153: }
1154:
1155: /*
1156: * Now register the sysctl handler, so the user can the value on
1157: * the fly.
1158: */
1159: SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
1160: OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
1161: &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
1162: "Minimum CDB size");
1163: }
1164:
1165: static int
1166: dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
1167: {
1168: int error, value;
1169:
1170: value = *(int *)arg1;
1171:
1172: error = sysctl_handle_int(oidp, &value, 0, req);
1173:
1174: if ((error != 0)
1175: || (req->newptr == NULL))
1176: return (error);
1177:
1178: /*
1179: * Acceptable values here are 6, 10 or 12. It's possible we may
1180: * support a 16 byte minimum command size in the future, since
1181: * there are now READ(16) and WRITE(16) commands defined in the
1182: * SBC-2 spec.
1183: */
1184: if (value < 6)
1185: value = 6;
1186: else if ((value > 6)
1187: && (value <= 10))
1188: value = 10;
1189: else if (value > 10)
1190: value = 12;
1191:
1192: *(int *)arg1 = value;
1193:
1194: return (0);
1195: }
1196:
1197: static cam_status
1198: daregister(struct cam_periph *periph, void *arg)
1199: {
1200: int s;
1201: struct da_softc *softc;
1202: struct ccb_setasync csa;
1203: struct ccb_pathinq cpi;
1204: struct ccb_getdev *cgd;
1205: char tmpstr[80];
1206: caddr_t match;
1207:
1208: cgd = (struct ccb_getdev *)arg;
1209: if (periph == NULL) {
1210: printf("daregister: periph was NULL!!\n");
1211: return(CAM_REQ_CMP_ERR);
1212: }
1213:
1214: if (cgd == NULL) {
1215: printf("daregister: no getdev CCB, can't register device\n");
1216: return(CAM_REQ_CMP_ERR);
1217: }
1218:
1219: softc = malloc(sizeof(*softc), M_DEVBUF, M_INTWAIT | M_ZERO);
1220: LIST_INIT(&softc->pending_ccbs);
1221: softc->state = DA_STATE_PROBE;
1222: bufq_init(&softc->buf_queue);
1223: if (SID_IS_REMOVABLE(&cgd->inq_data))
1224: softc->flags |= DA_FLAG_PACK_REMOVABLE;
1225: if ((cgd->inq_data.flags & SID_CmdQue) != 0)
1226: softc->flags |= DA_FLAG_TAGGED_QUEUING;
1227:
1228: periph->softc = softc;
1229:
1230: cam_extend_set(daperiphs, periph->unit_number, periph);
1231:
1232: /*
1233: * See if this device has any quirks.
1234: */
1235: match = cam_quirkmatch((caddr_t)&cgd->inq_data,
1236: (caddr_t)da_quirk_table,
1237: sizeof(da_quirk_table)/sizeof(*da_quirk_table),
1238: sizeof(*da_quirk_table), scsi_inquiry_match);
1239:
1240: if (match != NULL)
1241: softc->quirks = ((struct da_quirk_entry *)match)->quirks;
1242: else
1243: softc->quirks = DA_Q_NONE;
1244:
1245: TASK_INIT(&softc->sysctl_task, 0, dasysctlinit, periph);
1246:
1247: /* Check if the SIM does not want 6 byte commands */
1248: xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1);
1249: cpi.ccb_h.func_code = XPT_PATH_INQ;
1250: xpt_action((union ccb *)&cpi);
1251: if (cpi.ccb_h.status == CAM_REQ_CMP && (cpi.hba_misc & PIM_NO_6_BYTE))
1252: softc->quirks |= DA_Q_NO_6_BYTE;
1253:
1254: /*
1255: * RBC devices don't have to support READ(6), only READ(10).
1256: */
1257: if (softc->quirks & DA_Q_NO_6_BYTE || SID_TYPE(&cgd->inq_data) == T_RBC)
1258: softc->minimum_cmd_size = 10;
1259: else
1260: softc->minimum_cmd_size = 6;
1261:
1262: /*
1263: * Load the user's default, if any.
1264: */
1265: snprintf(tmpstr, sizeof(tmpstr), "kern.cam.da.%d.minimum_cmd_size",
1266: periph->unit_number);
1267: TUNABLE_INT_FETCH(tmpstr, &softc->minimum_cmd_size);
1268:
1269: /*
1270: * 6, 10 and 12 are the currently permissible values.
1271: */
1272: if (softc->minimum_cmd_size < 6)
1273: softc->minimum_cmd_size = 6;
1274: else if ((softc->minimum_cmd_size > 6)
1275: && (softc->minimum_cmd_size <= 10))
1276: softc->minimum_cmd_size = 10;
1277: else if (softc->minimum_cmd_size > 12)
1278: softc->minimum_cmd_size = 12;
1279:
1280: /*
1281: * Block our timeout handler while we
1282: * add this softc to the dev list.
1283: */
1284: s = splsoftclock();
1285: SLIST_INSERT_HEAD(&softc_list, softc, links);
1286: splx(s);
1287:
1288: /*
1289: * The DA driver supports a blocksize, but
1290: * we don't know the blocksize until we do
1291: * a read capacity. So, set a flag to
1292: * indicate that the blocksize is
1293: * unavailable right now. We'll clear the
1294: * flag as soon as we've done a read capacity.
1295: */
1296: devstat_add_entry(&softc->device_stats, "da",
1297: periph->unit_number, 0,
1298: DEVSTAT_BS_UNAVAILABLE,
1299: SID_TYPE(&cgd->inq_data) | DEVSTAT_TYPE_IF_SCSI,
1300: DEVSTAT_PRIORITY_DISK);
1301:
1302: /*
1303: * Register this media as a disk
1304: */
1305: disk_create(periph->unit_number, &softc->disk, 0, &da_cdevsw);
1306:
1307: /*
1308: * Add async callbacks for bus reset and
1309: * bus device reset calls. I don't bother
1310: * checking if this fails as, in most cases,
1311: * the system will function just fine without
1312: * them and the only alternative would be to
1313: * not attach the device on failure.
1314: */
1315: xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
1316: csa.ccb_h.func_code = XPT_SASYNC_CB;
1317: csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
1318: csa.callback = daasync;
1319: csa.callback_arg = periph;
1320: xpt_action((union ccb *)&csa);
1321: /*
1322: * Lock this peripheral until we are setup.
1323: * This first call can't block
1324: */
1325: (void)cam_periph_lock(periph, 0);
1326: xpt_schedule(periph, /*priority*/5);
1327:
1328: return(CAM_REQ_CMP);
1329: }
1330:
1331: static void
1332: dastart(struct cam_periph *periph, union ccb *start_ccb)
1333: {
1334: struct da_softc *softc;
1335:
1336: softc = (struct da_softc *)periph->softc;
1337:
1338:
1339: switch (softc->state) {
1340: case DA_STATE_NORMAL:
1341: {
1342: /* Pull a buffer from the queue and get going on it */
1343: struct buf *bp;
1344: int s;
1345:
1346: /*
1347: * See if there is a buf with work for us to do..
1348: */
1349: s = splbio();
1350: bp = bufq_first(&softc->buf_queue);
1351: if (periph->immediate_priority <= periph->pinfo.priority) {
1352: CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
1353: ("queuing for immediate ccb\n"));
1354: start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
1355: SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
1356: periph_links.sle);
1357: periph->immediate_priority = CAM_PRIORITY_NONE;
1358: splx(s);
1359: wakeup(&periph->ccb_list);
1360: } else if (bp == NULL) {
1361: splx(s);
1362: xpt_release_ccb(start_ccb);
1363: } else {
1364: int oldspl;
1365: u_int8_t tag_code;
1366:
1367: bufq_remove(&softc->buf_queue, bp);
1368:
1369: devstat_start_transaction(&softc->device_stats);
1370:
1371: if ((bp->b_flags & B_ORDERED) != 0
1372: || (softc->flags & DA_FLAG_NEED_OTAG) != 0) {
1373: softc->flags &= ~DA_FLAG_NEED_OTAG;
1374: softc->ordered_tag_count++;
1375: tag_code = MSG_ORDERED_Q_TAG;
1376: } else {
1377: tag_code = MSG_SIMPLE_Q_TAG;
1378: }
1379: scsi_read_write(&start_ccb->csio,
1380: /*retries*/da_retry_count,
1381: dadone,
1382: tag_code,
1383: bp->b_flags & B_READ,
1384: /*byte2*/0,
1385: softc->minimum_cmd_size,
1386: bp->b_pblkno,
1387: bp->b_bcount / softc->params.secsize,
1388: bp->b_data,
1389: bp->b_bcount,
1390: /*sense_len*/SSD_FULL_SIZE,
1391: da_default_timeout * 1000);
1392: start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
1393:
1394: /*
1395: * Block out any asyncronous callbacks
1396: * while we touch the pending ccb list.
1397: */
1398: oldspl = splcam();
1399: LIST_INSERT_HEAD(&softc->pending_ccbs,
1400: &start_ccb->ccb_h, periph_links.le);
1401: splx(oldspl);
1402:
1403: /* We expect a unit attention from this device */
1404: if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
1405: start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
1406: softc->flags &= ~DA_FLAG_RETRY_UA;
1407: }
1408:
1409: start_ccb->ccb_h.ccb_bp = bp;
1410: bp = bufq_first(&softc->buf_queue);
1411: splx(s);
1412:
1413: xpt_action(start_ccb);
1414: }
1415:
1416: if (bp != NULL) {
1417: /* Have more work to do, so ensure we stay scheduled */
1418: xpt_schedule(periph, /* XXX priority */1);
1419: }
1420: break;
1421: }
1422: case DA_STATE_PROBE:
1423: {
1424: struct ccb_scsiio *csio;
1425: struct scsi_read_capacity_data *rcap;
1426:
1427: rcap = malloc(sizeof(*rcap), M_TEMP, M_INTWAIT | M_ZERO);
1428: csio = &start_ccb->csio;
1429: scsi_read_capacity(csio,
1430: /*retries*/4,
1431: dadone,
1432: MSG_SIMPLE_Q_TAG,
1433: rcap,
1434: SSD_FULL_SIZE,
1435: /*timeout*/5000);
1436: start_ccb->ccb_h.ccb_bp = NULL;
1437: start_ccb->ccb_h.ccb_state = DA_CCB_PROBE;
1438: xpt_action(start_ccb);
1439: break;
1440: }
1441: }
1442: }
1443:
1444: static int
1445: cmd6workaround(union ccb *ccb)
1446: {
1447: struct scsi_rw_6 cmd6;
1448: struct scsi_rw_10 *cmd10;
1449: struct da_softc *softc;
1450: u_int8_t *cdb;
1451: int frozen;
1452:
1453: cdb = ccb->csio.cdb_io.cdb_bytes;
1454:
1455: /* Translation only possible if CDB is an array and cmd is R/W6 */
1456: if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0 ||
1457: (*cdb != READ_6 && *cdb != WRITE_6))
1458: return 0;
1459:
1460: xpt_print_path(ccb->ccb_h.path);
1461: printf("READ(6)/WRITE(6) not supported, "
1462: "increasing minimum_cmd_size to 10.\n");
1463: softc = (struct da_softc *)xpt_path_periph(ccb->ccb_h.path)->softc;
1464: softc->minimum_cmd_size = 10;
1465:
1466: bcopy(cdb, &cmd6, sizeof(struct scsi_rw_6));
1467: cmd10 = (struct scsi_rw_10 *)cdb;
1468: cmd10->opcode = (cmd6.opcode == READ_6) ? READ_10 : WRITE_10;
1469: cmd10->byte2 = 0;
1470: scsi_ulto4b(scsi_3btoul(cmd6.addr), cmd10->addr);
1471: cmd10->reserved = 0;
1472: scsi_ulto2b(cmd6.length, cmd10->length);
1473: cmd10->control = cmd6.control;
1474: ccb->csio.cdb_len = sizeof(*cmd10);
1475:
1476: /* Requeue request, unfreezing queue if necessary */
1477: frozen = (ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
1478: ccb->ccb_h.status = CAM_REQUEUE_REQ;
1479: xpt_action(ccb);
1480: if (frozen) {
1481: cam_release_devq(ccb->ccb_h.path,
1482: /*relsim_flags*/0,
1483: /*reduction*/0,
1484: /*timeout*/0,
1485: /*getcount_only*/0);
1486: }
1487: return (ERESTART);
1488: }
1489:
1490: static void
1491: dadone(struct cam_periph *periph, union ccb *done_ccb)
1492: {
1493: struct da_softc *softc;
1494: struct ccb_scsiio *csio;
1495:
1496: softc = (struct da_softc *)periph->softc;
1497: csio = &done_ccb->csio;
1498: switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
1499: case DA_CCB_BUFFER_IO:
1500: {
1501: struct buf *bp;
1502: int oldspl;
1503:
1504: bp = (struct buf *)done_ccb->ccb_h.ccb_bp;
1505: if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1506: int error;
1507: int s;
1508: int sf;
1509:
1510: if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
1511: sf = SF_RETRY_UA;
1512: else
1513: sf = 0;
1514:
1515: /* Retry selection timeouts */
1516: sf |= SF_RETRY_SELTO;
1517:
1518: if ((error = daerror(done_ccb, 0, sf)) == ERESTART) {
1519: /*
1520: * A retry was scheuled, so
1521: * just return.
1522: */
1523: return;
1524: }
1525: if (error != 0) {
1526: struct buf *q_bp;
1527:
1528: s = splbio();
1529:
1530: if (error == ENXIO) {
1531: /*
1532: * Catastrophic error. Mark our pack as
1533: * invalid.
1534: */
1535: /* XXX See if this is really a media
1536: * change first.
1537: */
1538: xpt_print_path(periph->path);
1539: printf("Invalidating pack\n");
1540: softc->flags |= DA_FLAG_PACK_INVALID;
1541: }
1542:
1543: /*
1544: * return all queued I/O with EIO, so that
1545: * the client can retry these I/Os in the
1546: * proper order should it attempt to recover.
1547: */
1548: while ((q_bp = bufq_first(&softc->buf_queue))
1549: != NULL) {
1550: bufq_remove(&softc->buf_queue, q_bp);
1551: q_bp->b_resid = q_bp->b_bcount;
1552: q_bp->b_error = EIO;
1553: q_bp->b_flags |= B_ERROR;
1554: biodone(q_bp);
1555: }
1556: splx(s);
1557: bp->b_error = error;
1558: bp->b_resid = bp->b_bcount;
1559: bp->b_flags |= B_ERROR;
1560: } else {
1561: bp->b_resid = csio->resid;
1562: bp->b_error = 0;
1563: if (bp->b_resid != 0)
1564: bp->b_flags |= B_ERROR;
1565: }
1566: if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
1567: cam_release_devq(done_ccb->ccb_h.path,
1568: /*relsim_flags*/0,
1569: /*reduction*/0,
1570: /*timeout*/0,
1571: /*getcount_only*/0);
1572: } else {
1573: bp->b_resid = csio->resid;
1574: if (csio->resid > 0)
1575: bp->b_flags |= B_ERROR;
1576: }
1577:
1578: /*
1579: * Block out any asyncronous callbacks
1580: * while we touch the pending ccb list.
1581: */
1582: oldspl = splcam();
1583: LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
1584: splx(oldspl);
1585:
1586: if (softc->device_stats.busy_count == 0)
1587: softc->flags |= DA_FLAG_WENT_IDLE;
1588:
1589: devstat_end_transaction_buf(&softc->device_stats, bp);
1590: biodone(bp);
1591: break;
1592: }
1593: case DA_CCB_PROBE:
1594: {
1595: struct scsi_read_capacity_data *rdcap;
1596: char announce_buf[80];
1597:
1598: rdcap = (struct scsi_read_capacity_data *)csio->data_ptr;
1599:
1600: if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
1601: struct disk_params *dp;
1602:
1603: dasetgeom(periph, rdcap);
1604: dp = &softc->params;
1605: snprintf(announce_buf, sizeof(announce_buf),
1606: "%luMB (%u %u byte sectors: %dH %dS/T %dC)",
1607: (unsigned long) (((u_int64_t)dp->secsize *
1608: dp->sectors) / (1024*1024)), dp->sectors,
1609: dp->secsize, dp->heads, dp->secs_per_track,
1610: dp->cylinders);
1611: } else {
1612: int error;
1613:
1614: announce_buf[0] = '\0';
1615:
1616: /*
1617: * Retry any UNIT ATTENTION type errors. They
1618: * are expected at boot.
1619: */
1620: error = daerror(done_ccb, 0, SF_RETRY_UA |
1621: SF_RETRY_SELTO | SF_NO_PRINT);
1622: if (error == ERESTART) {
1623: /*
1624: * A retry was scheuled, so
1625: * just return.
1626: */
1627: return;
1628: } else if (error != 0) {
1629: struct scsi_sense_data *sense;
1630: int asc, ascq;
1631: int sense_key, error_code;
1632: int have_sense;
1633: cam_status status;
1634: struct ccb_getdev cgd;
1635:
1636: /* Don't wedge this device's queue */
1637: cam_release_devq(done_ccb->ccb_h.path,
1638: /*relsim_flags*/0,
1639: /*reduction*/0,
1640: /*timeout*/0,
1641: /*getcount_only*/0);
1642:
1643: status = done_ccb->ccb_h.status;
1644:
1645: xpt_setup_ccb(&cgd.ccb_h,
1646: done_ccb->ccb_h.path,
1647: /* priority */ 1);
1648: cgd.ccb_h.func_code = XPT_GDEV_TYPE;
1649: xpt_action((union ccb *)&cgd);
1650:
1651: if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0)
1652: || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0)
1653: || ((status & CAM_AUTOSNS_VALID) == 0))
1654: have_sense = FALSE;
1655: else
1656: have_sense = TRUE;
1657:
1658: if (have_sense) {
1659: sense = &csio->sense_data;
1660: scsi_extract_sense(sense, &error_code,
1661: &sense_key,
1662: &asc, &ascq);
1663: }
1664: /*
1665: * Attach to anything that claims to be a
1666: * direct access or optical disk device,
1667: * as long as it doesn't return a "Logical
1668: * unit not supported" (0x25) error.
1669: */
1670: if ((have_sense) && (asc != 0x25)
1671: && (error_code == SSD_CURRENT_ERROR))
1672: snprintf(announce_buf,
1673: sizeof(announce_buf),
1674: "Attempt to query device "
1675: "size failed: %s, %s",
1676: scsi_sense_key_text[sense_key],
1677: scsi_sense_desc(asc,ascq,
1678: &cgd.inq_data));
1679: else {
1680: if (have_sense)
1681: scsi_sense_print(
1682: &done_ccb->csio);
1683: else {
1684: xpt_print_path(periph->path);
1685: printf("got CAM status %#x\n",
1686: done_ccb->ccb_h.status);
1687: }
1688:
1689: xpt_print_path(periph->path);
1690: printf("fatal error, failed"
1691: " to attach to device\n");
1692:
1693: /*
1694: * Free up resources.
1695: */
1696: cam_periph_invalidate(periph);
1697: }
1698: }
1699: }
1700: free(rdcap, M_TEMP);
1701: if (announce_buf[0] != '\0') {
1702: xpt_announce_periph(periph, announce_buf);
1703: /*
1704: * Create our sysctl variables, now that we know
1705: * we have successfully attached.
1706: */
1707: taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task);
1708: }
1709: softc->state = DA_STATE_NORMAL;
1710: /*
1711: * Since our peripheral may be invalidated by an error
1712: * above or an external event, we must release our CCB
1713: * before releasing the probe lock on the peripheral.
1714: * The peripheral will only go away once the last lock
1715: * is removed, and we need it around for the CCB release
1716: * operation.
1717: */
1718: xpt_release_ccb(done_ccb);
1719: cam_periph_unlock(periph);
1720: return;
1721: }
1722: case DA_CCB_WAITING:
1723: {
1724: /* Caller will release the CCB */
1725: wakeup(&done_ccb->ccb_h.cbfcnp);
1726: return;
1727: }
1728: case DA_CCB_DUMP:
1729: /* No-op. We're polling */
1730: return;
1731: default:
1732: break;
1733: }
1734: xpt_release_ccb(done_ccb);
1735: }
1736:
1737: static int
1738: daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
1739: {
1740: struct da_softc *softc;
1741: struct cam_periph *periph;
1742: int error;
1743:
1744: periph = xpt_path_periph(ccb->ccb_h.path);
1745: softc = (struct da_softc *)periph->softc;
1746:
1747: /*
1748: * Automatically detect devices that do not support
1749: * READ(6)/WRITE(6) and upgrade to using 10 byte cdbs.
1750: */
1751: error = 0;
1752: if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
1753: error = cmd6workaround(ccb);
1754: } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) ==
1755: CAM_SCSI_STATUS_ERROR)
1756: && (ccb->ccb_h.status & CAM_AUTOSNS_VALID)
1757: && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
1758: && ((ccb->ccb_h.flags & CAM_SENSE_PHYS) == 0)
1759: && ((ccb->ccb_h.flags & CAM_SENSE_PTR) == 0)) {
1760: int sense_key, error_code, asc, ascq;
1761:
1762: scsi_extract_sense(&ccb->csio.sense_data,
1763: &error_code, &sense_key, &asc, &ascq);
1764: if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
1765: error = cmd6workaround(ccb);
1766: }
1767: if (error == ERESTART)
1768: return (ERESTART);
1769:
1770: /*
1771: * XXX
1772: * Until we have a better way of doing pack validation,
1773: * don't treat UAs as errors.
1774: */
1775: sense_flags |= SF_RETRY_UA;
1776: return(cam_periph_error(ccb, cam_flags, sense_flags,
1777: &softc->saved_ccb));
1778: }
1779:
1780: static void
1781: daprevent(struct cam_periph *periph, int action)
1782: {
1783: struct da_softc *softc;
1784: union ccb *ccb;
1785: int error;
1786:
1787: softc = (struct da_softc *)periph->softc;
1788:
1789: if (((action == PR_ALLOW)
1790: && (softc->flags & DA_FLAG_PACK_LOCKED) == 0)
1791: || ((action == PR_PREVENT)
1792: && (softc->flags & DA_FLAG_PACK_LOCKED) != 0)) {
1793: return;
1794: }
1795:
1796: ccb = cam_periph_getccb(periph, /*priority*/1);
1797:
1798: scsi_prevent(&ccb->csio,
1799: /*retries*/1,
1800: /*cbcfp*/dadone,
1801: MSG_SIMPLE_Q_TAG,
1802: action,
1803: SSD_FULL_SIZE,
1804: 5000);
1805:
1806: error = cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
1807: /*sense_flags*/0, &softc->device_stats);
1808:
1809: if (error == 0) {
1810: if (action == PR_ALLOW)
1811: softc->flags &= ~DA_FLAG_PACK_LOCKED;
1812: else
1813: softc->flags |= DA_FLAG_PACK_LOCKED;
1814: }
1815:
1816: xpt_release_ccb(ccb);
1817: }
1818:
1819: static void
1820: dasetgeom(struct cam_periph *periph, struct scsi_read_capacity_data * rdcap)
1821: {
1822: struct ccb_calc_geometry ccg;
1823: struct da_softc *softc;
1824: struct disk_params *dp;
1825:
1826: softc = (struct da_softc *)periph->softc;
1827:
1828: dp = &softc->params;
1829: dp->secsize = scsi_4btoul(rdcap->length);
1830: dp->sectors = scsi_4btoul(rdcap->addr) + 1;
1831: /*
1832: * Have the controller provide us with a geometry
1833: * for this disk. The only time the geometry
1834: * matters is when we boot and the controller
1835: * is the only one knowledgeable enough to come
1836: * up with something that will make this a bootable
1837: * device.
1838: */
1839: xpt_setup_ccb(&ccg.ccb_h, periph->path, /*priority*/1);
1840: ccg.ccb_h.func_code = XPT_CALC_GEOMETRY;
1841: ccg.block_size = dp->secsize;
1842: ccg.volume_size = dp->sectors;
1843: ccg.heads = 0;
1844: ccg.secs_per_track = 0;
1845: ccg.cylinders = 0;
1846: xpt_action((union ccb*)&ccg);
1847: dp->heads = ccg.heads;
1848: dp->secs_per_track = ccg.secs_per_track;
1849: dp->cylinders = ccg.cylinders;
1850: }
1851:
1852: static void
1853: dasendorderedtag(void *arg)
1854: {
1855: struct da_softc *softc;
1856: int s;
1857:
1858: for (softc = SLIST_FIRST(&softc_list);
1859: softc != NULL;
1860: softc = SLIST_NEXT(softc, links)) {
1861: s = splsoftcam();
1862: if ((softc->ordered_tag_count == 0)
1863: && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
1864: softc->flags |= DA_FLAG_NEED_OTAG;
1865: }
1866: if (softc->device_stats.busy_count > 0)
1867: softc->flags &= ~DA_FLAG_WENT_IDLE;
1868:
1869: softc->ordered_tag_count = 0;
1870: splx(s);
1871: }
1872: /* Queue us up again */
1873: timeout(dasendorderedtag, NULL,
1874: (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL);
1875: }
1876:
1877: /*
1878: * Step through all DA peripheral drivers, and if the device is still open,
1879: * sync the disk cache to physical media.
1880: */
1881: static void
1882: dashutdown(void * arg, int howto)
1883: {
1884: struct cam_periph *periph;
1885: struct da_softc *softc;
1886:
1887: for (periph = TAILQ_FIRST(&dadriver.units); periph != NULL;
1888: periph = TAILQ_NEXT(periph, unit_links)) {
1889: union ccb ccb;
1890: softc = (struct da_softc *)periph->softc;
1891:
1892: /*
1893: * We only sync the cache if the drive is still open, and
1894: * if the drive is capable of it..
1895: */
1896: if (((softc->flags & DA_FLAG_OPEN) == 0)
1897: || (softc->quirks & DA_Q_NO_SYNC_CACHE))
1898: continue;
1899:
1900: xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1);
1901:
1902: ccb.ccb_h.ccb_state = DA_CCB_DUMP;
1903: scsi_synchronize_cache(&ccb.csio,
1904: /*retries*/1,
1905: /*cbfcnp*/dadone,
1906: MSG_SIMPLE_Q_TAG,
1907: /*begin_lba*/0, /* whole disk */
1908: /*lb_count*/0,
1909: SSD_FULL_SIZE,
1910: 5 * 60 * 1000);
1911:
1912: xpt_polled_action(&ccb);
1913:
1914: if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1915: if (((ccb.ccb_h.status & CAM_STATUS_MASK) ==
1916: CAM_SCSI_STATUS_ERROR)
1917: && (ccb.csio.scsi_status == SCSI_STATUS_CHECK_COND)){
1918: int error_code, sense_key, asc, ascq;
1919:
1920: scsi_extract_sense(&ccb.csio.sense_data,
1921: &error_code, &sense_key,
1922: &asc, &ascq);
1923:
1924: if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
1925: scsi_sense_print(&ccb.csio);
1926: } else {
1927: xpt_print_path(periph->path);
1928: printf("Synchronize cache failed, status "
1929: "== 0x%x, scsi status == 0x%x\n",
1930: ccb.ccb_h.status, ccb.csio.scsi_status);
1931: }
1932: }
1933:
1934: if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
1935: cam_release_devq(ccb.ccb_h.path,
1936: /*relsim_flags*/0,
1937: /*reduction*/0,
1938: /*timeout*/0,
1939: /*getcount_only*/0);
1940:
1941: }
1942: }
1943:
1944: #else /* !_KERNEL */
1945:
1946: /*
1947: * XXX This is only left out of the kernel build to silence warnings. If,
1948: * for some reason this function is used in the kernel, the ifdefs should
1949: * be moved so it is included both in the kernel and userland.
1950: */
1951: void
1952: scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries,
1953: void (*cbfcnp)(struct cam_periph *, union ccb *),
1954: u_int8_t tag_action, u_int8_t byte2, u_int16_t ileave,
1955: u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
1956: u_int32_t timeout)
1957: {
1958: struct scsi_format_unit *scsi_cmd;
1959:
1960: scsi_cmd = (struct scsi_format_unit *)&csio->cdb_io.cdb_bytes;
1961: scsi_cmd->opcode = FORMAT_UNIT;
1962: scsi_cmd->byte2 = byte2;
1963: scsi_ulto2b(ileave, scsi_cmd->interleave);
1964:
1965: cam_fill_csio(csio,
1966: retries,
1967: cbfcnp,
1968: /*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
1969: tag_action,
1970: data_ptr,
1971: dxfer_len,
1972: sense_len,
1973: sizeof(*scsi_cmd),
1974: timeout);
1975: }
1976:
1977: #endif /* _KERNEL */