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