Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / usb / scsa2usb / scsa2usb.c
blobbab9d9cf689c6436a9f9264db1dc3acdd32a3253
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2016 Joyent, Inc.
26 * Copyright (c) 2016 by Delphix. All rights reserved.
31 * scsa2usb bridge nexus driver:
33 * This driver supports the following wire transports:
34 * a. Bulk Only transport (see usb_ms_bulkonly.c)
35 * b. CB transport (see usb_ms_cbi.c)
36 * c. CBI transport with interrupt status completion (see usb_ms_cbi.c)
38 * It handles the following command sets:
39 * a. SCSI
40 * b. ATAPI command set (subset of SCSI command set)
41 * c. UFI command set (
42 * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf)
44 * For details on USB Mass Storage Class overview:
45 * http://www.usb.org/developers/devclass_docs/usbmassover_11.pdf
48 #include <sys/usb/usba/usbai_version.h>
49 #include <sys/scsi/scsi.h>
50 #include <sys/cdio.h>
51 #include <sys/sunndi.h>
52 #include <sys/esunddi.h>
53 #include <sys/callb.h>
54 #include <sys/kobj.h>
55 #include <sys/kobj_lex.h>
56 #include <sys/strsubr.h>
57 #include <sys/strsun.h>
58 #include <sys/sysmacros.h>
60 #include <sys/usb/usba.h>
61 #include <sys/usb/clients/ugen/usb_ugen.h>
62 #include <sys/usb/usba/usba_ugen.h>
64 #include <sys/usb/usba/usba_private.h>
65 #include <sys/usb/usba/usba_ugend.h>
66 #include <sys/usb/clients/mass_storage/usb_bulkonly.h>
67 #include <sys/usb/scsa2usb/scsa2usb.h>
70 * Function Prototypes
72 static int scsa2usb_attach(dev_info_t *, ddi_attach_cmd_t);
73 static int scsa2usb_info(dev_info_t *, ddi_info_cmd_t, void *,
74 void **);
75 static int scsa2usb_detach(dev_info_t *, ddi_detach_cmd_t);
76 static int scsa2usb_cleanup(dev_info_t *, scsa2usb_state_t *);
77 static void scsa2usb_validate_attrs(scsa2usb_state_t *);
78 static void scsa2usb_create_luns(scsa2usb_state_t *);
79 static int scsa2usb_is_usb(dev_info_t *);
80 static void scsa2usb_fake_inquiry(scsa2usb_state_t *,
81 struct scsi_inquiry *);
82 static void scsa2usb_do_inquiry(scsa2usb_state_t *,
83 uint_t, uint_t);
84 static int scsa2usb_do_tur(scsa2usb_state_t *, struct scsi_address *);
86 /* override property handling */
87 static void scsa2usb_override(scsa2usb_state_t *);
88 static int scsa2usb_parse_input_str(char *, scsa2usb_ov_t *,
89 scsa2usb_state_t *);
90 static void scsa2usb_override_error(char *, scsa2usb_state_t *);
91 static char *scsa2usb_strtok_r(char *, char *, char **);
94 /* PANIC callback handling */
95 static void scsa2usb_panic_callb_init(scsa2usb_state_t *);
96 static void scsa2usb_panic_callb_fini(scsa2usb_state_t *);
97 static boolean_t scsa2usb_panic_callb(void *, int);
99 /* SCSA support */
100 static int scsa2usb_scsi_tgt_probe(struct scsi_device *, int (*)(void));
101 static int scsa2usb_scsi_tgt_init(dev_info_t *, dev_info_t *,
102 scsi_hba_tran_t *, struct scsi_device *);
103 static void scsa2usb_scsi_tgt_free(dev_info_t *, dev_info_t *,
104 scsi_hba_tran_t *, struct scsi_device *);
105 static struct scsi_pkt *scsa2usb_scsi_init_pkt(struct scsi_address *,
106 struct scsi_pkt *, struct buf *, int, int,
107 int, int, int (*)(), caddr_t);
108 static void scsa2usb_scsi_destroy_pkt(struct scsi_address *,
109 struct scsi_pkt *);
110 static int scsa2usb_scsi_start(struct scsi_address *, struct scsi_pkt *);
111 static int scsa2usb_scsi_abort(struct scsi_address *, struct scsi_pkt *);
112 static int scsa2usb_scsi_reset(struct scsi_address *, int);
113 static int scsa2usb_scsi_getcap(struct scsi_address *, char *, int);
114 static int scsa2usb_scsi_setcap(struct scsi_address *, char *, int, int);
115 static int scsa2usb_scsi_bus_config(dev_info_t *, uint_t,
116 ddi_bus_config_op_t, void *, dev_info_t **);
117 static int scsa2usb_scsi_bus_unconfig(dev_info_t *, uint_t,
118 ddi_bus_config_op_t, void *);
120 /* functions for command and transport support */
121 static void scsa2usb_prepare_pkt(scsa2usb_state_t *, struct scsi_pkt *);
122 static int scsa2usb_cmd_transport(scsa2usb_state_t *, scsa2usb_cmd_t *);
123 static int scsa2usb_check_bulkonly_blacklist_attrs(scsa2usb_state_t *,
124 scsa2usb_cmd_t *, uchar_t);
125 static int scsa2usb_check_ufi_blacklist_attrs(scsa2usb_state_t *, uchar_t,
126 scsa2usb_cmd_t *);
127 static int scsa2usb_handle_scsi_cmd_sub_class(scsa2usb_state_t *,
128 scsa2usb_cmd_t *, struct scsi_pkt *);
129 static int scsa2usb_handle_ufi_subclass_cmd(scsa2usb_state_t *,
130 scsa2usb_cmd_t *, struct scsi_pkt *);
132 /* waitQ handling */
133 static void scsa2usb_work_thread(void *);
134 static void scsa2usb_transport_request(scsa2usb_state_t *, uint_t);
135 static void scsa2usb_flush_waitQ(scsa2usb_state_t *, uint_t, uchar_t);
136 static int scsa2usb_all_waitQs_empty(scsa2usb_state_t *);
138 /* auto request sense handling */
139 static int scsa2usb_create_arq_pkt(scsa2usb_state_t *,
140 struct scsi_address *);
141 static void scsa2usb_delete_arq_pkt(scsa2usb_state_t *);
142 static void scsa2usb_complete_arq_pkt(scsa2usb_state_t *, struct scsi_pkt *,
143 scsa2usb_cmd_t *, struct buf *);
145 /* utility functions for any transport */
146 static int scsa2usb_open_usb_pipes(scsa2usb_state_t *);
147 void scsa2usb_close_usb_pipes(scsa2usb_state_t *);
149 static void scsa2usb_fill_up_cdb_len(scsa2usb_cmd_t *, int);
150 static void scsa2usb_fill_up_cdb_lba(scsa2usb_cmd_t *, int);
151 static void scsa2usb_fill_up_ReadCD_cdb_len(scsa2usb_cmd_t *, int, int);
152 static void scsa2usb_fill_up_12byte_cdb_len(scsa2usb_cmd_t *, int, int);
153 static int scsa2usb_read_cd_blk_size(uchar_t);
154 int scsa2usb_rw_transport(scsa2usb_state_t *, struct scsi_pkt *);
155 void scsa2usb_setup_next_xfer(scsa2usb_state_t *, scsa2usb_cmd_t *);
157 static mblk_t *scsa2usb_bp_to_mblk(scsa2usb_state_t *);
158 int scsa2usb_handle_data_start(scsa2usb_state_t *,
159 scsa2usb_cmd_t *, usb_bulk_req_t *);
160 void scsa2usb_handle_data_done(scsa2usb_state_t *,
161 scsa2usb_cmd_t *cmd, usb_bulk_req_t *);
163 usb_bulk_req_t *scsa2usb_init_bulk_req(scsa2usb_state_t *,
164 size_t, uint_t, usb_req_attrs_t, usb_flags_t);
165 int scsa2usb_bulk_timeout(int);
166 int scsa2usb_clear_ept_stall(scsa2usb_state_t *, uint_t,
167 usb_pipe_handle_t, char *);
168 static void scsa2usb_pkt_completion(scsa2usb_state_t *, struct scsi_pkt *);
170 /* event handling */
171 static int scsa2usb_reconnect_event_cb(dev_info_t *);
172 static int scsa2usb_disconnect_event_cb(dev_info_t *);
173 static int scsa2usb_cpr_suspend(dev_info_t *);
174 static void scsa2usb_cpr_resume(dev_info_t *);
175 static void scsa2usb_restore_device_state(dev_info_t *, scsa2usb_state_t *);
177 /* PM handling */
178 static void scsa2usb_create_pm_components(dev_info_t *, scsa2usb_state_t *);
179 static void scsa2usb_raise_power(scsa2usb_state_t *);
180 static int scsa2usb_pwrlvl0(scsa2usb_state_t *);
181 static int scsa2usb_pwrlvl1(scsa2usb_state_t *);
182 static int scsa2usb_pwrlvl2(scsa2usb_state_t *);
183 static int scsa2usb_pwrlvl3(scsa2usb_state_t *);
184 static int scsa2usb_power(dev_info_t *, int comp, int level);
185 static void scsa2usb_pm_busy_component(scsa2usb_state_t *);
186 static void scsa2usb_pm_idle_component(scsa2usb_state_t *);
188 /* external functions for Bulk only (BO) support */
189 extern int scsa2usb_bulk_only_transport(scsa2usb_state_t *,
190 scsa2usb_cmd_t *);
191 extern int scsa2usb_bulk_only_get_max_lun(scsa2usb_state_t *);
193 /* external functions for CB/CBI support */
194 extern int scsa2usb_cbi_transport(scsa2usb_state_t *, scsa2usb_cmd_t *);
195 extern void scsa2usb_cbi_stop_intr_polling(scsa2usb_state_t *);
198 /* cmd decoding */
199 static char *scsa2usb_cmds[] = {
200 "\000tur",
201 "\001rezero",
202 "\003rqsense",
203 "\004format",
204 "\014cartprot",
205 "\022inquiry",
206 "\026tranlba",
207 "\030fmtverify",
208 "\032modesense",
209 "\033start",
210 "\035snddiag",
211 "\036doorlock",
212 "\043formatcap",
213 "\045readcap",
214 "\050read10",
215 "\052write10",
216 "\053seek10",
217 "\056writeverify",
218 "\057verify",
219 "\065synchcache",
220 "\076readlong",
221 "\077writelong",
222 "\102readsubchan",
223 "\103readtoc",
224 "\104readhdr",
225 "\105playaudio10",
226 "\107playaudio_msf",
227 "\110playaudio_ti",
228 "\111playtrk_r10",
229 "\112geteventnotify",
230 "\113pause_resume",
231 "\116stop/play_scan",
232 "\121readdiscinfo",
233 "\122readtrkinfo",
234 "\123reservedtrk",
235 "\124sendopcinfo",
236 "\125modeselect",
237 "\132modesense",
238 "\133closetrksession",
239 "\135sendcuesheet",
240 "\136prin",
241 "\137prout",
242 "\241blankcd",
243 "\245playaudio12",
244 "\250read12",
245 "\251playtrk12",
246 "\252write12",
247 "\254getperf",
248 "\271readcdmsf",
249 "\273setcdspeed",
250 "\275mechanism_sts",
251 "\276readcd",
252 NULL
257 * Mass-Storage devices masquerade as "sd" disks.
259 * These devices may not support all SCSI CDBs in their
260 * entirety due to their hardware implementation limitations.
262 * As such, following is a list of some of the black-listed
263 * devices w/ the attributes that they do not support.
264 * (See scsa2usb.h for description on each attribute)
266 #define X ((uint16_t)(-1))
268 static struct blacklist {
269 uint16_t idVendor; /* vendor ID */
270 uint16_t idProduct; /* product ID */
271 uint16_t bcdDevice; /* device release number in bcd */
272 uint16_t attributes; /* attributes to blacklist */
273 } scsa2usb_blacklist[] = {
274 /* Iomega Zip100 drive (prototype) with flaky bridge */
275 {MS_IOMEGA_VID, MS_IOMEGA_PID1_ZIP100, 0,
276 SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM},
278 /* Iomega Zip100 drive (newer model) with flaky bridge */
279 {MS_IOMEGA_VID, MS_IOMEGA_PID2_ZIP100, 0,
280 SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM},
282 /* Iomega Zip100 drive (newer model) with flaky bridge */
283 {MS_IOMEGA_VID, MS_IOMEGA_PID3_ZIP100, 0,
284 SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM},
286 /* Iomega Zip250 drive */
287 {MS_IOMEGA_VID, MS_IOMEGA_PID_ZIP250, 0, SCSA2USB_ATTRS_GET_LUN},
289 /* Iomega Clik! drive */
290 {MS_IOMEGA_VID, MS_IOMEGA_PID_CLIK, 0,
291 SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP},
293 /* Kingston DataTraveler Stick / PNY Attache Stick */
294 {MS_TOSHIBA_VID, MS_TOSHIBA_PID0, 0,
295 SCSA2USB_ATTRS_GET_LUN},
297 /* PNY Floppy drive */
298 {MS_PNY_VID, MS_PNY_PID0, 0,
299 SCSA2USB_ATTRS_GET_LUN},
301 /* SMSC floppy Device - and its clones */
302 {MS_SMSC_VID, X, 0, SCSA2USB_ATTRS_START_STOP},
304 /* Hagiwara SmartMedia Device */
305 {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID1, 0,
306 SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP},
308 /* Hagiwara CompactFlash Device */
309 {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID2, 0,
310 SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP},
312 /* Hagiwara SmartMedia/CompactFlash Combo Device */
313 {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID3, 0,
314 SCSA2USB_ATTRS_START_STOP},
316 /* Hagiwara new SM Device */
317 {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID4, 0,
318 SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP},
320 /* Hagiwara new CF Device */
321 {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID5, 0,
322 SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP},
324 /* Mitsumi CD-RW Device(s) */
325 {MS_MITSUMI_VID, X, X, SCSA2USB_ATTRS_BIG_TIMEOUT |
326 SCSA2USB_ATTRS_GET_CONF | SCSA2USB_ATTRS_GET_PERF},
328 /* Neodio Technologies Corporation SM/CF/MS/SD Combo Device */
329 {MS_NEODIO_VID, MS_NEODIO_DEVICE_3050, 0,
330 SCSA2USB_ATTRS_MODE_SENSE },
332 /* dumb flash devices */
333 {MS_SONY_FLASH_VID, MS_SONY_FLASH_PID, 0,
334 SCSA2USB_ATTRS_REDUCED_CMD},
336 {MS_TREK_FLASH_VID, MS_TREK_FLASH_PID, 0,
337 SCSA2USB_ATTRS_REDUCED_CMD},
339 {MS_PENN_FLASH_VID, MS_PENN_FLASH_PID, 0,
340 SCSA2USB_ATTRS_REDUCED_CMD},
342 /* SimpleTech UCF-100 CF Device */
343 {MS_SIMPLETECH_VID, MS_SIMPLETECH_PID1, 0,
344 SCSA2USB_ATTRS_REDUCED_CMD},
346 {MS_ADDONICS_CARD_READER_VID, MS_ADDONICS_CARD_READER_PID,
347 0, SCSA2USB_ATTRS_REDUCED_CMD},
349 /* Acomdata 80GB USB/1394 Hard Disk */
350 {MS_ACOMDATA_VID, MS_ACOMDATA_PID1, 0,
351 SCSA2USB_ATTRS_USE_CSW_RESIDUE},
353 /* OTi6828 Flash Disk */
354 {MS_OTI_VID, MS_OTI_DEVICE_6828, 0,
355 SCSA2USB_ATTRS_USE_CSW_RESIDUE},
357 /* AMI Virtual Floppy */
358 {MS_AMI_VID, MS_AMI_VIRTUAL_FLOPPY, 0,
359 SCSA2USB_ATTRS_NO_MEDIA_CHECK},
361 /* ScanLogic USB Storage Device */
362 {MS_SCANLOGIC_VID, MS_SCANLOGIC_PID1, 0,
363 SCSA2USB_ATTRS_NO_CAP_ADJUST},
365 /* Super Top USB 2.0 IDE Device */
366 {MS_SUPERTOP_VID, MS_SUPERTOP_DEVICE_6600, 0,
367 SCSA2USB_ATTRS_USE_CSW_RESIDUE},
369 /* Aigo Miniking Device NEHFSP14 */
370 {MS_AIGO_VID, MS_AIGO_DEVICE_6981, 0,
371 SCSA2USB_ATTRS_USE_CSW_RESIDUE},
373 /* Alcor Micro Corp 6387 flash disk */
374 {MS_ALCOR_VID, MS_ALCOR_PID0, 0,
375 SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_USE_CSW_RESIDUE},
377 /* Western Digital External HDD */
378 {MS_WD_VID, MS_WD_PID, 0,
379 SCSA2USB_ATTRS_INQUIRY_EVPD}
383 #define N_SCSA2USB_BLACKLIST (sizeof (scsa2usb_blacklist))/ \
384 sizeof (struct blacklist)
387 * Attribute values can be overridden by values
388 * contained in the scsa2usb.conf file.
389 * These arrays define possible user input values.
392 struct scsa2usb_subclass_protocol_override {
393 char *name;
394 int value;
397 static struct scsa2usb_subclass_protocol_override scsa2usb_protocol[] = {
398 {"CB", SCSA2USB_CB_PROTOCOL},
399 {"CBI", SCSA2USB_CBI_PROTOCOL},
400 {"BO", SCSA2USB_BULK_ONLY_PROTOCOL}
403 static struct scsa2usb_subclass_protocol_override scsa2usb_subclass[] = {
404 {"SCSI", SCSA2USB_SCSI_CMDSET},
405 {"ATAPI", SCSA2USB_ATAPI_CMDSET},
406 {"UFI", SCSA2USB_UFI_CMDSET}
410 #define N_SCSA2USB_SUBC_OVERRIDE (sizeof (scsa2usb_subclass))/ \
411 sizeof (struct scsa2usb_subclass_protocol_override)
413 #define N_SCSA2USB_PROT_OVERRIDE (sizeof (scsa2usb_protocol))/ \
414 sizeof (struct scsa2usb_subclass_protocol_override)
416 /* global variables */
417 static void *scsa2usb_statep; /* for soft state */
418 static boolean_t scsa2usb_sync_message = B_TRUE; /* for syncing */
420 /* for debug messages */
421 uint_t scsa2usb_errmask = (uint_t)DPRINT_MASK_ALL;
422 uint_t scsa2usb_errlevel = USB_LOG_L4;
423 uint_t scsa2usb_instance_debug = (uint_t)-1;
424 uint_t scsa2usb_scsi_bus_config_debug = 0;
425 uint_t scsa2usb_long_timeout = 50 * SCSA2USB_BULK_PIPE_TIMEOUT;
429 * Some devices have problems with big bulk transfers,
430 * transfers >= 128kbytes hang the device. This tunable allows to
431 * limit the maximum bulk transfers rate.
433 uint_t scsa2usb_max_bulk_xfer_size = SCSA2USB_MAX_BULK_XFER_SIZE;
436 #ifdef SCSA2USB_BULK_ONLY_TEST
438 * Test BO 13 cases. (See USB Mass Storage Class - Bulk Only Transport).
439 * We are not covering test cases 1, 6, and 12 as these are the "good"
440 * test cases and are tested as part of the normal drive access operations.
442 * NOTE: This is for testing only. It will be replaced by a uscsi test.
443 * Some are listed here while; other test cases are moved to usb_bulkonly.c
445 static int scsa2usb_test_case_5 = 0;
446 int scsa2usb_test_case_8 = 0;
447 int scsa2usb_test_case_10 = 0;
448 static int scsa2usb_test_case_11 = 0;
450 static void scsa2usb_test_mblk(scsa2usb_state_t *, boolean_t);
451 #endif /* SCSA2USB_BULK_ONLY_TEST */
453 static int scsa2usb_ugen_open(dev_t *, int, int, cred_t *);
454 static int scsa2usb_ugen_close(dev_t, int, int, cred_t *);
455 static int scsa2usb_ugen_read(dev_t, struct uio *, cred_t *);
456 static int scsa2usb_ugen_write(dev_t, struct uio *, cred_t *);
457 static int scsa2usb_ugen_poll(dev_t, short, int, short *,
458 struct pollhead **);
460 /* scsa2usb cb_ops */
461 static struct cb_ops scsa2usb_cbops = {
462 scsa2usb_ugen_open, /* open */
463 scsa2usb_ugen_close, /* close */
464 nodev, /* strategy */
465 nodev, /* print */
466 nodev, /* dump */
467 scsa2usb_ugen_read, /* read */
468 scsa2usb_ugen_write, /* write */
469 nodev, /* ioctl */
470 nodev, /* devmap */
471 nodev, /* mmap */
472 nodev, /* segmap */
473 scsa2usb_ugen_poll, /* poll */
474 ddi_prop_op, /* prop_op */
475 NULL, /* stream */
476 D_MP, /* cb_flag */
477 CB_REV, /* rev */
478 nodev, /* int (*cb_aread)() */
479 nodev /* int (*cb_awrite)() */
482 /* modloading support */
483 static struct dev_ops scsa2usb_ops = {
484 DEVO_REV, /* devo_rev, */
485 0, /* refcnt */
486 scsa2usb_info, /* info */
487 nulldev, /* identify */
488 nulldev, /* probe */
489 scsa2usb_attach, /* attach */
490 scsa2usb_detach, /* detach */
491 nodev, /* reset */
492 &scsa2usb_cbops, /* driver operations */
493 NULL, /* bus operations */
494 scsa2usb_power, /* power */
495 ddi_quiesce_not_needed, /* quiesce */
498 static struct modldrv modldrv = {
499 &mod_driverops, /* Module type. This one is a driver */
500 "SCSA to USB Driver", /* Name of the module. */
501 &scsa2usb_ops, /* driver ops */
504 static struct modlinkage modlinkage = {
505 MODREV_1, (void *)&modldrv, NULL
508 /* event support */
509 static usb_event_t scsa2usb_events = {
510 scsa2usb_disconnect_event_cb,
511 scsa2usb_reconnect_event_cb,
512 NULL, NULL
516 _init(void)
518 int rval;
520 if (((rval = ddi_soft_state_init(&scsa2usb_statep,
521 sizeof (scsa2usb_state_t), SCSA2USB_INITIAL_ALLOC)) != 0)) {
523 return (rval);
526 if ((rval = scsi_hba_init(&modlinkage)) != 0) {
527 ddi_soft_state_fini(&scsa2usb_statep);
529 return (rval);
532 if ((rval = mod_install(&modlinkage)) != 0) {
533 scsi_hba_fini(&modlinkage);
534 ddi_soft_state_fini(&scsa2usb_statep);
536 return (rval);
539 return (rval);
544 _fini(void)
546 int rval;
548 if ((rval = mod_remove(&modlinkage)) == 0) {
549 scsi_hba_fini(&modlinkage);
550 ddi_soft_state_fini(&scsa2usb_statep);
553 return (rval);
558 _info(struct modinfo *modinfop)
560 return (mod_info(&modlinkage, modinfop));
565 * scsa2usb_info :
566 * Get minor number, soft state structure etc.
568 /*ARGSUSED*/
569 static int
570 scsa2usb_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
571 void *arg, void **result)
573 scsa2usb_state_t *scsa2usbp = NULL;
574 int error = DDI_FAILURE;
575 int instance = SCSA2USB_MINOR_TO_INSTANCE(getminor((dev_t)arg));
577 switch (infocmd) {
578 case DDI_INFO_DEVT2DEVINFO:
579 if (((scsa2usbp = ddi_get_soft_state(scsa2usb_statep,
580 instance)) != NULL) &&
581 scsa2usbp->scsa2usb_dip) {
582 *result = scsa2usbp->scsa2usb_dip;
583 error = DDI_SUCCESS;
584 } else {
585 *result = NULL;
587 break;
588 case DDI_INFO_DEVT2INSTANCE:
589 *result = (void *)(uintptr_t)instance;
590 error = DDI_SUCCESS;
591 break;
592 default:
593 break;
596 return (error);
601 * scsa2usb_attach:
602 * Attach driver
603 * Allocate a "scsi_hba_tran" - call scsi_hba_tran_alloc()
604 * Invoke scsi_hba_attach_setup
605 * Get the serialno of the device
606 * Open bulk pipes
607 * Create disk child(ren)
608 * Register events
609 * Create and register panic callback
611 * NOTE: Replaced CBW_DIR_OUT with USB_EP_DIR_OUT and CBW_DIR_IN with
612 * USB_EP_DIR_IN as they are the same #defines.
614 static int
615 scsa2usb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
617 int instance = ddi_get_instance(dip);
618 int interface;
619 uint_t lun;
620 boolean_t ept_check = B_TRUE;
621 scsi_hba_tran_t *tran; /* scsi transport */
622 scsa2usb_state_t *scsa2usbp;
623 usb_log_handle_t log_handle;
624 usb_ep_data_t *ep_data;
625 usb_client_dev_data_t *dev_data;
626 usb_alt_if_data_t *altif_data;
627 usb_ugen_info_t usb_ugen_info;
629 USB_DPRINTF_L4(DPRINT_MASK_SCSA, NULL,
630 "scsa2usb_attach: dip = 0x%p", (void *)dip);
632 switch (cmd) {
633 case DDI_ATTACH:
634 break;
635 case DDI_RESUME:
636 scsa2usb_cpr_resume(dip);
638 return (DDI_SUCCESS);
639 default:
640 USB_DPRINTF_L2(DPRINT_MASK_SCSA, NULL,
641 "scsa2usb_attach: failed");
643 return (DDI_FAILURE);
646 /* Allocate softc information */
647 if (ddi_soft_state_zalloc(scsa2usb_statep, instance) != DDI_SUCCESS) {
648 ddi_prop_remove_all(dip);
650 return (DDI_FAILURE);
653 /* get soft state space and initialize */
654 if ((scsa2usbp = ddi_get_soft_state(scsa2usb_statep,
655 instance)) == NULL) {
656 USB_DPRINTF_L2(DPRINT_MASK_SCSA, NULL,
657 "scsa2usb%d: bad soft state", instance);
658 ddi_prop_remove_all(dip);
660 return (DDI_FAILURE);
663 scsa2usbp->scsa2usb_dip = dip;
664 scsa2usbp->scsa2usb_instance = instance;
666 /* allocate a log handle for debug/error messages */
667 scsa2usbp->scsa2usb_log_handle = log_handle =
668 usb_alloc_log_hdl(dip, "s2u",
669 &scsa2usb_errlevel,
670 &scsa2usb_errmask, &scsa2usb_instance_debug,
673 /* attach to USBA */
674 if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
675 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
676 "usb_client_attach failed");
678 goto fail;
680 if (usb_get_dev_data(dip, &dev_data, USB_PARSE_LVL_IF, 0) !=
681 USB_SUCCESS) {
682 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
683 "usb_get_dev_data failed");
685 goto fail;
688 /* initialize the mutex with the right cookie */
689 mutex_init(&scsa2usbp->scsa2usb_mutex, NULL, MUTEX_DRIVER,
690 dev_data->dev_iblock_cookie);
691 cv_init(&scsa2usbp->scsa2usb_transport_busy_cv, NULL, CV_DRIVER, NULL);
693 for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) {
694 usba_init_list(&scsa2usbp->scsa2usb_waitQ[lun], NULL,
695 dev_data->dev_iblock_cookie);
697 mutex_enter(&scsa2usbp->scsa2usb_mutex);
698 scsa2usbp->scsa2usb_dip = dip;
699 scsa2usbp->scsa2usb_instance = instance;
700 scsa2usbp->scsa2usb_attrs = SCSA2USB_ALL_ATTRS;
701 scsa2usbp->scsa2usb_dev_data = dev_data;
704 /* save the default pipe handle */
705 scsa2usbp->scsa2usb_default_pipe = dev_data->dev_default_ph;
707 /* basic inits are done */
708 scsa2usbp->scsa2usb_flags |= SCSA2USB_FLAGS_LOCKS_INIT;
710 USB_DPRINTF_L4(DPRINT_MASK_SCSA, log_handle,
711 "curr_cfg=%ld, curr_if=%d",
712 (long)(dev_data->dev_curr_cfg - &dev_data->dev_cfg[0]),
713 dev_data->dev_curr_if);
715 interface = dev_data->dev_curr_if;
716 scsa2usbp->scsa2usb_intfc_num = dev_data->dev_curr_if;
718 /* now find out relevant descriptors for alternate 0 */
719 altif_data = &dev_data->dev_curr_cfg->cfg_if[interface].if_alt[0];
721 if (altif_data->altif_n_ep == 0) {
722 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
723 "invalid alt 0 for interface %d", interface);
724 mutex_exit(&scsa2usbp->scsa2usb_mutex);
726 goto fail;
729 /* All CB/CBI, BO devices should have this value set */
730 if (altif_data->altif_descr.bInterfaceClass !=
731 USB_CLASS_MASS_STORAGE) {
732 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
733 "invalid interface class (0x%x)",
734 altif_data->altif_descr.bInterfaceClass);
736 scsa2usbp->scsa2usb_intfc_descr = altif_data->altif_descr;
738 /* figure out the endpoints and copy the descr */
739 if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, 0, 0,
740 USB_EP_ATTR_BULK, USB_EP_DIR_OUT)) != NULL) {
741 if (usb_ep_xdescr_fill(USB_EP_XDESCR_CURRENT_VERSION,
742 dip, ep_data, &scsa2usbp->scsa2usb_bulkout_xept) !=
743 USB_SUCCESS) {
745 mutex_exit(&scsa2usbp->scsa2usb_mutex);
747 goto fail;
750 if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, 0, 0,
751 USB_EP_ATTR_BULK, USB_EP_DIR_IN)) != NULL) {
752 if (usb_ep_xdescr_fill(USB_EP_XDESCR_CURRENT_VERSION,
753 dip, ep_data, &scsa2usbp->scsa2usb_bulkin_xept) !=
754 USB_SUCCESS) {
756 mutex_exit(&scsa2usbp->scsa2usb_mutex);
758 goto fail;
761 if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, 0, 0,
762 USB_EP_ATTR_INTR, USB_EP_DIR_IN)) != NULL) {
763 if (usb_ep_xdescr_fill(USB_EP_XDESCR_CURRENT_VERSION,
764 dip, ep_data, &scsa2usbp->scsa2usb_intr_xept) !=
765 USB_SUCCESS) {
767 mutex_exit(&scsa2usbp->scsa2usb_mutex);
769 goto fail;
774 * check here for protocol and subclass supported by this driver
776 * first check if conf file has override values
777 * Note: override values are not used if supplied values are legal
779 scsa2usb_override(scsa2usbp);
781 USB_DPRINTF_L3(DPRINT_MASK_SCSA, log_handle,
782 "protocol=0x%x override=0x%x subclass=0x%x override=0x%x",
783 scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol,
784 scsa2usbp->scsa2usb_protocol_override,
785 scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass,
786 scsa2usbp->scsa2usb_subclass_override);
788 switch (scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol) {
789 case USB_PROTO_MS_CBI:
790 scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_CB_PROTOCOL;
791 break;
792 case USB_PROTO_MS_CBI_WC:
793 scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_CBI_PROTOCOL;
794 break;
795 case USB_PROTO_MS_ISD_1999_SILICN:
796 case USB_PROTO_MS_BULK_ONLY:
797 scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_BULK_ONLY_PROTOCOL;
798 break;
799 default:
800 if (scsa2usbp->scsa2usb_protocol_override) {
801 scsa2usbp->scsa2usb_cmd_protocol |=
802 scsa2usbp->scsa2usb_protocol_override;
803 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
804 "overriding protocol %x",
805 scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol);
806 break;
809 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
810 "unsupported protocol = %x",
811 scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol);
812 mutex_exit(&scsa2usbp->scsa2usb_mutex);
814 goto fail;
817 switch (scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass) {
818 case USB_SUBCLS_MS_SCSI: /* transparent SCSI */
819 scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_SCSI_CMDSET;
820 break;
821 case USB_SUBCLS_MS_SFF8020I:
822 case USB_SUBCLS_MS_SFF8070I:
823 scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_ATAPI_CMDSET;
824 break;
825 case USB_SUBCLS_MS_UFI: /* UFI */
826 scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_UFI_CMDSET;
827 break;
828 default:
829 if (scsa2usbp->scsa2usb_subclass_override) {
830 scsa2usbp->scsa2usb_cmd_protocol |=
831 scsa2usbp->scsa2usb_subclass_override;
832 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
833 "overriding subclass %x",
834 scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass);
835 break;
838 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
839 "unsupported subclass = %x",
840 scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass);
841 mutex_exit(&scsa2usbp->scsa2usb_mutex);
843 goto fail;
846 /* check that we have the right set of endpoint descriptors */
847 if (SCSA2USB_IS_BULK_ONLY(scsa2usbp) || SCSA2USB_IS_CB(scsa2usbp)) {
848 if ((scsa2usbp->scsa2usb_bulkout_ept.bLength == 0) ||
849 (scsa2usbp->scsa2usb_bulkin_ept.bLength == 0)) {
850 ept_check = B_FALSE;
852 } else if (SCSA2USB_IS_CBI(scsa2usbp)) {
853 if ((scsa2usbp->scsa2usb_bulkout_ept.bLength == 0) ||
854 (scsa2usbp->scsa2usb_bulkin_ept.bLength == 0) ||
855 (scsa2usbp->scsa2usb_intr_ept.bLength == 0)) {
856 ept_check = B_FALSE;
860 if (ept_check == B_FALSE) {
861 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
862 "scsa2usb%d doesn't support minimum required endpoints",
863 instance);
864 mutex_exit(&scsa2usbp->scsa2usb_mutex);
866 goto fail;
870 * Validate the black-listed attributes
872 scsa2usb_validate_attrs(scsa2usbp);
874 /* Print the serial number from the registration data */
875 if (scsa2usbp->scsa2usb_dev_data->dev_serial) {
876 USB_DPRINTF_L4(DPRINT_MASK_SCSA,
877 scsa2usbp->scsa2usb_log_handle, "Serial Number = %s",
878 scsa2usbp->scsa2usb_dev_data->dev_serial);
882 * Allocate a SCSA transport structure
884 tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
885 scsa2usbp->scsa2usb_tran = tran;
888 * initialize transport structure
890 tran->tran_hba_private = scsa2usbp;
891 tran->tran_tgt_private = NULL;
892 tran->tran_tgt_init = scsa2usb_scsi_tgt_init;
893 tran->tran_tgt_probe = scsa2usb_scsi_tgt_probe;
894 tran->tran_tgt_free = scsa2usb_scsi_tgt_free;
895 tran->tran_start = scsa2usb_scsi_start;
896 tran->tran_abort = scsa2usb_scsi_abort;
897 tran->tran_reset = scsa2usb_scsi_reset;
898 tran->tran_getcap = scsa2usb_scsi_getcap;
899 tran->tran_setcap = scsa2usb_scsi_setcap;
900 tran->tran_init_pkt = scsa2usb_scsi_init_pkt;
901 tran->tran_destroy_pkt = scsa2usb_scsi_destroy_pkt;
902 tran->tran_dmafree = NULL;
903 tran->tran_sync_pkt = NULL;
904 tran->tran_reset_notify = NULL;
905 tran->tran_get_bus_addr = NULL;
906 tran->tran_get_name = NULL;
907 tran->tran_quiesce = NULL;
908 tran->tran_unquiesce = NULL;
909 tran->tran_bus_reset = NULL;
910 tran->tran_add_eventcall = NULL;
911 tran->tran_get_eventcookie = NULL;
912 tran->tran_post_event = NULL;
913 tran->tran_remove_eventcall = NULL;
914 tran->tran_bus_config = scsa2usb_scsi_bus_config;
915 tran->tran_bus_unconfig = scsa2usb_scsi_bus_unconfig;
918 * register with SCSA as an HBA
919 * Note that the dma attributes are from parent nexus
921 if (scsi_hba_attach_setup(dip, usba_get_hc_dma_attr(dip), tran, 0)) {
922 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
923 "scsi_hba_attach_setup failed");
924 mutex_exit(&scsa2usbp->scsa2usb_mutex);
926 goto fail;
929 scsa2usbp->scsa2usb_flags |= SCSA2USB_FLAGS_HBA_ATTACH_SETUP;
931 /* create minor node */
932 if (ddi_create_minor_node(dip, "scsa2usb", S_IFCHR,
933 instance << SCSA2USB_MINOR_INSTANCE_SHIFT,
934 DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
935 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
936 "scsi_attach: ddi_create_minor_node failed");
937 mutex_exit(&scsa2usbp->scsa2usb_mutex);
939 goto fail;
942 /* open pipes and set scsa2usb_flags */
943 if (scsa2usb_open_usb_pipes(scsa2usbp) == USB_FAILURE) {
944 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
945 "error opening pipes");
946 mutex_exit(&scsa2usbp->scsa2usb_mutex);
948 goto fail;
951 /* set default block size. updated after read cap cmd */
952 for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) {
953 scsa2usbp->scsa2usb_lbasize[lun] = DEV_BSIZE;
956 mutex_exit(&scsa2usbp->scsa2usb_mutex);
958 /* initialize PANIC callback */
959 scsa2usb_panic_callb_init(scsa2usbp);
961 /* finally we are all done 'initializing' the device */
962 mutex_enter(&scsa2usbp->scsa2usb_mutex);
963 scsa2usbp->scsa2usb_dev_state = USB_DEV_ONLINE;
965 /* enable PM, mutex needs to be held across this */
966 scsa2usb_create_pm_components(dip, scsa2usbp);
967 mutex_exit(&scsa2usbp->scsa2usb_mutex);
969 /* register for connect/disconnect events */
970 if (usb_register_event_cbs(scsa2usbp->scsa2usb_dip, &scsa2usb_events,
971 0) != USB_SUCCESS) {
972 USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle,
973 "error cb registering");
974 goto fail;
977 /* free the dev_data tree, we no longer need it */
978 usb_free_descr_tree(dip, dev_data);
980 scsa2usb_pm_idle_component(scsa2usbp);
982 /* log the conf file override string if there is one */
983 if (scsa2usbp->scsa2usb_override_str) {
984 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
985 "scsa2usb.conf override: %s",
986 scsa2usbp->scsa2usb_override_str);
989 if (usb_owns_device(dip)) {
990 /* get a ugen handle */
991 bzero(&usb_ugen_info, sizeof (usb_ugen_info));
992 usb_ugen_info.usb_ugen_flags = 0;
993 usb_ugen_info.usb_ugen_minor_node_ugen_bits_mask =
994 (dev_t)SCSA2USB_MINOR_UGEN_BITS_MASK;
995 usb_ugen_info.usb_ugen_minor_node_instance_mask =
996 (dev_t)~SCSA2USB_MINOR_UGEN_BITS_MASK;
997 scsa2usbp->scsa2usb_ugen_hdl =
998 usb_ugen_get_hdl(dip, &usb_ugen_info);
1000 if (usb_ugen_attach(scsa2usbp->scsa2usb_ugen_hdl, cmd) !=
1001 USB_SUCCESS) {
1002 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1003 scsa2usbp->scsa2usb_log_handle,
1004 "usb_ugen_attach failed");
1006 usb_ugen_release_hdl(scsa2usbp->scsa2usb_ugen_hdl);
1007 scsa2usbp->scsa2usb_ugen_hdl = NULL;
1011 /* report device */
1012 ddi_report_dev(dip);
1014 return (DDI_SUCCESS);
1016 fail:
1017 if (scsa2usbp) {
1018 (void) scsa2usb_cleanup(dip, scsa2usbp);
1021 return (DDI_FAILURE);
1026 * scsa2usb_detach:
1027 * detach or suspend driver instance
1029 static int
1030 scsa2usb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1032 scsi_hba_tran_t *tran;
1033 scsa2usb_state_t *scsa2usbp;
1034 int rval;
1036 tran = ddi_get_driver_private(dip);
1037 ASSERT(tran != NULL);
1039 scsa2usbp = (scsa2usb_state_t *)tran->tran_hba_private;
1040 ASSERT(scsa2usbp);
1042 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1043 "scsa2usb_detach: dip = 0x%p, cmd = %d", (void *)dip, cmd);
1045 switch (cmd) {
1046 case DDI_DETACH:
1048 if (scsa2usb_cleanup(dip, scsa2usbp) != USB_SUCCESS) {
1050 return (DDI_FAILURE);
1053 return (DDI_SUCCESS);
1054 case DDI_SUSPEND:
1055 rval = scsa2usb_cpr_suspend(dip);
1057 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
1058 default:
1060 return (DDI_FAILURE);
1065 * ugen support
1068 * scsa2usb_ugen_open()
1069 * (all ugen opens and pipe opens are by definition exclusive so it is OK
1070 * to count opens)
1072 static int
1073 scsa2usb_ugen_open(dev_t *devp, int flag, int sflag, cred_t *cr)
1075 scsa2usb_state_t *scsa2usbp;
1076 int rval;
1078 if ((scsa2usbp = ddi_get_soft_state(scsa2usb_statep,
1079 SCSA2USB_MINOR_TO_INSTANCE(getminor(*devp)))) == NULL) {
1080 /* deferred detach */
1082 return (ENXIO);
1085 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1086 "scsa2usb_ugen_open: dev_t=0x%lx", *devp);
1088 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1090 /* if this is the first ugen open, check on transport busy */
1091 if (scsa2usbp->scsa2usb_busy_proc != curproc) {
1092 while (scsa2usbp->scsa2usb_transport_busy ||
1093 (scsa2usb_all_waitQs_empty(scsa2usbp) !=
1094 USB_SUCCESS)) {
1095 rval = cv_wait_sig(
1096 &scsa2usbp->scsa2usb_transport_busy_cv,
1097 &scsa2usbp->scsa2usb_mutex);
1098 if (rval == 0) {
1099 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1101 return (EINTR);
1104 scsa2usbp->scsa2usb_transport_busy++;
1105 scsa2usbp->scsa2usb_busy_proc = curproc;
1108 scsa2usbp->scsa2usb_ugen_open_count++;
1110 scsa2usb_raise_power(scsa2usbp);
1112 scsa2usb_close_usb_pipes(scsa2usbp);
1114 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1116 rval = usb_ugen_open(scsa2usbp->scsa2usb_ugen_hdl, devp, flag,
1117 sflag, cr);
1118 if (!rval) {
1120 * if usb_ugen_open() succeeded, we'll change the minor number
1121 * so that we can keep track of every open()/close() issued by
1122 * the userland processes. We need to pick a minor number that
1123 * is not used by the ugen framework
1126 usb_ugen_hdl_impl_t *usb_ugen_hdl_impl;
1127 ugen_state_t *ugenp;
1128 int ugen_minor, clone;
1130 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1132 usb_ugen_hdl_impl =
1133 (usb_ugen_hdl_impl_t *)scsa2usbp->scsa2usb_ugen_hdl;
1134 ugenp = usb_ugen_hdl_impl->hdl_ugenp;
1136 /* 'clone' is bigger than any ugen minor in use */
1137 for (clone = ugenp->ug_minor_node_table_index + 1;
1138 clone < SCSA2USB_MAX_CLONE; clone++) {
1139 if (!scsa2usbp->scsa2usb_clones[clone])
1140 break;
1143 if (clone >= SCSA2USB_MAX_CLONE) {
1144 cmn_err(CE_WARN, "scsa2usb_ugen_open: too many clones");
1145 rval = EBUSY;
1146 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1147 goto open_done;
1150 ugen_minor = getminor(*devp) & SCSA2USB_MINOR_UGEN_BITS_MASK;
1151 *devp = makedevice(getmajor(*devp),
1152 (scsa2usbp->scsa2usb_instance
1153 << SCSA2USB_MINOR_INSTANCE_SHIFT)
1154 + clone);
1156 /* save the ugen minor */
1157 scsa2usbp->scsa2usb_clones[clone] = (uint8_t)ugen_minor;
1158 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1159 "scsa2usb_ugen_open: new dev=%lx, old minor=%x",
1160 *devp, ugen_minor);
1162 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1165 open_done:
1167 if (rval) {
1168 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1170 /* reopen the pipes */
1171 if (--scsa2usbp->scsa2usb_ugen_open_count == 0) {
1172 scsa2usbp->scsa2usb_transport_busy--;
1173 scsa2usbp->scsa2usb_busy_proc = NULL;
1174 cv_signal(&scsa2usbp->scsa2usb_transport_busy_cv);
1176 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1178 scsa2usb_pm_idle_component(scsa2usbp);
1181 return (rval);
1186 * scsa2usb_ugen_close()
1188 static int
1189 scsa2usb_ugen_close(dev_t dev, int flag, int otype, cred_t *cr)
1191 int rval;
1192 int ugen_minor, clone;
1194 scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep,
1195 SCSA2USB_MINOR_TO_INSTANCE(getminor(dev)));
1197 if (scsa2usbp == NULL) {
1199 return (ENXIO);
1202 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1203 "scsa2usb_ugen_close: dev_t=0x%lx", dev);
1205 clone = getminor(dev) & SCSA2USB_MINOR_UGEN_BITS_MASK;
1206 ugen_minor = scsa2usbp->scsa2usb_clones[clone];
1207 dev = makedevice(getmajor(dev),
1208 (scsa2usbp->scsa2usb_instance << SCSA2USB_MINOR_INSTANCE_SHIFT)
1209 + ugen_minor);
1210 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1211 "scsa2usb_ugen_close: old dev=%lx", dev);
1212 rval = usb_ugen_close(scsa2usbp->scsa2usb_ugen_hdl, dev, flag,
1213 otype, cr);
1215 if (rval == 0) {
1216 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1218 scsa2usbp->scsa2usb_clones[clone] = 0;
1219 /* reopen the pipes */
1220 if (--scsa2usbp->scsa2usb_ugen_open_count == 0) {
1221 scsa2usbp->scsa2usb_transport_busy--;
1222 scsa2usbp->scsa2usb_busy_proc = NULL;
1223 cv_signal(&scsa2usbp->scsa2usb_transport_busy_cv);
1225 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1227 scsa2usb_pm_idle_component(scsa2usbp);
1230 return (rval);
1235 * scsa2usb_ugen_read/write()
1237 /*ARGSUSED*/
1238 static int
1239 scsa2usb_ugen_read(dev_t dev, struct uio *uiop, cred_t *credp)
1241 int clone, ugen_minor;
1242 scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep,
1243 SCSA2USB_MINOR_TO_INSTANCE(getminor(dev)));
1245 if (scsa2usbp == NULL) {
1247 return (ENXIO);
1250 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1251 "scsa2usb_ugen_read: dev_t=0x%lx", dev);
1253 clone = getminor(dev) & SCSA2USB_MINOR_UGEN_BITS_MASK;
1254 ugen_minor = scsa2usbp->scsa2usb_clones[clone];
1255 dev = makedevice(getmajor(dev),
1256 (scsa2usbp->scsa2usb_instance << SCSA2USB_MINOR_INSTANCE_SHIFT)
1257 + ugen_minor);
1259 return (usb_ugen_read(scsa2usbp->scsa2usb_ugen_hdl, dev,
1260 uiop, credp));
1264 /*ARGSUSED*/
1265 static int
1266 scsa2usb_ugen_write(dev_t dev, struct uio *uiop, cred_t *credp)
1268 int clone, ugen_minor;
1269 scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep,
1270 SCSA2USB_MINOR_TO_INSTANCE(getminor(dev)));
1272 if (scsa2usbp == NULL) {
1274 return (ENXIO);
1277 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1278 "scsa2usb_ugen_write: dev_t=0x%lx", dev);
1280 clone = getminor(dev) & SCSA2USB_MINOR_UGEN_BITS_MASK;
1281 ugen_minor = scsa2usbp->scsa2usb_clones[clone];
1282 dev = makedevice(getmajor(dev),
1283 (scsa2usbp->scsa2usb_instance << SCSA2USB_MINOR_INSTANCE_SHIFT)
1284 + ugen_minor);
1286 return (usb_ugen_write(scsa2usbp->scsa2usb_ugen_hdl,
1287 dev, uiop, credp));
1292 * scsa2usb_ugen_poll
1294 static int
1295 scsa2usb_ugen_poll(dev_t dev, short events,
1296 int anyyet, short *reventsp, struct pollhead **phpp)
1298 int clone, ugen_minor;
1299 scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep,
1300 SCSA2USB_MINOR_TO_INSTANCE(getminor(dev)));
1302 if (scsa2usbp == NULL) {
1304 return (ENXIO);
1307 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1308 "scsa2usb_ugen_poll: dev_t=0x%lx", dev);
1310 clone = getminor(dev) & SCSA2USB_MINOR_UGEN_BITS_MASK;
1311 ugen_minor = scsa2usbp->scsa2usb_clones[clone];
1312 dev = makedevice(getmajor(dev),
1313 (scsa2usbp->scsa2usb_instance << SCSA2USB_MINOR_INSTANCE_SHIFT)
1314 + ugen_minor);
1316 return (usb_ugen_poll(scsa2usbp->scsa2usb_ugen_hdl, dev, events,
1317 anyyet, reventsp, phpp));
1322 * scsa2usb_cleanup:
1323 * cleanup whatever attach has setup
1325 static int
1326 scsa2usb_cleanup(dev_info_t *dip, scsa2usb_state_t *scsa2usbp)
1328 int rval, i;
1329 scsa2usb_power_t *pm;
1330 uint_t lun;
1332 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1333 "scsa2usb_cleanup:");
1335 /* wait till the work thread is done */
1336 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1337 for (i = 0; i < SCSA2USB_DRAIN_TIMEOUT; i++) {
1338 if (scsa2usbp->scsa2usb_work_thread_id == NULL) {
1340 break;
1342 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1343 ddi_sleep(1);
1344 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1346 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1348 if (i >= SCSA2USB_DRAIN_TIMEOUT) {
1350 return (USB_FAILURE);
1354 * Disable the event callbacks first, after this point, event
1355 * callbacks will never get called. Note we shouldn't hold
1356 * mutex while unregistering events because there may be a
1357 * competing event callback thread. Event callbacks are done
1358 * with ndi mutex held and this can cause a potential deadlock.
1360 usb_unregister_event_cbs(scsa2usbp->scsa2usb_dip, &scsa2usb_events);
1362 if (scsa2usbp->scsa2usb_flags & SCSA2USB_FLAGS_LOCKS_INIT) {
1364 * if a waitQ exists, get rid of it before destroying it
1366 for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) {
1367 scsa2usb_flush_waitQ(scsa2usbp, lun, CMD_TRAN_ERR);
1368 usba_destroy_list(&scsa2usbp->scsa2usb_waitQ[lun]);
1371 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1372 if (scsa2usbp->scsa2usb_flags &
1373 SCSA2USB_FLAGS_HBA_ATTACH_SETUP) {
1374 (void) scsi_hba_detach(dip);
1375 scsi_hba_tran_free(scsa2usbp->scsa2usb_tran);
1378 if (scsa2usbp->scsa2usb_flags &
1379 SCSA2USB_FLAGS_PIPES_OPENED) {
1380 scsa2usb_close_usb_pipes(scsa2usbp);
1383 /* Lower the power */
1384 pm = scsa2usbp->scsa2usb_pm;
1386 if (pm && (scsa2usbp->scsa2usb_dev_state !=
1387 USB_DEV_DISCONNECTED)) {
1388 if (pm->scsa2usb_wakeup_enabled) {
1389 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1390 (void) pm_raise_power(dip, 0,
1391 USB_DEV_OS_FULL_PWR);
1393 if ((rval = usb_handle_remote_wakeup(dip,
1394 USB_REMOTE_WAKEUP_DISABLE)) !=
1395 USB_SUCCESS) {
1396 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1397 scsa2usbp->scsa2usb_log_handle,
1398 "disable remote wakeup failed "
1399 "(%d)", rval);
1401 } else {
1402 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1405 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
1407 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1410 if (pm) {
1411 kmem_free(pm, sizeof (scsa2usb_power_t));
1414 if (scsa2usbp->scsa2usb_override_str) {
1415 kmem_free(scsa2usbp->scsa2usb_override_str,
1416 strlen(scsa2usbp->scsa2usb_override_str) + 1);
1417 scsa2usbp->scsa2usb_override_str = NULL;
1420 /* remove the minor nodes */
1421 ddi_remove_minor_node(dip, NULL);
1423 /* Cancel the registered panic callback */
1424 scsa2usb_panic_callb_fini(scsa2usbp);
1426 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1428 mutex_destroy(&scsa2usbp->scsa2usb_mutex);
1429 cv_destroy(&scsa2usbp->scsa2usb_transport_busy_cv);
1432 usb_client_detach(scsa2usbp->scsa2usb_dip,
1433 scsa2usbp->scsa2usb_dev_data);
1435 if (scsa2usbp->scsa2usb_ugen_hdl) {
1436 (void) usb_ugen_detach(scsa2usbp->scsa2usb_ugen_hdl,
1437 DDI_DETACH);
1438 usb_ugen_release_hdl(scsa2usbp->scsa2usb_ugen_hdl);
1441 usb_free_log_hdl(scsa2usbp->scsa2usb_log_handle);
1443 ddi_prop_remove_all(dip);
1445 ddi_soft_state_free(scsa2usb_statep, ddi_get_instance(dip));
1447 return (USB_SUCCESS);
1452 * scsa2usb_override:
1453 * some devices may be attached even though their subclass or
1454 * protocol info is not according to spec.
1455 * these can be determined by the 'subclass-protocol-override'
1456 * property set in the conf file.
1458 static void
1459 scsa2usb_override(scsa2usb_state_t *scsa2usbp)
1461 scsa2usb_ov_t ov;
1462 char **override_str = NULL;
1463 char *override_str_cpy;
1464 uint_t override_str_len, override_str_cpy_len;
1465 uint_t i;
1466 usb_dev_descr_t *descr = scsa2usbp->scsa2usb_dev_data->dev_descr;
1468 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
1470 scsa2usbp->scsa2usb_subclass_override =
1471 scsa2usbp->scsa2usb_protocol_override = 0;
1473 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, scsa2usbp->scsa2usb_dip,
1474 DDI_PROP_DONTPASS, "attribute-override-list",
1475 &override_str, &override_str_len) != DDI_PROP_SUCCESS) {
1477 return;
1480 /* parse each string in the subclass-protocol-override property */
1481 for (i = 0; i < override_str_len; i++) {
1483 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1484 "override_str[%d] = %s", i, override_str[i]);
1487 * save a copy of the override string for possible
1488 * inclusion in soft state later
1490 override_str_cpy_len = strlen(override_str[i]) + 1;
1491 override_str_cpy = kmem_zalloc(override_str_cpy_len, KM_SLEEP);
1492 (void) strcpy(override_str_cpy, override_str[i]);
1494 bzero(&ov, sizeof (scsa2usb_ov_t));
1496 if (scsa2usb_parse_input_str(override_str[i], &ov,
1497 scsa2usbp) == USB_FAILURE) {
1498 kmem_free(override_str_cpy, override_str_cpy_len);
1499 continue;
1503 * see if subclass/protocol needs to be overridden for device
1504 * or if device should not be power managed
1505 * if there'a a match, save the override string in soft state
1507 if (((descr->idVendor == (uint16_t)ov.vid) || (ov.vid == 0)) &&
1508 ((descr->idProduct == (uint16_t)ov.pid) || (ov.pid == 0)) &&
1509 ((descr->bcdDevice == (uint16_t)ov.rev) || (ov.rev == 0))) {
1510 scsa2usbp->scsa2usb_subclass_override = ov.subclass;
1511 scsa2usbp->scsa2usb_protocol_override = ov.protocol;
1513 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1514 scsa2usbp->scsa2usb_log_handle,
1515 "vid=0x%x pid=0x%x rev=0x%x subclass=0x%x "
1516 "protocol=0x%x "
1517 "pmoff=%d fake_removable=%d modesense=%d "
1518 "reduced-cmd-support=%d",
1519 ov.vid, ov.pid, ov.rev, ov.subclass, ov.protocol,
1520 ov.pmoff, ov.fake_removable, ov.no_modesense,
1521 ov.reduced_cmd_support);
1523 if (ov.pmoff) {
1524 scsa2usbp->scsa2usb_attrs &= ~SCSA2USB_ATTRS_PM;
1526 if (ov.fake_removable) {
1527 scsa2usbp->scsa2usb_attrs &=
1528 ~SCSA2USB_ATTRS_RMB;
1530 if (ov.no_modesense) {
1531 scsa2usbp->scsa2usb_attrs &=
1532 ~SCSA2USB_ATTRS_MODE_SENSE;
1534 if (ov.reduced_cmd_support) {
1535 scsa2usbp->scsa2usb_attrs &=
1536 ~SCSA2USB_ATTRS_REDUCED_CMD;
1538 scsa2usbp->scsa2usb_override_str = override_str_cpy;
1539 break;
1540 } else {
1541 kmem_free(override_str_cpy, override_str_cpy_len);
1545 ddi_prop_free(override_str);
1550 * scsa2usb_parse_input_str:
1551 * parse one conf file subclass-protocol-override string
1552 * return vendor id, product id, revision, subclass, protocol
1553 * function return is success or failure
1555 static int
1556 scsa2usb_parse_input_str(char *str, scsa2usb_ov_t *ovp,
1557 scsa2usb_state_t *scsa2usbp)
1559 char *input_field, *input_value;
1560 char *lasts;
1561 uint_t i;
1562 u_longlong_t value;
1564 /* parse all the input pairs in the string */
1565 for (input_field = scsa2usb_strtok_r(str, "=", &lasts);
1566 input_field != NULL;
1567 input_field = scsa2usb_strtok_r(lasts, "=", &lasts)) {
1569 if ((input_value = scsa2usb_strtok_r(lasts, " ", &lasts)) ==
1570 NULL) {
1571 scsa2usb_override_error("format", scsa2usbp);
1573 return (USB_FAILURE);
1575 /* if input value is a 'don't care', skip to the next pair */
1576 if (strcmp(input_value, "*") == 0) {
1577 continue;
1579 if (strcasecmp(input_field, "vid") == 0) {
1580 if (kobj_getvalue(input_value, &value) == -1) {
1581 scsa2usb_override_error("vendor id", scsa2usbp);
1583 return (USB_FAILURE);
1585 ovp->vid = (int)value;
1586 } else if (strcasecmp(input_field, "pid") == 0) {
1587 if (kobj_getvalue(input_value, &value) == -1) {
1588 scsa2usb_override_error("product id",
1589 scsa2usbp);
1591 return (USB_FAILURE);
1593 ovp->pid = (int)value;
1594 } else if (strcasecmp(input_field, "rev") == 0) {
1595 if (kobj_getvalue(input_value, &value) == -1) {
1596 scsa2usb_override_error("revision id",
1597 scsa2usbp);
1599 return (USB_FAILURE);
1601 ovp->rev = (int)value;
1602 } else if (strcasecmp(input_field, "subclass") == 0) {
1603 for (i = 0; i < N_SCSA2USB_SUBC_OVERRIDE; i++) {
1604 if (strcasecmp(input_value,
1605 scsa2usb_subclass[i].name) == 0) {
1606 ovp->subclass =
1607 scsa2usb_subclass[i].value;
1608 break;
1611 if (ovp->subclass == 0) {
1612 scsa2usb_override_error("subclass", scsa2usbp);
1614 return (USB_FAILURE);
1616 } else if (strcasecmp(input_field, "protocol") == 0) {
1617 for (i = 0; i < N_SCSA2USB_PROT_OVERRIDE; i++) {
1618 if (strcasecmp(input_value,
1619 scsa2usb_protocol[i].name) == 0) {
1620 ovp->protocol =
1621 scsa2usb_protocol[i].value;
1622 break;
1625 if (ovp->protocol == 0) {
1626 scsa2usb_override_error("protocol", scsa2usbp);
1628 return (USB_FAILURE);
1630 } else if (strcasecmp(input_field, "pm") == 0) {
1631 if (strcasecmp(input_value, "off") == 0) {
1632 ovp->pmoff = 1;
1633 break;
1634 } else {
1635 scsa2usb_override_error("pm", scsa2usbp);
1637 return (USB_FAILURE);
1639 } else if (strcasecmp(input_field, "removable") == 0) {
1640 if (strcasecmp(input_value, "true") == 0) {
1641 ovp->fake_removable = 1;
1642 break;
1643 } else {
1644 scsa2usb_override_error("removable", scsa2usbp);
1646 return (USB_FAILURE);
1648 } else if (strcasecmp(input_field, "modesense") == 0) {
1649 if (strcasecmp(input_value, "false") == 0) {
1650 ovp->no_modesense = 1;
1651 break;
1652 } else {
1653 scsa2usb_override_error("modesense",
1654 scsa2usbp);
1656 return (USB_FAILURE);
1658 } else if (strcasecmp(input_field,
1659 "reduced-cmd-support") == 0) {
1660 if (strcasecmp(input_value, "true") == 0) {
1661 ovp->reduced_cmd_support = 1;
1662 break;
1663 } else {
1664 scsa2usb_override_error(
1665 "reduced-cmd-support", scsa2usbp);
1667 return (USB_FAILURE);
1669 } else {
1670 scsa2usb_override_error(input_field, scsa2usbp);
1672 return (USB_FAILURE);
1676 return (USB_SUCCESS);
1681 * scsa2usb_override_error:
1682 * print an error message if conf file string is bad format
1684 static void
1685 scsa2usb_override_error(char *input_field, scsa2usb_state_t *scsa2usbp)
1687 USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1688 "invalid %s in scsa2usb.conf file entry", input_field);
1692 * scsa2usb_strtok_r:
1693 * parse a list of tokens
1695 static char *
1696 scsa2usb_strtok_r(char *p, char *sep, char **lasts)
1698 char *e;
1699 char *tok = NULL;
1701 if (p == 0 || *p == 0) {
1703 return (NULL);
1706 e = p+strlen(p);
1708 do {
1709 if (strchr(sep, *p) != NULL) {
1710 if (tok != NULL) {
1711 *p = 0;
1712 *lasts = p+1;
1714 return (tok);
1716 } else if (tok == NULL) {
1717 tok = p;
1719 } while (++p < e);
1721 *lasts = NULL;
1723 return (tok);
1728 * scsa2usb_validate_attrs:
1729 * many devices have BO/CB/CBI protocol support issues.
1730 * use vendor/product info to reset the
1731 * individual erroneous attributes
1733 * NOTE: we look at only device at a time (at attach time)
1735 static void
1736 scsa2usb_validate_attrs(scsa2usb_state_t *scsa2usbp)
1738 int i, mask;
1739 usb_dev_descr_t *desc = scsa2usbp->scsa2usb_dev_data->dev_descr;
1741 if (!SCSA2USB_IS_BULK_ONLY(scsa2usbp)) {
1742 scsa2usbp->scsa2usb_attrs &= ~SCSA2USB_ATTRS_GET_LUN;
1745 /* determine if this device is on the blacklist */
1746 for (i = 0; i < N_SCSA2USB_BLACKLIST; i++) {
1747 if ((scsa2usb_blacklist[i].idVendor == desc->idVendor) &&
1748 ((scsa2usb_blacklist[i].idProduct == desc->idProduct) ||
1749 (scsa2usb_blacklist[i].idProduct == X))) {
1750 scsa2usbp->scsa2usb_attrs &=
1751 ~(scsa2usb_blacklist[i].attributes);
1752 break;
1757 * Mitsumi's CD-RW drives subclass isn't UFI.
1758 * But they support UFI command-set (this code ensures that)
1759 * NOTE: This is a special case, and is being called out so.
1761 if (desc->idVendor == MS_MITSUMI_VID) {
1762 mask = scsa2usbp->scsa2usb_cmd_protocol & SCSA2USB_CMDSET_MASK;
1763 if (mask) {
1764 scsa2usbp->scsa2usb_cmd_protocol &= ~mask;
1766 scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_UFI_CMDSET;
1769 if (scsa2usbp->scsa2usb_attrs != SCSA2USB_ALL_ATTRS) {
1770 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1771 scsa2usbp->scsa2usb_log_handle,
1772 "scsa2usb attributes modified: 0x%x",
1773 scsa2usbp->scsa2usb_attrs);
1779 * scsa2usb_create_luns:
1780 * check the number of luns but continue if the check fails,
1781 * create child nodes for each lun
1783 static void
1784 scsa2usb_create_luns(scsa2usb_state_t *scsa2usbp)
1786 int lun, rval;
1787 char *compatible[MAX_COMPAT_NAMES]; /* compatible names */
1788 dev_info_t *cdip;
1789 uchar_t dtype;
1790 char *node_name;
1791 char *driver_name = NULL;
1793 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1794 "scsa2usb_create_luns:");
1796 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1798 /* Set n_luns to 1 by default (for floppies and other devices) */
1799 scsa2usbp->scsa2usb_n_luns = 1;
1802 * Check if there are any device out there which don't
1803 * support the GET_MAX_LUN command. If so, don't issue
1804 * control request to them.
1806 if ((scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_GET_LUN) == 0) {
1807 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1808 "get_max_lun cmd not supported");
1809 } else {
1810 if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) {
1811 scsa2usbp->scsa2usb_n_luns =
1812 scsa2usb_bulk_only_get_max_lun(scsa2usbp);
1816 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1817 "scsa2usb_create_luns: %d luns found", scsa2usbp->scsa2usb_n_luns);
1820 * create disk child for each lun
1822 for (lun = 0; lun < scsa2usbp->scsa2usb_n_luns; lun++) {
1823 ASSERT(scsa2usbp->scsa2usb_lun_dip[lun] == NULL);
1825 /* do an inquiry to get the dtype of this lun */
1826 scsa2usb_do_inquiry(scsa2usbp, 0, lun);
1828 dtype = scsa2usbp->scsa2usb_lun_inquiry[lun].
1829 inq_dtype & DTYPE_MASK;
1831 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
1832 "dtype[%d]=0x%x", lun, dtype);
1834 driver_name = NULL;
1836 switch (dtype) {
1837 case DTYPE_DIRECT:
1838 case DTYPE_RODIRECT:
1839 case DTYPE_OPTICAL:
1840 node_name = "disk";
1841 driver_name = "sd";
1843 break;
1844 case DTYPE_SEQUENTIAL:
1845 node_name = "tape";
1846 driver_name = "st";
1848 break;
1849 case DTYPE_PRINTER:
1850 node_name = "printer";
1852 break;
1853 case DTYPE_PROCESSOR:
1854 node_name = "processor";
1856 break;
1857 case DTYPE_WORM:
1858 node_name = "worm";
1860 break;
1861 case DTYPE_SCANNER:
1862 node_name = "scanner";
1864 break;
1865 case DTYPE_CHANGER:
1866 node_name = "changer";
1868 break;
1869 case DTYPE_COMM:
1870 node_name = "comm";
1872 break;
1873 case DTYPE_ARRAY_CTRL:
1874 node_name = "array_ctrl";
1876 break;
1877 case DTYPE_ESI:
1878 node_name = "esi";
1879 driver_name = "ses";
1881 break;
1882 default:
1883 node_name = "generic";
1885 break;
1888 if (driver_name) {
1889 compatible[0] = driver_name;
1892 ndi_devi_alloc_sleep(scsa2usbp->scsa2usb_dip, node_name,
1893 (pnode_t)DEVI_SID_NODEID, &cdip);
1895 /* attach target & lun properties */
1896 rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "target", 0);
1897 if (rval != DDI_PROP_SUCCESS) {
1898 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1899 scsa2usbp->scsa2usb_log_handle,
1900 "ndi_prop_update_int target failed %d", rval);
1901 (void) ndi_devi_free(cdip);
1902 continue;
1905 rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip,
1906 "hotpluggable");
1907 if (rval != DDI_PROP_SUCCESS) {
1908 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1909 scsa2usbp->scsa2usb_log_handle,
1910 "ndi_prop_create_boolean hotpluggable failed %d",
1911 rval);
1912 ddi_prop_remove_all(cdip);
1913 (void) ndi_devi_free(cdip);
1914 continue;
1917 * Some devices don't support LOG SENSE, so tells
1918 * sd driver not to send this command.
1920 rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
1921 "pm-capable", 1);
1922 if (rval != DDI_PROP_SUCCESS) {
1923 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1924 scsa2usbp->scsa2usb_log_handle,
1925 "ndi_prop_update_int pm-capable failed %d", rval);
1926 ddi_prop_remove_all(cdip);
1927 (void) ndi_devi_free(cdip);
1928 continue;
1931 rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "lun", lun);
1932 if (rval != DDI_PROP_SUCCESS) {
1933 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1934 scsa2usbp->scsa2usb_log_handle,
1935 "ndi_prop_update_int lun failed %d", rval);
1936 ddi_prop_remove_all(cdip);
1937 (void) ndi_devi_free(cdip);
1938 continue;
1941 if (driver_name) {
1942 rval = ndi_prop_update_string_array(DDI_DEV_T_NONE,
1943 cdip, "compatible", (char **)compatible,
1944 MAX_COMPAT_NAMES);
1945 if (rval != DDI_PROP_SUCCESS) {
1946 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1947 scsa2usbp->scsa2usb_log_handle,
1948 "ndi_prop_update_string_array failed %d",
1949 rval);
1950 ddi_prop_remove_all(cdip);
1951 (void) ndi_devi_free(cdip);
1952 continue;
1957 * add property "usb" so we always verify that it is our child
1959 rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "usb");
1960 if (rval != DDI_PROP_SUCCESS) {
1961 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
1962 scsa2usbp->scsa2usb_log_handle,
1963 "ndi_prop_create_boolean failed %d", rval);
1964 ddi_prop_remove_all(cdip);
1965 (void) ndi_devi_free(cdip);
1966 continue;
1969 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1970 (void) ddi_initchild(scsa2usbp->scsa2usb_dip, cdip);
1971 mutex_enter(&scsa2usbp->scsa2usb_mutex);
1973 usba_set_usba_device(cdip,
1974 usba_get_usba_device(scsa2usbp->scsa2usb_dip));
1976 mutex_exit(&scsa2usbp->scsa2usb_mutex);
1981 * scsa2usb_is_usb:
1982 * scsa2usb gets called for all possible sd children.
1983 * we can only accept usb children
1985 static int
1986 scsa2usb_is_usb(dev_info_t *dip)
1988 if (dip) {
1989 return (ddi_prop_exists(DDI_DEV_T_ANY, dip,
1990 DDI_PROP_DONTPASS, "usb"));
1992 return (0);
1997 * Panic Stuff
1998 * scsa2usb_panic_callb_init:
1999 * initialize PANIC callb and free allocated resources
2001 static void
2002 scsa2usb_panic_callb_init(scsa2usb_state_t *scsa2usbp)
2005 * In case the system panics, the sync command flushes
2006 * dirty FS pages or buffers. This would cause a hang
2007 * in USB.
2008 * The reason for the failure is that we enter
2009 * polled mode (interrupts disabled) and HCD gets stuck
2010 * trying to execute bulk requests
2011 * The panic_callback registered below provides a warning
2012 * that a panic has occurred and from that point onwards, we
2013 * complete each request successfully and immediately. This
2014 * will fake successful syncing so at least the rest of the
2015 * filesystems complete syncing.
2017 scsa2usbp->scsa2usb_panic_info =
2018 kmem_zalloc(sizeof (scsa2usb_cpr_t), KM_SLEEP);
2019 mutex_init(&scsa2usbp->scsa2usb_panic_info->lockp,
2020 NULL, MUTEX_DRIVER,
2021 scsa2usbp->scsa2usb_dev_data->dev_iblock_cookie);
2022 scsa2usbp->scsa2usb_panic_info->statep = scsa2usbp;
2023 scsa2usbp->scsa2usb_panic_info->cpr.cc_lockp =
2024 &scsa2usbp->scsa2usb_panic_info->lockp;
2025 scsa2usbp->scsa2usb_panic_info->cpr.cc_id =
2026 callb_add(scsa2usb_panic_callb,
2027 (void *)scsa2usbp->scsa2usb_panic_info,
2028 CB_CL_PANIC, "scsa2usb");
2033 * scsa2usb_panic_callb_fini:
2034 * cancel out PANIC callb and free allocated resources
2036 static void
2037 scsa2usb_panic_callb_fini(scsa2usb_state_t *scsa2usbp)
2039 if (scsa2usbp->scsa2usb_panic_info) {
2040 SCSA2USB_CANCEL_CB(scsa2usbp->scsa2usb_panic_info->cpr.cc_id);
2041 mutex_destroy(&scsa2usbp->scsa2usb_panic_info->lockp);
2042 scsa2usbp->scsa2usb_panic_info->statep = NULL;
2043 kmem_free(scsa2usbp->scsa2usb_panic_info,
2044 sizeof (scsa2usb_cpr_t));
2045 scsa2usbp->scsa2usb_panic_info = NULL;
2051 * scsa2usb_panic_callb:
2052 * This routine is called when there is a system panic.
2054 /* ARGSUSED */
2055 static boolean_t
2056 scsa2usb_panic_callb(void *arg, int code)
2058 scsa2usb_cpr_t *cpr_infop;
2059 scsa2usb_state_t *scsa2usbp;
2060 uint_t lun;
2062 _NOTE(NO_COMPETING_THREADS_NOW);
2063 cpr_infop = (scsa2usb_cpr_t *)arg;
2064 scsa2usbp = (scsa2usb_state_t *)cpr_infop->statep;
2066 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2067 "scsa2usb_panic_callb: code=%d", code);
2070 * If we return error here, "sd" prints lots of error
2071 * messages and could retry the same pkt over and over again.
2072 * The sync recovery isn't "smooth" in that case. By faking
2073 * a success return, instead, we force sync to complete.
2075 if (scsa2usbp->scsa2usb_cur_pkt) {
2077 * Do not print the "no sync" warning here. it will then be
2078 * displayed before we actually start syncing. Also we don't
2079 * replace this code with a call to scsa2usb_pkt_completion().
2080 * NOTE: mutexes are disabled during panic.
2082 scsa2usbp->scsa2usb_cur_pkt->pkt_reason = CMD_CMPLT;
2083 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2084 scsa2usb_pkt_completion(scsa2usbp, scsa2usbp->scsa2usb_cur_pkt);
2085 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2088 /* get rid of waitQ */
2089 for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) {
2090 scsa2usb_flush_waitQ(scsa2usbp, lun, CMD_CMPLT);
2093 _NOTE(COMPETING_THREADS_NOW);
2095 return (B_TRUE);
2099 * scsa2usb_cpr_suspend
2100 * determine if the device's state can be changed to SUSPENDED
2101 * close pipes if there is no activity
2103 /* ARGSUSED */
2104 static int
2105 scsa2usb_cpr_suspend(dev_info_t *dip)
2107 scsa2usb_state_t *scsa2usbp;
2108 int prev_state;
2109 int rval = USB_FAILURE;
2111 scsa2usbp = ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip));
2113 ASSERT(scsa2usbp != NULL);
2115 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2116 "scsa2usb_cpr_suspend:");
2118 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2119 switch (scsa2usbp->scsa2usb_dev_state) {
2120 case USB_DEV_ONLINE:
2121 case USB_DEV_PWRED_DOWN:
2122 case USB_DEV_DISCONNECTED:
2123 prev_state = scsa2usbp->scsa2usb_dev_state;
2124 scsa2usbp->scsa2usb_dev_state = USB_DEV_SUSPENDED;
2127 * If the device is busy, we cannot suspend
2129 if (SCSA2USB_BUSY(scsa2usbp)) {
2130 USB_DPRINTF_L3(DPRINT_MASK_SCSA,
2131 scsa2usbp->scsa2usb_log_handle,
2132 "scsa2usb_cpr_suspend: I/O active");
2134 /* fall back to previous state */
2135 scsa2usbp->scsa2usb_dev_state = prev_state;
2136 } else {
2137 rval = USB_SUCCESS;
2140 break;
2141 case USB_DEV_SUSPENDED:
2142 default:
2143 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2144 "scsa2usb_cpr_suspend: Illegal dev state: %d",
2145 scsa2usbp->scsa2usb_dev_state);
2147 break;
2149 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2151 if ((rval == USB_SUCCESS) && scsa2usbp->scsa2usb_ugen_hdl) {
2152 rval = usb_ugen_detach(scsa2usbp->scsa2usb_ugen_hdl,
2153 DDI_SUSPEND);
2156 return (rval);
2161 * scsa2usb_cpr_resume:
2162 * restore device's state
2164 static void
2165 scsa2usb_cpr_resume(dev_info_t *dip)
2167 scsa2usb_state_t *scsa2usbp =
2168 ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip));
2170 ASSERT(scsa2usbp != NULL);
2172 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2173 "scsa2usb_cpr_resume: dip = 0x%p", (void *)dip);
2175 scsa2usb_restore_device_state(dip, scsa2usbp);
2177 if (scsa2usbp->scsa2usb_ugen_hdl) {
2178 (void) usb_ugen_attach(scsa2usbp->scsa2usb_ugen_hdl,
2179 DDI_RESUME);
2185 * scsa2usb_restore_device_state:
2186 * - raise the device's power
2187 * - reopen all the pipes
2189 static void
2190 scsa2usb_restore_device_state(dev_info_t *dip, scsa2usb_state_t *scsa2usbp)
2192 uint_t prev_state;
2194 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2195 "scsa2usb_restore_device_state:");
2197 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2198 prev_state = scsa2usbp->scsa2usb_dev_state;
2200 scsa2usb_raise_power(scsa2usbp);
2202 ASSERT((prev_state == USB_DEV_DISCONNECTED) ||
2203 (prev_state == USB_DEV_SUSPENDED));
2205 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2207 /* Check for the same device */
2208 if (usb_check_same_device(dip, scsa2usbp->scsa2usb_log_handle,
2209 USB_LOG_L0, DPRINT_MASK_ALL, USB_CHK_ALL, NULL) != USB_SUCCESS) {
2211 /* change the flags to active */
2212 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2213 scsa2usbp->scsa2usb_dev_state = USB_DEV_DISCONNECTED;
2214 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2216 scsa2usb_pm_idle_component(scsa2usbp);
2218 return;
2222 * if the device had remote wakeup earlier,
2223 * enable it again
2225 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2226 if (scsa2usbp->scsa2usb_pm &&
2227 scsa2usbp->scsa2usb_pm->scsa2usb_wakeup_enabled) {
2228 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2229 (void) usb_handle_remote_wakeup(scsa2usbp->scsa2usb_dip,
2230 USB_REMOTE_WAKEUP_ENABLE);
2231 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2234 scsa2usbp->scsa2usb_dev_state = USB_DEV_ONLINE;
2235 scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_NONE;
2236 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2238 scsa2usb_pm_idle_component(scsa2usbp);
2243 * SCSA entry points:
2245 * scsa2usb_scsi_tgt_probe:
2246 * scsa functions are exported by means of the transport table
2247 * Issue a probe to get the inquiry data.
2249 /* ARGSUSED */
2250 static int
2251 scsa2usb_scsi_tgt_probe(struct scsi_device *sd, int (*waitfunc)(void))
2253 scsi_hba_tran_t *tran;
2254 scsa2usb_state_t *scsa2usbp;
2255 dev_info_t *dip = ddi_get_parent(sd->sd_dev);
2256 int rval;
2258 ASSERT(dip);
2260 tran = ddi_get_driver_private(dip);
2261 ASSERT(tran != NULL);
2262 scsa2usbp = (scsa2usb_state_t *)tran->tran_hba_private;
2263 ASSERT(scsa2usbp);
2265 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2266 "scsa2usb_scsi_tgt_probe:");
2268 /* if device is disconnected (ie. pipes closed), fail immediately */
2269 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2270 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) {
2271 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2273 return (SCSIPROBE_FAILURE);
2275 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2277 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2278 "scsa2usb_scsi_tgt_probe: scsi_device = 0x%p", (void *)sd);
2280 if ((rval = scsi_hba_probe(sd, waitfunc)) == SCSIPROBE_EXISTS) {
2282 * respect the removable bit on all USB storage devices
2283 * unless overridden by a scsa2usb.conf entry
2285 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2286 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_RMB)) {
2287 _NOTE(SCHEME_PROTECTS_DATA("unshared", scsi_inquiry))
2288 sd->sd_inq->inq_rmb = 1;
2290 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2293 return (rval);
2298 * scsa2usb_scsi_tgt_init:
2299 * check whether we created this child ourselves
2301 /* ARGSUSED */
2302 static int
2303 scsa2usb_scsi_tgt_init(dev_info_t *dip, dev_info_t *cdip,
2304 scsi_hba_tran_t *tran, struct scsi_device *sd)
2306 scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)
2307 tran->tran_hba_private;
2308 int lun;
2309 int t_len = sizeof (lun);
2311 if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
2312 DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP, "lun", (caddr_t)&lun,
2313 &t_len) != DDI_PROP_SUCCESS) {
2315 return (DDI_FAILURE);
2318 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2319 "scsa2usb_scsi_tgt_init: %s, lun%d", ddi_driver_name(cdip), lun);
2321 /* is this a child we created? */
2322 if (scsa2usb_is_usb(cdip) == 0) {
2324 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2325 "scsa2usb_scsi_tgt_init: new child %s%d",
2326 ddi_driver_name(cdip), ddi_get_instance(cdip));
2329 * add property "usb" so we can always verify that it
2330 * is our child
2332 if (ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "usb") !=
2333 DDI_PROP_SUCCESS) {
2334 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
2335 scsa2usbp->scsa2usb_log_handle,
2336 "ndi_prop_create_boolean failed");
2338 return (DDI_FAILURE);
2341 usba_set_usba_device(cdip,
2342 usba_get_usba_device(scsa2usbp->scsa2usb_dip));
2345 * we don't store this dip in scsa2usb_lun_dip, there
2346 * might be multiple dips for the same device
2349 return (DDI_SUCCESS);
2352 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2353 if ((lun >= scsa2usbp->scsa2usb_n_luns) ||
2354 (scsa2usbp->scsa2usb_lun_dip[lun] != NULL)) {
2355 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2357 return (DDI_FAILURE);
2360 scsa2usbp->scsa2usb_lun_dip[lun] = cdip;
2361 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2363 return (DDI_SUCCESS);
2368 * scsa2usb_scsi_tgt_free:
2370 /* ARGSUSED */
2371 static void
2372 scsa2usb_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *cdip,
2373 scsi_hba_tran_t *tran, struct scsi_device *sd)
2375 scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)
2376 tran->tran_hba_private;
2377 int lun;
2378 int t_len = sizeof (lun);
2380 /* is this our child? */
2381 if (scsa2usb_is_usb(cdip) == 0) {
2383 return;
2386 if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
2387 DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP, "lun", (caddr_t)&lun,
2388 &t_len) != DDI_PROP_SUCCESS) {
2390 return;
2393 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2394 "scsa2usb_scsi_tgt_free: %s lun%d", ddi_driver_name(cdip), lun);
2396 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2397 if (lun < scsa2usbp->scsa2usb_n_luns) {
2398 if (scsa2usbp->scsa2usb_lun_dip[lun] == cdip) {
2399 scsa2usbp->scsa2usb_lun_dip[lun] = NULL;
2402 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2407 * bus enumeration entry points
2409 static int
2410 scsa2usb_scsi_bus_config(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
2411 void *arg, dev_info_t **child)
2413 int circ;
2414 int rval;
2416 scsa2usb_state_t *scsa2usbp =
2417 ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip));
2419 ASSERT(scsa2usbp != NULL);
2421 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2422 "scsa2usb_scsi_bus_config: op=%d", op);
2424 if (scsa2usb_scsi_bus_config_debug) {
2425 flag |= NDI_DEVI_DEBUG;
2428 ndi_devi_enter(dip, &circ);
2429 /* create children if necessary */
2430 if (DEVI(dip)->devi_child == NULL) {
2431 scsa2usb_create_luns(scsa2usbp);
2434 rval = ndi_busop_bus_config(dip, flag, op, arg, child, 0);
2436 ndi_devi_exit(dip, circ);
2438 return (rval);
2442 static int
2443 scsa2usb_scsi_bus_unconfig(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
2444 void *arg)
2446 scsa2usb_state_t *scsa2usbp =
2447 ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip));
2449 int circular_count;
2450 int rval = NDI_SUCCESS;
2451 uint_t save_flag = flag;
2453 ASSERT(scsa2usbp != NULL);
2455 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2456 "scsa2usb_scsi_bus_unconfig: op=%d", op);
2458 if (scsa2usb_scsi_bus_config_debug) {
2459 flag |= NDI_DEVI_DEBUG;
2463 * first offline and if offlining successful, then
2464 * remove children
2466 if (op == BUS_UNCONFIG_ALL) {
2467 flag &= ~(NDI_DEVI_REMOVE | NDI_UNCONFIG);
2470 ndi_devi_enter(dip, &circular_count);
2471 rval = ndi_busop_bus_unconfig(dip, flag, op, arg);
2474 * If unconfig is successful and not part of modunload
2475 * daemon, attempt to remove children.
2477 if (op == BUS_UNCONFIG_ALL && rval == NDI_SUCCESS &&
2478 (flag & NDI_AUTODETACH) == 0) {
2479 flag |= NDI_DEVI_REMOVE;
2480 rval = ndi_busop_bus_unconfig(dip, flag, op, arg);
2482 ndi_devi_exit(dip, circular_count);
2484 if ((rval != NDI_SUCCESS) && (op == BUS_UNCONFIG_ALL) &&
2485 (save_flag & NDI_DEVI_REMOVE)) {
2486 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2487 if (scsa2usbp->scsa2usb_warning_given != B_TRUE) {
2488 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
2489 scsa2usbp->scsa2usb_log_handle,
2490 "Disconnected device was busy, "
2491 "please reconnect.");
2492 scsa2usbp->scsa2usb_warning_given = B_TRUE;
2494 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2497 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2498 "scsa2usb_scsi_bus_unconfig: rval=%d", rval);
2500 return (rval);
2505 * scsa2usb_scsi_init_pkt:
2506 * Set up the scsi_pkt for transport. Also initialize
2507 * scsa2usb_cmd struct for the transport.
2508 * NOTE: We do not do any DMA setup here as USBA framework
2509 * does that for us.
2511 static struct scsi_pkt *
2512 scsa2usb_scsi_init_pkt(struct scsi_address *ap,
2513 struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
2514 int tgtlen, int flags, int (*callback)(), caddr_t arg)
2516 scsa2usb_cmd_t *cmd;
2517 scsa2usb_state_t *scsa2usbp;
2518 struct scsi_pkt *in_pkt = pkt;
2520 ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
2522 scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap);
2524 /* Print sync message */
2525 if (ddi_in_panic()) {
2526 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2527 SCSA2USB_PRINT_SYNC_MSG(scsa2usb_sync_message, scsa2usbp);
2528 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2529 /* continue so caller will not hang or complain */
2532 /* allocate a pkt, if none already allocated */
2533 if (pkt == NULL) {
2534 if (statuslen < sizeof (struct scsi_arq_status)) {
2535 statuslen = sizeof (struct scsi_arq_status);
2538 pkt = scsi_hba_pkt_alloc(scsa2usbp->scsa2usb_dip, ap, cmdlen,
2539 statuslen, tgtlen, sizeof (scsa2usb_cmd_t),
2540 callback, arg);
2541 if (pkt == NULL) {
2543 return (NULL);
2546 cmd = PKT2CMD(pkt);
2547 cmd->cmd_pkt = pkt; /* back link to pkt */
2548 cmd->cmd_scblen = statuslen;
2549 cmd->cmd_cdblen = (uchar_t)cmdlen;
2551 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2552 cmd->cmd_tag = scsa2usbp->scsa2usb_tag++;
2553 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2555 cmd->cmd_bp = bp;
2557 * The buffer size of cmd->cmd_scb is constrained
2558 * to sizeof (struct scsi_arq_status), if the scblen
2559 * is bigger than that, we use pkt->pkt_scbp directly.
2561 if (cmd->cmd_scblen == sizeof (struct scsi_arq_status)) {
2562 pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
2565 usba_init_list(&cmd->cmd_waitQ, (usb_opaque_t)cmd,
2566 scsa2usbp->scsa2usb_dev_data->dev_iblock_cookie);
2567 } else {
2568 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2569 "scsa2usb: pkt != NULL");
2571 /* nothing to do */
2574 if (bp && (bp->b_bcount != 0)) {
2575 if ((bp_mapin_common(bp, (callback == SLEEP_FUNC) ?
2576 VM_SLEEP : VM_NOSLEEP)) == NULL) {
2577 if (pkt != in_pkt) {
2578 scsi_hba_pkt_free(ap, pkt);
2581 return (NULL);
2584 USB_DPRINTF_L3(DPRINT_MASK_SCSA,
2585 scsa2usbp->scsa2usb_log_handle,
2586 "scsa2usb_scsi_init_pkt: mapped in 0x%p, addr=0x%p",
2587 (void *)bp, (void *)bp->b_un.b_addr);
2590 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2591 "scsa2usb_scsi_init_pkt: ap = 0x%p pkt: 0x%p\n\t"
2592 "bp = 0x%p cmdlen = %x stlen = 0x%x tlen = 0x%x flags = 0x%x",
2593 (void *)ap, (void *)pkt, (void *)bp, cmdlen, statuslen,
2594 tgtlen, flags);
2596 return (pkt);
2601 * scsa2usb_scsi_destroy_pkt:
2602 * We are done with the packet. Get rid of it.
2604 static void
2605 scsa2usb_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
2607 scsa2usb_cmd_t *cmd = PKT2CMD(pkt);
2608 scsa2usb_state_t *scsa2usbp = ADDR2SCSA2USB(ap);
2610 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2611 "scsa2usb_scsi_destroy_pkt: pkt=0x%p", (void *)pkt);
2613 usba_destroy_list(&cmd->cmd_waitQ);
2614 scsi_hba_pkt_free(ap, pkt);
2619 * scsa2usb_scsi_start:
2620 * For each command being issued, build up the CDB
2621 * and call scsi_transport to issue the command. This
2622 * function is based on the assumption that USB allows
2623 * a subset of SCSI commands. Other SCSI commands we fail.
2625 static int
2626 scsa2usb_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
2628 scsa2usb_cmd_t *cmd;
2629 scsa2usb_state_t *scsa2usbp = ADDR2SCSA2USB(ap);
2630 uint_t lun = ap->a_lun;
2632 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2634 cmd = PKT2CMD(pkt);
2635 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2636 "scsa2usb_scsi_start:\n\t"
2637 "bp: 0x%p ap: 0x%p pkt: 0x%p flag: 0x%x time: 0x%x\n\tcdb0: 0x%x "
2638 "dev_state: 0x%x pkt_state: 0x%x flags: 0x%x pipe_state: 0x%x",
2639 (void *)cmd->cmd_bp, (void *)ap, (void *)pkt, pkt->pkt_flags,
2640 pkt->pkt_time, pkt->pkt_cdbp[0], scsa2usbp->scsa2usb_dev_state,
2641 scsa2usbp->scsa2usb_pkt_state, scsa2usbp->scsa2usb_flags,
2642 scsa2usbp->scsa2usb_pipe_state);
2644 if (pkt->pkt_time == 0) {
2645 USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2646 "pkt submitted with 0 timeout which may cause indefinite "
2647 "hangs");
2651 * if we are in panic, we are in polled mode, so we can just
2652 * accept the request, drop it and return
2653 * if we fail this request, the rest of the file systems do not
2654 * get synced
2656 if (ddi_in_panic()) {
2657 extern int do_polled_io;
2659 ASSERT(do_polled_io);
2660 scsa2usb_prepare_pkt(scsa2usbp, pkt);
2661 SCSA2USB_PRINT_SYNC_MSG(scsa2usb_sync_message, scsa2usbp);
2662 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2664 return (TRAN_ACCEPT);
2667 /* we cannot do polling, this should not happen */
2668 if (pkt->pkt_flags & FLAG_NOINTR) {
2669 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2670 "NOINTR packet: opcode = 0%x", pkt->pkt_cdbp[0]);
2671 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2673 return (TRAN_BADPKT);
2676 /* prepare packet */
2677 scsa2usb_prepare_pkt(scsa2usbp, pkt);
2679 /* just queue up the requests in the waitQ if below max */
2680 if (usba_list_entry_count(&scsa2usbp->scsa2usb_waitQ[lun]) >
2681 SCSA2USB_MAX_REQ_PER_LUN) {
2682 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
2683 scsa2usbp->scsa2usb_log_handle,
2684 "scsa2usb_scsi_start: limit (%d) exceeded",
2685 SCSA2USB_MAX_REQ_PER_LUN);
2686 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2688 return (TRAN_BUSY);
2691 usba_add_to_list(&scsa2usbp->scsa2usb_waitQ[lun], &cmd->cmd_waitQ);
2693 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2694 "scsa2usb_work_thread_id=0x%p, count=%d, lun=%d",
2695 (void *)scsa2usbp->scsa2usb_work_thread_id,
2696 usba_list_entry_count(&scsa2usbp->scsa2usb_waitQ[lun]), lun);
2698 /* fire up a thread to start executing the protocol */
2699 if (scsa2usbp->scsa2usb_work_thread_id == 0) {
2700 if ((usb_async_req(scsa2usbp->scsa2usb_dip,
2701 scsa2usb_work_thread,
2702 (void *)scsa2usbp, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
2703 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
2704 scsa2usbp->scsa2usb_log_handle,
2705 "no work thread started");
2707 if (usba_rm_from_list(
2708 &scsa2usbp->scsa2usb_waitQ[lun],
2709 &cmd->cmd_waitQ) == USB_SUCCESS) {
2710 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2712 return (TRAN_BUSY);
2713 } else {
2715 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2717 return (TRAN_ACCEPT);
2720 scsa2usbp->scsa2usb_work_thread_id = (kthread_t *)1;
2723 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2725 return (TRAN_ACCEPT);
2730 * scsa2usb_scsi_abort:
2731 * Issue SCSI abort command. This function is a NOP.
2733 /* ARGSUSED */
2734 static int
2735 scsa2usb_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
2737 scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap);
2739 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2740 "scsa2usb_scsi_abort: pkt = %p", (void *)pkt);
2742 /* if device is disconnected (ie. pipes closed), fail immediately */
2743 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2744 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) {
2745 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2747 return (0);
2750 /* flush waitQ if target and lun match */
2751 if ((ap->a_target == pkt->pkt_address.a_target) &&
2752 (ap->a_lun == pkt->pkt_address.a_lun)) {
2753 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2754 scsa2usb_flush_waitQ(scsa2usbp, ap->a_lun, CMD_ABORTED);
2755 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2757 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2759 return (0);
2764 * scsa2usb_scsi_reset:
2765 * device reset may turn the device into a brick and bus reset
2766 * is not applicable.
2767 * just flush the waitQ
2768 * We return success, always.
2770 /* ARGSUSED */
2771 static int
2772 scsa2usb_scsi_reset(struct scsi_address *ap, int level)
2774 scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap);
2776 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2777 "scsa2usb_scsi_reset: ap = 0x%p, level = %d", (void *)ap, level);
2779 /* flush waitQ */
2780 scsa2usb_flush_waitQ(scsa2usbp, ap->a_lun, CMD_RESET);
2782 return (1);
2787 * scsa2usb_scsi_getcap:
2788 * Get SCSI capabilities.
2790 /* ARGSUSED */
2791 static int
2792 scsa2usb_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
2794 int rval = -1;
2795 uint_t cidx;
2796 size_t dev_bsize_cap;
2797 scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap);
2798 ASSERT(scsa2usbp);
2800 if (cap == NULL) {
2801 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2802 "scsa2usb_scsi_getcap: invalid arg, "
2803 "cap = 0x%p whom = %d", (void *)cap, whom);
2805 return (rval);
2808 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2809 "scsa2usb_scsi_getcap: cap = %s", cap);
2811 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2813 /* if device is disconnected (ie. pipes closed), fail immediately */
2814 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) {
2816 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2818 return (rval);
2821 cidx = scsi_hba_lookup_capstr(cap);
2822 switch (cidx) {
2823 case SCSI_CAP_GEOMETRY:
2824 /* Just check and fail immediately if zero, rarely happens */
2825 if (scsa2usbp->scsa2usb_secsz[ap->a_lun] == 0) {
2826 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
2827 scsa2usbp->scsa2usb_log_handle,
2828 "scsa2usb_scsi_getcap failed:"
2829 "scsa2usbp->scsa2usb_secsz[ap->a_lun] == 0");
2830 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2832 return (rval);
2835 dev_bsize_cap = scsa2usbp->scsa2usb_totalsec[ap->a_lun];
2837 if (scsa2usbp->scsa2usb_secsz[ap->a_lun] > DEV_BSIZE) {
2838 dev_bsize_cap *=
2839 scsa2usbp->scsa2usb_secsz[ap->a_lun] / DEV_BSIZE;
2840 } else if (scsa2usbp->scsa2usb_secsz[ap->a_lun] <
2841 DEV_BSIZE) {
2842 dev_bsize_cap /=
2843 DEV_BSIZE / scsa2usbp->scsa2usb_secsz[ap->a_lun];
2846 if (dev_bsize_cap < 65536 * 2 * 18) { /* < ~1GB */
2847 /* unlabeled floppy, 18k per cylinder */
2848 rval = ((2 << 16) | 18);
2849 } else if (dev_bsize_cap < 65536 * 64 * 32) { /* < 64GB */
2850 /* 1024k per cylinder */
2851 rval = ((64 << 16) | 32);
2852 } else if (dev_bsize_cap < 65536 * 255 * 63) { /* < ~500GB */
2853 /* ~8m per cylinder */
2854 rval = ((255 << 16) | 63);
2855 } else { /* .. 8TB */
2856 /* 64m per cylinder */
2857 rval = ((512 << 16) | 256);
2859 break;
2861 case SCSI_CAP_DMA_MAX:
2862 rval = scsa2usbp->scsa2usb_max_bulk_xfer_size;
2863 break;
2864 case SCSI_CAP_SCSI_VERSION:
2865 rval = SCSI_VERSION_2;
2866 break;
2867 case SCSI_CAP_INTERCONNECT_TYPE:
2868 rval = INTERCONNECT_USB;
2869 break;
2870 case SCSI_CAP_ARQ:
2871 /* FALLTHRU */
2872 case SCSI_CAP_UNTAGGED_QING:
2873 rval = 1;
2874 break;
2875 default:
2876 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2877 "scsa2usb_scsi_getcap: unsupported cap = %s", cap);
2878 break;
2881 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2882 "scsa2usb_scsi_getcap: cap = %s, returned = %d", cap, rval);
2884 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2886 return (rval);
2891 * scsa2usb_scsi_setcap:
2892 * Set SCSI capabilities.
2894 /* ARGSUSED */
2895 static int
2896 scsa2usb_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
2898 int rval = -1; /* default is cap undefined */
2899 uint_t cidx;
2900 scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap);
2901 ASSERT(scsa2usbp);
2903 if (cap == NULL || whom == 0) {
2904 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2905 "scsa2usb_scsi_setcap: invalid arg");
2907 return (rval);
2910 mutex_enter(&scsa2usbp->scsa2usb_mutex);
2911 /* if device is disconnected (ie. pipes closed), fail immediately */
2912 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) {
2913 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2915 return (rval);
2918 cidx = scsi_hba_lookup_capstr(cap);
2919 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2920 "scsa2usb_scsi_setcap: ap = 0x%p value = 0x%x whom = 0x%x "
2921 "cidx = 0x%x", (void *)ap, value, whom, cidx);
2923 switch (cidx) {
2924 case SCSI_CAP_SECTOR_SIZE:
2925 if (value) {
2926 scsa2usbp->scsa2usb_secsz[ap->a_lun] = value;
2928 break;
2929 case SCSI_CAP_TOTAL_SECTORS:
2930 if (value) {
2931 scsa2usbp->scsa2usb_totalsec[ap->a_lun] = value;
2933 break;
2934 case SCSI_CAP_ARQ:
2935 rval = 1;
2936 break;
2937 case SCSI_CAP_DMA_MAX:
2938 case SCSI_CAP_SCSI_VERSION:
2939 case SCSI_CAP_INTERCONNECT_TYPE:
2940 case SCSI_CAP_UNTAGGED_QING:
2941 /* supported but not settable */
2942 rval = 0;
2943 break;
2944 default:
2945 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2946 "scsa2usb_scsi_setcap: unsupported cap = %s", cap);
2947 break;
2950 mutex_exit(&scsa2usbp->scsa2usb_mutex);
2952 return (rval);
2957 * scsa2usb - cmd and transport stuff
2960 * scsa2usb_prepare_pkt:
2961 * initialize some fields of the pkt and cmd
2962 * (the pkt may have been resubmitted/retried)
2964 static void
2965 scsa2usb_prepare_pkt(scsa2usb_state_t *scsa2usbp, struct scsi_pkt *pkt)
2967 scsa2usb_cmd_t *cmd = PKT2CMD(pkt);
2969 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
2970 "scsa2usb_prepare_pkt: pkt=0x%p cdb: 0x%x (%s)",
2971 (void *)pkt, pkt->pkt_cdbp[0],
2972 scsi_cname(pkt->pkt_cdbp[0], scsa2usb_cmds));
2974 pkt->pkt_reason = CMD_CMPLT; /* Set reason to pkt_complete */
2975 pkt->pkt_state = 0; /* Reset next three fields */
2976 pkt->pkt_statistics = 0;
2977 pkt->pkt_resid = 0;
2978 bzero(pkt->pkt_scbp, cmd->cmd_scblen); /* Set status to good */
2980 if (cmd) {
2981 cmd->cmd_timeout = pkt->pkt_time;
2982 cmd->cmd_xfercount = 0; /* Reset the fields */
2983 cmd->cmd_total_xfercount = 0;
2984 cmd->cmd_lba = 0;
2985 cmd->cmd_done = 0;
2986 cmd->cmd_dir = 0;
2987 cmd->cmd_offset = 0;
2988 cmd->cmd_actual_len = cmd->cmd_cdblen;
2994 * scsa2usb_force_invalid_request
2996 static void
2997 scsa2usb_force_invalid_request(scsa2usb_state_t *scsa2usbp,
2998 scsa2usb_cmd_t *cmd)
3000 struct scsi_arq_status *arqp;
3002 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3003 "scsa2usb_force_invalid_request: pkt = 0x%p", (void *)cmd->cmd_pkt);
3005 if (cmd->cmd_scblen >= sizeof (struct scsi_arq_status)) {
3006 arqp = (struct scsi_arq_status *)cmd->cmd_pkt->pkt_scbp;
3007 bzero(arqp, cmd->cmd_scblen);
3009 arqp->sts_status.sts_chk = 1;
3010 arqp->sts_rqpkt_reason = CMD_CMPLT;
3011 arqp->sts_rqpkt_state = STATE_XFERRED_DATA |
3012 STATE_GOT_BUS | STATE_GOT_STATUS;
3013 arqp->sts_sensedata.es_valid = 1;
3014 arqp->sts_sensedata.es_class = 7;
3015 arqp->sts_sensedata.es_key = KEY_ILLEGAL_REQUEST;
3017 cmd->cmd_pkt->pkt_state = STATE_ARQ_DONE |
3018 STATE_GOT_BUS | STATE_GOT_BUS | STATE_GOT_BUS |
3019 STATE_GOT_STATUS;
3020 #ifdef DEBUG
3022 uchar_t *p = (uchar_t *)(&arqp->sts_sensedata);
3023 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
3024 scsa2usbp->scsa2usb_log_handle,
3025 "cdb: %x rqsense: "
3026 "%x %x %x %x %x %x %x %x %x %x "
3027 "%x %x %x %x %x %x %x %x %x %x",
3028 cmd->cmd_pkt->pkt_cdbp[0],
3029 p[0], p[1], p[2], p[3], p[4],
3030 p[5], p[6], p[7], p[8], p[9],
3031 p[10], p[11], p[12], p[13], p[14],
3032 p[15], p[16], p[17], p[18], p[19]);
3034 #endif
3041 * scsa2usb_cmd_transport:
3043 static int
3044 scsa2usb_cmd_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd)
3046 int rval, transport;
3047 struct scsi_pkt *pkt;
3049 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3050 "scsa2usb_cmd_transport: pkt: 0x%p, cur_pkt = 0x%p",
3051 (void *)cmd->cmd_pkt, (void *)scsa2usbp->scsa2usb_cur_pkt);
3053 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
3054 ASSERT(scsa2usbp->scsa2usb_cur_pkt == NULL);
3056 pkt = scsa2usbp->scsa2usb_cur_pkt = cmd->cmd_pkt;
3058 /* check black-listed attrs first */
3059 if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) {
3060 transport = scsa2usb_check_bulkonly_blacklist_attrs(scsa2usbp,
3061 cmd, pkt->pkt_cdbp[0]);
3062 } else if (SCSA2USB_IS_CB(scsa2usbp) || SCSA2USB_IS_CBI(scsa2usbp)) {
3063 transport = scsa2usb_check_ufi_blacklist_attrs(scsa2usbp,
3064 pkt->pkt_cdbp[0], cmd);
3067 /* just accept the command or return error */
3068 if (transport == SCSA2USB_JUST_ACCEPT) {
3069 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp);
3071 return (TRAN_ACCEPT);
3072 } else if (transport == SCSA2USB_REJECT) {
3073 return (TRAN_FATAL_ERROR);
3076 /* check command set next */
3077 if (SCSA2USB_IS_SCSI_CMDSET(scsa2usbp) ||
3078 SCSA2USB_IS_ATAPI_CMDSET(scsa2usbp)) {
3079 transport =
3080 scsa2usb_handle_scsi_cmd_sub_class(scsa2usbp, cmd, pkt);
3081 } else if (SCSA2USB_IS_UFI_CMDSET(scsa2usbp)) {
3082 transport =
3083 scsa2usb_handle_ufi_subclass_cmd(scsa2usbp, cmd, pkt);
3084 } else {
3085 transport = SCSA2USB_REJECT;
3088 switch (transport) {
3089 case SCSA2USB_TRANSPORT:
3090 if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) {
3091 rval = scsa2usb_bulk_only_transport(scsa2usbp, cmd);
3092 } else if (SCSA2USB_IS_CB(scsa2usbp) ||
3093 SCSA2USB_IS_CBI(scsa2usbp)) {
3094 rval = scsa2usb_cbi_transport(scsa2usbp, cmd);
3095 } else {
3096 rval = TRAN_FATAL_ERROR;
3098 break;
3099 case SCSA2USB_JUST_ACCEPT:
3100 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp);
3101 rval = TRAN_ACCEPT;
3102 break;
3103 default:
3104 rval = TRAN_FATAL_ERROR;
3107 return (rval);
3112 * scsa2usb_check_bulkonly_blacklist_attrs:
3113 * validate "scsa2usb_blacklist_attrs" (see scsa2usb.h)
3114 * if blacklisted attrs match accept the request
3115 * attributes checked are:-
3116 * SCSA2USB_ATTRS_START_STOP
3119 scsa2usb_check_bulkonly_blacklist_attrs(scsa2usb_state_t *scsa2usbp,
3120 scsa2usb_cmd_t *cmd, uchar_t opcode)
3122 struct scsi_inquiry *inq =
3123 &scsa2usbp->scsa2usb_lun_inquiry[cmd->cmd_pkt->pkt_address.a_lun];
3125 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3126 "scsa2usb_check_bulkonly_blacklist_attrs: opcode = %s",
3127 scsi_cname(opcode, scsa2usb_cmds));
3129 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
3132 * decode and convert the packet
3133 * for most cmds, we can bcopy the cdb
3135 switch (opcode) {
3136 case SCMD_DOORLOCK:
3137 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_DOORLOCK)) {
3139 return (SCSA2USB_JUST_ACCEPT);
3142 * only lock the door for CD and DVD drives
3144 } else if ((inq->inq_dtype == DTYPE_RODIRECT) ||
3145 (inq->inq_dtype == DTYPE_OPTICAL)) {
3147 if (inq->inq_rmb) {
3149 break;
3153 return (SCSA2USB_JUST_ACCEPT);
3155 case SCMD_START_STOP: /* SCMD_LOAD for sequential devices */
3157 * these devices don't have mechanics that spin the
3158 * media up and down. So, it doesn't make much sense
3159 * to issue this cmd.
3161 * Furthermore, Hagiwara devices do not handle these
3162 * cmds well. just accept this command as success.
3164 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_START_STOP)) {
3166 return (SCSA2USB_JUST_ACCEPT);
3168 } else if (inq->inq_dtype == DTYPE_SEQUENTIAL) {
3170 * In case of USB tape device, we need to send the
3171 * command to the device to unload the media.
3173 break;
3175 } else if (cmd->cmd_pkt->pkt_cdbp[4] & LOEJECT) {
3177 * if the device is really a removable then
3178 * pass it on to the device, else just accept
3180 if (inq->inq_rmb) {
3182 break;
3185 return (SCSA2USB_JUST_ACCEPT);
3187 } else if (!scsa2usbp->scsa2usb_rcvd_not_ready) {
3189 * if we have not received a NOT READY condition,
3190 * just accept since some device choke on this too.
3191 * we do have to let EJECT get through though
3193 return (SCSA2USB_JUST_ACCEPT);
3196 break;
3197 case SCMD_INQUIRY:
3199 * Some devices do not handle the inquiry cmd well
3200 * so build an inquiry and accept this command as
3201 * success.
3203 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_INQUIRY)) {
3204 uchar_t evpd = 0x01;
3205 unsigned int bufsize;
3206 int count;
3208 if (cmd->cmd_pkt->pkt_cdbp[1] & evpd)
3209 return (SCSA2USB_REJECT);
3211 scsa2usb_fake_inquiry(scsa2usbp, inq);
3213 /* Copy no more than requested */
3214 count = MIN(cmd->cmd_bp->b_bcount,
3215 sizeof (struct scsi_inquiry));
3216 bufsize = cmd->cmd_pkt->pkt_cdbp[4];
3217 count = MIN(count, bufsize);
3218 bcopy(inq, cmd->cmd_bp->b_un.b_addr, count);
3220 cmd->cmd_pkt->pkt_resid = bufsize - count;
3221 cmd->cmd_pkt->pkt_state |= STATE_XFERRED_DATA;
3223 return (SCSA2USB_JUST_ACCEPT);
3224 } else if (!(scsa2usbp->scsa2usb_attrs &
3225 SCSA2USB_ATTRS_INQUIRY_EVPD)) {
3227 * Some devices do not handle the inquiry cmd with
3228 * evpd bit set well, e.g. some devices return the
3229 * same page 0x83 data which will cause the generated
3230 * devid by sd is not unique, thus return CHECK
3231 * CONDITION directly to sd.
3233 uchar_t evpd = 0x01;
3235 if (!(cmd->cmd_pkt->pkt_cdbp[1] & evpd))
3236 break;
3238 if (cmd->cmd_bp) {
3239 cmd->cmd_pkt->pkt_resid = cmd->cmd_bp->
3240 b_bcount;
3242 scsa2usb_force_invalid_request(scsa2usbp, cmd);
3244 return (SCSA2USB_JUST_ACCEPT);
3246 break;
3248 * Fake accepting the following Opcodes
3249 * (as most drives don't support these)
3250 * These are needed by format command.
3252 case SCMD_RESERVE:
3253 case SCMD_RELEASE:
3254 case SCMD_PERSISTENT_RESERVE_IN:
3255 case SCMD_PERSISTENT_RESERVE_OUT:
3257 return (SCSA2USB_JUST_ACCEPT);
3259 case SCMD_MODE_SENSE:
3260 case SCMD_MODE_SELECT:
3261 case SCMD_MODE_SENSE_G1:
3262 case SCMD_MODE_SELECT_G1:
3263 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_MODE_SENSE)) {
3264 if (cmd->cmd_bp) {
3265 cmd->cmd_pkt->pkt_resid = cmd->cmd_bp->
3266 b_bcount;
3268 scsa2usb_force_invalid_request(scsa2usbp, cmd);
3270 return (SCSA2USB_JUST_ACCEPT);
3273 break;
3274 default:
3276 break;
3279 return (SCSA2USB_TRANSPORT);
3284 * scsa2usb_handle_scsi_cmd_sub_class:
3285 * prepare a scsi cmd
3286 * returns SCSA2USB_TRANSPORT, SCSA2USB_REJECT, SCSA2USB_JUST_ACCEPT
3289 scsa2usb_handle_scsi_cmd_sub_class(scsa2usb_state_t *scsa2usbp,
3290 scsa2usb_cmd_t *cmd, struct scsi_pkt *pkt)
3292 uchar_t evpd = 0x01;
3293 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3294 "scsa2usb_handle_scsi_cmd_sub_class: cmd = 0x%p pkt = 0x%p",
3295 (void *)cmd, (void *)pkt);
3297 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
3299 bzero(&cmd->cmd_cdb, SCSI_CDB_SIZE);
3300 cmd->cmd_cdb[SCSA2USB_OPCODE] = pkt->pkt_cdbp[0]; /* Set the opcode */
3301 cmd->cmd_cdb[SCSA2USB_LUN] = pkt->pkt_cdbp[1];
3304 * decode and convert the packet
3305 * for most cmds, we can bcopy the cdb
3307 switch (pkt->pkt_cdbp[0]) {
3308 case SCMD_FORMAT:
3310 * SCMD_FORMAT used to limit cmd->cmd_xfercount
3311 * to 4 bytes, but this hangs
3312 * formatting dvd media using cdrecord (that is,
3313 * a SCSI FORMAT UNIT command with a parameter list > 4 bytes)
3314 * (bit 4 in cdb1 is the Fmtdata bit)
3316 if ((pkt->pkt_cdbp[1] & 0x10) && cmd->cmd_bp) {
3317 cmd->cmd_xfercount = cmd->cmd_bp->b_bcount;
3318 } else {
3319 cmd->cmd_xfercount = 4;
3321 cmd->cmd_dir = CBW_DIR_OUT;
3322 cmd->cmd_actual_len = CDB_GROUP0;
3323 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3324 break;
3326 case SCMD_INQUIRY:
3327 cmd->cmd_dir = CBW_DIR_IN;
3328 cmd->cmd_actual_len = CDB_GROUP0;
3329 cmd->cmd_cdb[SCSA2USB_LBA_0] = pkt->pkt_cdbp[2];
3332 * If vpd pages data is limited to maximum SCSA2USB_MAX_INQ_LEN,
3333 * the page data may be truncated, which may cause some issues
3334 * such as making the unique page 0x83 or 0x80 data from
3335 * different devices become the same. So don't limit return
3336 * length for vpd page inquiry cmd.
3337 * Another, in order to maintain compatibility, the original
3338 * length limitation for standard inquiry retains here. It
3339 * can be removed in future if it is verified that enough
3340 * devices can work well.
3342 if (pkt->pkt_cdbp[1] & evpd) {
3343 cmd->cmd_cdb[SCSA2USB_LBA_2] = cmd->cmd_xfercount =
3344 (cmd->cmd_bp ? cmd->cmd_bp->b_bcount : 0);
3345 } else {
3346 cmd->cmd_cdb[SCSA2USB_LBA_2] = cmd->cmd_xfercount =
3347 min(SCSA2USB_MAX_INQ_LEN,
3348 cmd->cmd_bp ? cmd->cmd_bp->b_bcount : 0);
3350 break;
3352 case SCMD_READ_CAPACITY:
3353 cmd->cmd_dir = CBW_DIR_IN;
3354 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3355 cmd->cmd_xfercount = sizeof (scsa2usb_read_cap_t);
3356 break;
3359 * SCMD_READ/SCMD_WRITE are converted to G1 cmds
3360 * (as ATAPI devices don't recognize G0 commands)
3362 * SCMD_READ_LONG/SCMD_WRITE_LONG are handled in
3363 * scsa2usb_rw_transport() along with other commands.
3365 * USB Host Controllers cannot handle large (read/write)
3366 * xfers. We split the large request to chunks of
3367 * smaller ones to meet the HCD limitations.
3369 case SCMD_READ:
3370 case SCMD_WRITE:
3371 case SCMD_READ_G1:
3372 case SCMD_WRITE_G1:
3373 case SCMD_READ_G5:
3374 case SCMD_WRITE_G5:
3375 case SCMD_READ_LONG:
3376 case SCMD_WRITE_LONG:
3377 case SCMD_READ_CD:
3378 switch (scsa2usbp->
3379 scsa2usb_lun_inquiry[pkt->pkt_address.a_lun].
3380 inq_dtype & DTYPE_MASK) {
3381 case DTYPE_DIRECT:
3382 case DTYPE_RODIRECT:
3383 case DTYPE_OPTICAL:
3384 return (scsa2usb_rw_transport(
3385 scsa2usbp, pkt));
3386 default:
3387 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3388 if (cmd->cmd_bp) {
3389 cmd->cmd_dir =
3390 (cmd->cmd_bp->b_flags & B_READ) ?
3391 CBW_DIR_IN : CBW_DIR_OUT;
3392 cmd->cmd_xfercount =
3393 cmd->cmd_bp->b_bcount;
3395 break;
3397 break;
3399 case SCMD_REQUEST_SENSE:
3400 cmd->cmd_dir = CBW_DIR_IN;
3401 cmd->cmd_xfercount = pkt->pkt_cdbp[4];
3402 cmd->cmd_cdb[SCSA2USB_LBA_2] = pkt->pkt_cdbp[4];
3403 cmd->cmd_actual_len = CDB_GROUP0;
3404 break;
3406 case SCMD_DOORLOCK:
3407 case SCMD_START_STOP:
3408 case SCMD_TEST_UNIT_READY:
3409 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3410 break;
3413 * Needed by zip protocol to reset the device
3415 case SCMD_SDIAG:
3416 case SCMD_REZERO_UNIT:
3417 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3418 cmd->cmd_actual_len = CDB_GROUP1;
3419 break;
3421 case SCMD_WRITE_VERIFY:
3422 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3423 cmd->cmd_dir = CBW_DIR_OUT;
3424 cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8];
3425 cmd->cmd_actual_len = CDB_GROUP1;
3426 break;
3429 * Next command does not have a SCSI equivalent as
3430 * it is vendor specific.
3431 * It was listed in the vendor's ATAPI Zip specs.
3433 case SCMD_READ_FORMAT_CAP:
3434 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3435 cmd->cmd_dir = CBW_DIR_IN;
3436 cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8];
3437 cmd->cmd_actual_len = CDB_GROUP1;
3438 break;
3439 case IOMEGA_CMD_CARTRIDGE_PROTECT:
3440 cmd->cmd_dir = CBW_DIR_OUT;
3441 cmd->cmd_cdb[SCSA2USB_LBA_2] = pkt->pkt_cdbp[4];
3442 cmd->cmd_cdb[SCSA2USB_LBA_2] &= ~1; /* Make it even */
3443 cmd->cmd_cdb[SCSA2USB_LUN] = pkt->pkt_cdbp[1];
3444 cmd->cmd_actual_len = CDB_GROUP0;
3445 cmd->cmd_xfercount = pkt->pkt_cdbp[4]; /* Length of password */
3446 break;
3449 * Do not convert SCMD_MODE_SENSE/SELECT to G1 cmds because
3450 * the mode header is different as well. USB devices don't
3451 * support 0x03 & 0x04 mode pages, which are already obsoleted
3452 * by SPC-2 specification.
3454 case SCMD_MODE_SENSE:
3455 case SCMD_MODE_SELECT:
3456 if (((pkt->pkt_cdbp[2] & SD_MODE_SENSE_PAGE_MASK)
3457 == SD_MODE_SENSE_PAGE3_CODE) ||
3458 ((pkt->pkt_cdbp[2] & SD_MODE_SENSE_PAGE_MASK)
3459 == SD_MODE_SENSE_PAGE4_CODE)) {
3460 if (cmd->cmd_bp) {
3461 cmd->cmd_pkt->pkt_resid = cmd->cmd_bp->b_bcount;
3463 scsa2usb_force_invalid_request(scsa2usbp, cmd);
3464 return (SCSA2USB_JUST_ACCEPT);
3466 /* FALLTHROUGH */
3468 default:
3470 * an unknown command may be a uscsi cmd which we
3471 * should let go thru without mapping
3473 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3474 if (cmd->cmd_bp) {
3475 cmd->cmd_dir = (cmd->cmd_bp->b_flags & B_READ) ?
3476 CBW_DIR_IN : CBW_DIR_OUT;
3477 cmd->cmd_xfercount = cmd->cmd_bp->b_bcount;
3480 break;
3481 } /* end of switch */
3483 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3484 "scsa2usb_handle_scsi_cmd_sub_class: opcode = 0x%x count = 0x%lx",
3485 pkt->pkt_cdbp[SCSA2USB_OPCODE], cmd->cmd_xfercount);
3487 cmd->cmd_total_xfercount = cmd->cmd_xfercount;
3489 return (SCSA2USB_TRANSPORT);
3494 * scsa2usb_do_tur is performed before READ CAPACITY command is issued.
3495 * It returns media status, 0 for media ready, -1 for media not ready
3496 * or other errors.
3498 static int
3499 scsa2usb_do_tur(scsa2usb_state_t *scsa2usbp, struct scsi_address *ap)
3501 struct scsi_pkt *pkt;
3502 scsa2usb_cmd_t *turcmd;
3503 int rval = -1;
3505 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3506 "scsa2usb_do_tur:");
3508 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
3510 mutex_exit(&scsa2usbp->scsa2usb_mutex);
3511 if ((pkt = scsi_init_pkt(ap, NULL, NULL, CDB_GROUP0, 1,
3512 PKT_PRIV_LEN, PKT_CONSISTENT, SLEEP_FUNC, NULL)) == NULL) {
3513 mutex_enter(&scsa2usbp->scsa2usb_mutex);
3514 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
3515 scsa2usbp->scsa2usb_log_handle,
3516 "scsa2usb_do_tur: init pkt failed");
3518 return (rval);
3521 RQ_MAKECOM_G0(pkt, FLAG_HEAD | FLAG_NODISCON,
3522 (char)SCMD_TEST_UNIT_READY, 0, 0);
3524 pkt->pkt_comp = NULL;
3525 pkt->pkt_time = PKT_DEFAULT_TIMEOUT;
3526 turcmd = PKT2CMD(pkt);
3528 mutex_enter(&scsa2usbp->scsa2usb_mutex);
3529 scsa2usb_prepare_pkt(scsa2usbp, turcmd->cmd_pkt);
3531 if (scsa2usb_cmd_transport(scsa2usbp, turcmd) != TRAN_ACCEPT) {
3532 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
3533 scsa2usbp->scsa2usb_log_handle,
3534 "scsa2usb_do_tur: cmd transport failed, "
3535 "pkt_reason=0x%x", turcmd->cmd_pkt->pkt_reason);
3536 } else if (*(turcmd->cmd_pkt->pkt_scbp) != STATUS_GOOD) {
3538 * Theoretically, the sense data should be retrieved and
3539 * sense key be checked when check condition happens. If
3540 * the sense key is UNIT ATTENTION, TEST UNIT READY cmd
3541 * needs to be sent again to clear the UNIT ATTENTION and
3542 * another TUR to be sent to get the real media status.
3543 * But the AMI virtual floppy device simply cannot recover
3544 * from UNIT ATTENTION by re-sending a TUR cmd, so it
3545 * doesn't make any difference whether to check sense key
3546 * or not. Just ignore sense key checking here and assume
3547 * the device is NOT READY.
3549 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
3550 scsa2usbp->scsa2usb_log_handle,
3551 "scsa2usb_do_tur: media not ready");
3552 } else {
3553 rval = 0;
3556 mutex_exit(&scsa2usbp->scsa2usb_mutex);
3557 scsi_destroy_pkt(pkt);
3558 mutex_enter(&scsa2usbp->scsa2usb_mutex);
3560 return (rval);
3565 * scsa2usb_check_ufi_blacklist_attrs:
3566 * validate "scsa2usb_blacklist_attrs" (see scsa2usb.h)
3567 * if blacklisted attrs match accept the request
3568 * attributes checked are:-
3569 * SCSA2USB_ATTRS_GET_CONF
3570 * SCSA2USB_ATTRS_GET_PERF
3571 * SCSA2USB_ATTRS_GET_START_STOP
3573 static int
3574 scsa2usb_check_ufi_blacklist_attrs(scsa2usb_state_t *scsa2usbp, uchar_t opcode,
3575 scsa2usb_cmd_t *cmd)
3577 int rval = SCSA2USB_TRANSPORT;
3579 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
3581 switch (opcode) {
3582 case SCMD_PRIN:
3583 case SCMD_PROUT:
3584 rval = SCSA2USB_JUST_ACCEPT;
3585 break;
3586 case SCMD_MODE_SENSE:
3587 case SCMD_MODE_SELECT:
3588 if (cmd->cmd_bp) {
3589 cmd->cmd_pkt->pkt_resid = cmd->cmd_bp->b_bcount;
3591 scsa2usb_force_invalid_request(scsa2usbp, cmd);
3592 rval = SCSA2USB_JUST_ACCEPT;
3593 break;
3594 case SCMD_GET_CONFIGURATION:
3595 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_GET_CONF)) {
3596 rval = SCSA2USB_JUST_ACCEPT;
3598 break;
3599 case SCMD_GET_PERFORMANCE:
3600 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_GET_PERF)) {
3601 rval = SCSA2USB_JUST_ACCEPT;
3603 break;
3604 case SCMD_START_STOP:
3606 * some CB/CBI devices don't have mechanics that spin the
3607 * media up and down. So, it doesn't make much sense
3608 * to issue this cmd to those devices.
3610 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_START_STOP)) {
3611 rval = SCSA2USB_JUST_ACCEPT;
3613 break;
3614 case SCMD_READ_CAPACITY:
3616 * Some devices don't support READ CAPACITY command
3617 * when media is not ready. Need to check media status
3618 * before issuing the cmd to such device.
3620 if (!(scsa2usbp->scsa2usb_attrs &
3621 SCSA2USB_ATTRS_NO_MEDIA_CHECK)) {
3622 struct scsi_pkt *pkt = cmd->cmd_pkt;
3624 ASSERT(scsa2usbp->scsa2usb_cur_pkt == pkt);
3625 scsa2usbp->scsa2usb_cur_pkt = NULL;
3627 if (scsa2usb_do_tur(scsa2usbp,
3628 &pkt->pkt_address) != 0) {
3629 /* media not ready, force cmd invalid */
3630 if (cmd->cmd_bp) {
3631 cmd->cmd_pkt->pkt_resid =
3632 cmd->cmd_bp->b_bcount;
3634 scsa2usb_force_invalid_request(scsa2usbp, cmd);
3635 rval = SCSA2USB_JUST_ACCEPT;
3638 scsa2usbp->scsa2usb_cur_pkt = pkt;
3640 break;
3641 default:
3642 break;
3645 return (rval);
3650 * scsa2usb_handle_ufi_subclass_cmd:
3651 * prepare a UFI cmd
3652 * returns SCSA2USB_TRANSPORT, SCSA2USB_REJECT
3655 scsa2usb_handle_ufi_subclass_cmd(scsa2usb_state_t *scsa2usbp,
3656 scsa2usb_cmd_t *cmd, struct scsi_pkt *pkt)
3658 uchar_t opcode = pkt->pkt_cdbp[0];
3660 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3661 "scsa2usb_handle_ufi_subclass_cmd: cmd = 0x%p pkt = 0x%p",
3662 (void *)cmd, (void *)pkt);
3664 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
3666 bzero(&cmd->cmd_cdb, SCSI_CDB_SIZE);
3667 cmd->cmd_cdb[SCSA2USB_OPCODE] = opcode; /* Set the opcode */
3668 cmd->cmd_cdb[SCSA2USB_LUN] = pkt->pkt_cdbp[1];
3671 * decode and convert the packet if necessary
3672 * for most cmds, we can bcopy the cdb
3674 switch (opcode) {
3675 case SCMD_FORMAT:
3676 /* if parameter list is specified */
3677 if (pkt->pkt_cdbp[1] & 0x10) {
3678 cmd->cmd_xfercount =
3679 (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8];
3680 cmd->cmd_dir = USB_EP_DIR_OUT;
3681 cmd->cmd_actual_len = CDB_GROUP5;
3683 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3684 break;
3685 case SCMD_INQUIRY:
3686 cmd->cmd_dir = USB_EP_DIR_IN;
3687 cmd->cmd_actual_len = CDB_GROUP0;
3688 cmd->cmd_cdb[SCSA2USB_LBA_0] = pkt->pkt_cdbp[2];
3689 cmd->cmd_cdb[SCSA2USB_LBA_2] = cmd->cmd_xfercount =
3690 min(SCSA2USB_MAX_INQ_LEN,
3691 cmd->cmd_bp ? cmd->cmd_bp->b_bcount : 0);
3692 break;
3693 case SCMD_READ_CAPACITY:
3694 cmd->cmd_dir = USB_EP_DIR_IN;
3695 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3696 cmd->cmd_xfercount = sizeof (scsa2usb_read_cap_t);
3697 break;
3698 case SCMD_REQUEST_SENSE:
3699 cmd->cmd_dir = USB_EP_DIR_IN;
3700 cmd->cmd_xfercount = pkt->pkt_cdbp[4];
3701 cmd->cmd_cdb[SCSA2USB_LBA_2] = pkt->pkt_cdbp[4];
3702 cmd->cmd_actual_len = CDB_GROUP0;
3703 break;
3706 * do not convert SCMD_MODE_SENSE/SELECT because the
3707 * mode header is different as well
3711 * see usb_bulkonly.c for comments on the next set of commands
3713 case SCMD_READ:
3714 case SCMD_WRITE:
3715 case SCMD_READ_G1:
3716 case SCMD_WRITE_G1:
3717 case SCMD_READ_G5:
3718 case SCMD_WRITE_G5:
3719 case SCMD_READ_LONG:
3720 case SCMD_WRITE_LONG:
3721 case SCMD_READ_CD:
3723 return (scsa2usb_rw_transport(scsa2usbp, pkt));
3725 case SCMD_TEST_UNIT_READY:
3727 * Some CB/CBI devices may not support TUR.
3729 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3730 break;
3731 case SCMD_READ_FORMAT_CAP:
3732 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3733 cmd->cmd_dir = USB_EP_DIR_IN;
3734 cmd->cmd_actual_len = CDB_GROUP1;
3735 cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8];
3736 break;
3737 case SCMD_WRITE_VERIFY:
3738 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3739 cmd->cmd_dir = USB_EP_DIR_OUT;
3740 cmd->cmd_actual_len = CDB_GROUP1;
3741 cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8];
3742 break;
3743 case SCMD_START_STOP:
3744 /* A larger timeout is needed for 'flaky' CD-RW devices */
3745 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_BIG_TIMEOUT)) {
3746 cmd->cmd_timeout = max(cmd->cmd_timeout,
3747 20 * SCSA2USB_BULK_PIPE_TIMEOUT);
3749 /* FALLTHRU */
3750 default:
3752 * all other commands don't need special mapping
3754 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3755 if (cmd->cmd_bp) {
3756 cmd->cmd_dir = (cmd->cmd_bp->b_flags & B_READ) ?
3757 CBW_DIR_IN : CBW_DIR_OUT;
3758 cmd->cmd_xfercount = cmd->cmd_bp->b_bcount;
3760 break;
3762 } /* end of switch */
3764 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3765 "scsa2usb_handle_ufi_subclass_cmd: opcode = 0x%x count = 0x%lx",
3766 opcode, cmd->cmd_xfercount);
3768 cmd->cmd_total_xfercount = cmd->cmd_xfercount;
3770 return (SCSA2USB_TRANSPORT);
3775 * scsa2usb_rw_transport:
3776 * Handle splitting READ and WRITE requests to the
3777 * device to a size that the host controller allows.
3779 * returns TRAN_* values and not USB_SUCCESS/FAILURE
3781 * To support CD-R/CD-RW/DVD media, we need to support a
3782 * variety of block sizes for the different types of CD
3783 * data (audio, data, video, CD-XA, yellowbook, redbook etc.)
3785 * Some of the block sizes used are:- 512, 1k, 2k, 2056, 2336
3786 * 2340, 2352, 2368, 2448, 2646, 2647 etc.
3788 * NOTE: the driver could be entertaining a SCSI CDB that uses
3789 * any of the above listed block sizes at a given time, and a
3790 * totally different block size at any other given time for a
3791 * different CDB.
3793 * We need to compute block size every time and figure out
3794 * matching LBA and LEN accordingly.
3796 * Also UHCI has a limitation that it can only xfer 32k at a
3797 * given time. So, with "odd" sized blocks and a limitation of
3798 * how much we can xfer per shot, we need to compute xfer_count
3799 * as well each time.
3801 * The same computation is also done in the function
3802 * scsa2usb_setup_next_xfer(). To save computing block_size in
3803 * this function, I am saving block_size in "cmd" now.
3806 scsa2usb_rw_transport(scsa2usb_state_t *scsa2usbp, struct scsi_pkt *pkt)
3808 scsa2usb_cmd_t *cmd = PKT2CMD(pkt);
3809 int lba, dir, opcode;
3810 struct buf *bp = cmd->cmd_bp;
3811 size_t len, xfer_count;
3812 size_t blk_size; /* calculate the block size to be used */
3813 int sz;
3815 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3816 "scsa2usb_rw_transport:");
3818 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
3820 opcode = pkt->pkt_cdbp[0];
3821 blk_size = scsa2usbp->scsa2usb_lbasize[pkt->pkt_address.a_lun];
3822 /* set to default */
3824 switch (opcode) {
3825 case SCMD_READ:
3827 * Note that READ/WRITE(6) are not supported by the drive.
3828 * convert it into a 10 byte read/write.
3830 lba = SCSA2USB_LBA_6BYTE(pkt);
3831 len = SCSA2USB_LEN_6BYTE(pkt);
3832 opcode = SCMD_READ_G1; /* Overwrite it w/ byte 10 cmd val */
3833 dir = USB_EP_DIR_IN;
3834 break;
3835 case SCMD_WRITE:
3836 lba = SCSA2USB_LBA_6BYTE(pkt);
3837 len = SCSA2USB_LEN_6BYTE(pkt);
3838 opcode = SCMD_WRITE_G1; /* Overwrite it w/ byte 10 cmd val */
3839 dir = USB_EP_DIR_OUT;
3840 break;
3841 case SCMD_READ_G1:
3842 case SCMD_READ_LONG:
3843 lba = SCSA2USB_LBA_10BYTE(pkt);
3844 len = SCSA2USB_LEN_10BYTE(pkt);
3845 dir = USB_EP_DIR_IN;
3846 break;
3847 case SCMD_WRITE_G1:
3848 case SCMD_WRITE_LONG:
3849 lba = SCSA2USB_LBA_10BYTE(pkt);
3850 len = SCSA2USB_LEN_10BYTE(pkt);
3851 dir = USB_EP_DIR_OUT;
3852 if (len) {
3853 sz = SCSA2USB_CDRW_BLKSZ(bp ? bp->b_bcount : 0, len);
3854 if (SCSA2USB_VALID_CDRW_BLKSZ(sz)) {
3855 blk_size = sz; /* change it accordingly */
3858 break;
3859 case SCMD_READ_CD:
3860 lba = SCSA2USB_LBA_10BYTE(pkt);
3861 len = SCSA2USB_LEN_READ_CD(pkt);
3862 dir = USB_EP_DIR_IN;
3864 /* Figure out the block size */
3865 blk_size = scsa2usb_read_cd_blk_size(pkt->pkt_cdbp[1] >> 2);
3866 break;
3867 case SCMD_READ_G5:
3868 lba = SCSA2USB_LBA_12BYTE(pkt);
3869 len = SCSA2USB_LEN_12BYTE(pkt);
3870 dir = USB_EP_DIR_IN;
3871 break;
3872 case SCMD_WRITE_G5:
3873 lba = SCSA2USB_LBA_12BYTE(pkt);
3874 len = SCSA2USB_LEN_12BYTE(pkt);
3875 dir = USB_EP_DIR_OUT;
3876 break;
3879 cmd->cmd_total_xfercount = xfer_count = len * blk_size;
3881 /* reduce xfer count if necessary */
3882 if (blk_size &&
3883 (xfer_count > scsa2usbp->scsa2usb_max_bulk_xfer_size)) {
3885 * For CD-RW devices reduce the xfer count based
3886 * on the block size used by these devices. The
3887 * block size could change for READ_CD and WRITE
3888 * opcodes.
3890 * Also as UHCI allows a max xfer of 32k at a time;
3891 * compute the xfer_count based on the new block_size.
3893 * The len part of the cdb changes as a result of that.
3895 if (SCSA2USB_VALID_CDRW_BLKSZ(blk_size)) {
3896 xfer_count = ((scsa2usbp->scsa2usb_max_bulk_xfer_size/
3897 blk_size) * blk_size);
3898 len = xfer_count/blk_size;
3899 xfer_count = blk_size * len;
3900 } else {
3901 xfer_count = scsa2usbp->scsa2usb_max_bulk_xfer_size;
3902 len = xfer_count/blk_size;
3906 cmd->cmd_xfercount = xfer_count;
3907 cmd->cmd_dir = (uchar_t)dir;
3908 cmd->cmd_blksize = (int)blk_size;
3911 * Having figured out the 'partial' xfer len based on the
3912 * block size; fill it in to the cmd->cmd_cdb
3914 cmd->cmd_cdb[SCSA2USB_OPCODE] = (uchar_t)opcode;
3915 switch (opcode) {
3916 case SCMD_READ_CD:
3917 bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen);
3918 scsa2usb_fill_up_ReadCD_cdb_len(cmd, len, CDB_GROUP5);
3919 break;
3920 case SCMD_WRITE_G5:
3921 case SCMD_READ_G5:
3922 scsa2usb_fill_up_12byte_cdb_len(cmd, len, CDB_GROUP5);
3923 break;
3924 default:
3925 scsa2usb_fill_up_cdb_len(cmd, len);
3926 cmd->cmd_actual_len = CDB_GROUP1;
3927 break;
3930 scsa2usb_fill_up_cdb_lba(cmd, lba);
3932 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3933 "bcount=0x%lx lba=0x%x len=0x%lx xfercount=0x%lx total=0x%lx",
3934 bp ? bp->b_bcount : 0, lba, len, cmd->cmd_xfercount,
3935 cmd->cmd_total_xfercount);
3937 /* Set the timeout value as per command request */
3938 if ((opcode == SCMD_WRITE_G1) && SCSA2USB_VALID_CDRW_BLKSZ(blk_size)) {
3940 * We increase the time as CD-RW writes have two things
3941 * to do. After writing out the data to the media, a
3942 * TOC needs to be filled up at the beginning of the media
3943 * This is when the write gets "finalized".
3944 * Hence the actual write could take longer than the
3945 * value specified in cmd->cmd_timeout.
3947 cmd->cmd_timeout *= 4;
3949 USB_DPRINTF_L4(DPRINT_MASK_SCSA,
3950 scsa2usbp->scsa2usb_log_handle,
3951 "new timeout value = 0x%x", cmd->cmd_timeout);
3954 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3955 "lba 0x%x len 0x%lx xfercount 0x%lx total 0x%lx",
3956 lba, len, cmd->cmd_xfercount, cmd->cmd_total_xfercount);
3958 return (SCSA2USB_TRANSPORT);
3963 * scsa2usb_setup_next_xfer:
3964 * For READs and WRITEs we split up the transfer in terms of
3965 * HCD understood units. This function handles the split transfers.
3967 * See comments in the previous function scsa2usb_rw_transport
3969 * The lba computation was being done based on scsa2usb_max_bulk_xfer_size
3970 * earlier. With CD-RW devices, the xfer_count and the block_size may
3971 * no longer be a multiple of scsa2usb_max_bulk_xfer_size. So compute
3972 * xfer_count all over again. Adjust lba, based on the previous requests'
3973 * len. Find out the len and add it to cmd->cmd_lba to get the new lba
3975 void
3976 scsa2usb_setup_next_xfer(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd)
3978 int xfer_len = min(scsa2usbp->scsa2usb_max_bulk_xfer_size,
3979 cmd->cmd_total_xfercount);
3980 int cdb_len;
3981 size_t blk_size;
3983 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
3985 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
3986 "scsa2usb_setup_next_xfer: opcode = 0x%x lba = 0x%x "
3987 "total count = 0x%lx", cmd->cmd_cdb[SCSA2USB_OPCODE],
3988 cmd->cmd_lba, cmd->cmd_total_xfercount);
3990 ASSERT(cmd->cmd_total_xfercount > 0);
3991 cmd->cmd_xfercount = xfer_len;
3992 blk_size = scsa2usbp->scsa2usb_lbasize[
3993 cmd->cmd_pkt->pkt_address.a_lun];
3996 * For CD-RW devices reduce the xfer count based on the
3997 * block_size used by these devices. See changes below
3998 * where xfer_count is being adjusted.
4000 * Also adjust len/lba based on the block_size and xfer_count.
4001 * NOTE: Always calculate lba first, as it based on previous
4002 * commands' values.
4004 switch (cmd->cmd_cdb[SCSA2USB_OPCODE]) {
4005 case SCMD_READ_CD:
4006 /* calculate lba = current_lba + len_of_prev_cmd */
4007 cmd->cmd_lba += (cmd->cmd_cdb[6] << 16) +
4008 (cmd->cmd_cdb[7] << 8) + cmd->cmd_cdb[8];
4009 cdb_len = xfer_len/cmd->cmd_blksize;
4010 cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_2] = (uchar_t)cdb_len;
4011 /* re-adjust xfer count */
4012 cmd->cmd_xfercount = cdb_len * cmd->cmd_blksize;
4013 break;
4014 case SCMD_WRITE_G5:
4015 case SCMD_READ_G5:
4016 /* calculate lba = current_lba + len_of_prev_cmd */
4017 cmd->cmd_lba += (cmd->cmd_cdb[6] << 24) +
4018 (cmd->cmd_cdb[7] << 16) + (cmd->cmd_cdb[8] << 8) +
4019 cmd->cmd_cdb[9];
4020 if (blk_size) {
4021 xfer_len /= blk_size;
4023 scsa2usb_fill_up_12byte_cdb_len(cmd, xfer_len, CDB_GROUP5);
4024 break;
4025 case SCMD_WRITE_G1:
4026 case SCMD_WRITE_LONG:
4027 /* calculate lba = current_lba + len_of_prev_cmd */
4028 cmd->cmd_lba += (cmd->cmd_cdb[7] << 8) + cmd->cmd_cdb[8];
4029 if (SCSA2USB_VALID_CDRW_BLKSZ(cmd->cmd_blksize)) {
4030 blk_size = cmd->cmd_blksize;
4032 cdb_len = xfer_len/blk_size;
4033 scsa2usb_fill_up_cdb_len(cmd, cdb_len);
4034 /* re-adjust xfer count */
4035 cmd->cmd_xfercount = cdb_len * blk_size;
4036 break;
4037 default:
4038 if (blk_size) {
4039 xfer_len /= blk_size;
4041 scsa2usb_fill_up_cdb_len(cmd, xfer_len);
4042 cmd->cmd_lba += scsa2usbp->scsa2usb_max_bulk_xfer_size/blk_size;
4045 /* fill in the lba */
4046 scsa2usb_fill_up_cdb_lba(cmd, cmd->cmd_lba);
4048 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4049 "scsa2usb_setup_next_xfer:\n\tlba = 0x%x xfer_len = 0x%x "
4050 "xfercount = 0x%lx total = 0x%lx", cmd->cmd_lba, xfer_len,
4051 cmd->cmd_xfercount, cmd->cmd_total_xfercount);
4056 * take one request from the lun's waitQ and transport it
4058 static void
4059 scsa2usb_transport_request(scsa2usb_state_t *scsa2usbp, uint_t lun)
4061 int rval;
4062 struct scsi_pkt *pkt;
4063 struct scsa2usb_cmd *cmd, *arqcmd;
4065 if ((cmd = (scsa2usb_cmd_t *)
4066 usba_rm_first_pvt_from_list(
4067 &scsa2usbp->scsa2usb_waitQ[lun])) == NULL) {
4069 return;
4071 pkt = cmd->cmd_pkt;
4074 * if device has been disconnected, just complete it
4076 if (scsa2usbp->scsa2usb_dev_state == USB_DEV_DISCONNECTED) {
4077 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4078 "device not accessible");
4079 pkt->pkt_reason = CMD_DEV_GONE;
4080 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp);
4081 scsa2usb_pkt_completion(scsa2usbp, pkt);
4083 return;
4086 USB_DPRINTF_L4(DPRINT_MASK_SCSA,
4087 scsa2usbp->scsa2usb_log_handle,
4088 "scsa2usb_transport_request: cmd=0x%p bp=0x%p addr=0x%p",
4089 (void *)cmd, (void *)cmd->cmd_bp,
4090 (void *)(cmd->cmd_bp ? cmd->cmd_bp->b_un.b_addr : NULL));
4092 rval = scsa2usb_cmd_transport(scsa2usbp, cmd);
4094 USB_DPRINTF_L3(DPRINT_MASK_SCSA,
4095 scsa2usbp->scsa2usb_log_handle,
4096 "scsa2usb_transport_request: transport rval = %d",
4097 rval);
4099 if (scsa2usbp->scsa2usb_cur_pkt == NULL) {
4101 return;
4104 ASSERT(pkt == scsa2usbp->scsa2usb_cur_pkt);
4106 if (ddi_in_panic()) {
4107 pkt->pkt_reason = CMD_CMPLT;
4108 scsa2usb_pkt_completion(scsa2usbp, pkt);
4110 return;
4114 * start an auto-request sense iff
4115 * there was a check condition, we have enough
4116 * space in the status block, and we have not
4117 * faked an auto request sense
4119 if ((*(pkt->pkt_scbp) == STATUS_CHECK) &&
4120 (cmd->cmd_scblen >= sizeof (struct scsi_arq_status)) &&
4121 ((pkt->pkt_state & STATE_ARQ_DONE) == 0) &&
4122 (scsa2usb_create_arq_pkt(scsa2usbp,
4123 &pkt->pkt_address) == USB_SUCCESS)) {
4124 arqcmd = scsa2usbp->scsa2usb_arq_cmd;
4127 * copy the timeout from the
4128 * original packet
4129 * for lack of a better value
4131 arqcmd->cmd_pkt->pkt_time = pkt->pkt_time;
4132 scsa2usb_prepare_pkt(scsa2usbp,
4133 arqcmd->cmd_pkt);
4135 scsa2usbp->scsa2usb_cur_pkt = NULL;
4136 if (scsa2usb_cmd_transport(
4137 scsa2usbp, arqcmd) == TRAN_ACCEPT) {
4139 /* finish w/ this packet */
4140 scsa2usb_complete_arq_pkt(
4141 scsa2usbp, arqcmd->cmd_pkt, cmd,
4142 scsa2usbp->scsa2usb_arq_bp);
4145 * we have valid request sense
4146 * data so clear the pkt_reason
4148 pkt->pkt_reason = CMD_CMPLT;
4150 scsa2usbp->scsa2usb_cur_pkt = pkt;
4151 scsa2usb_delete_arq_pkt(scsa2usbp);
4154 if ((rval != TRAN_ACCEPT) &&
4155 (pkt->pkt_reason == CMD_CMPLT)) {
4156 pkt->pkt_reason = CMD_TRAN_ERR;
4159 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp);
4160 scsa2usb_pkt_completion(scsa2usbp, pkt);
4162 ASSERT(scsa2usbp->scsa2usb_cur_pkt == NULL);
4167 * scsa2usb_work_thread:
4168 * The taskq thread that kicks off the transport (BO and CB/CBI)
4170 static void
4171 scsa2usb_work_thread(void *arg)
4173 scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)arg;
4174 uint_t lun;
4175 uint_t count;
4177 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4178 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4179 "scsa2usb_work_thread start: thread_id=0x%p",
4180 (void *)scsa2usbp->scsa2usb_work_thread_id);
4182 ASSERT(scsa2usbp->scsa2usb_work_thread_id == (kthread_t *)1);
4183 scsa2usbp->scsa2usb_work_thread_id = curthread;
4185 /* exclude ugen accesses */
4186 while (scsa2usbp->scsa2usb_transport_busy) {
4187 cv_wait(&scsa2usbp->scsa2usb_transport_busy_cv,
4188 &scsa2usbp->scsa2usb_mutex);
4190 ASSERT(scsa2usbp->scsa2usb_ugen_open_count == 0);
4191 scsa2usbp->scsa2usb_transport_busy++;
4192 scsa2usbp->scsa2usb_busy_proc = curproc;
4194 scsa2usb_raise_power(scsa2usbp);
4196 /* reopen the pipes if necessary */
4197 (void) scsa2usb_open_usb_pipes(scsa2usbp);
4199 for (;;) {
4200 ASSERT(scsa2usbp->scsa2usb_ugen_open_count == 0);
4201 for (lun = 0; lun < scsa2usbp->scsa2usb_n_luns; lun++) {
4202 scsa2usb_transport_request(scsa2usbp, lun);
4204 count = 0;
4205 for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) {
4206 count += usba_list_entry_count(
4207 &scsa2usbp->scsa2usb_waitQ[lun]);
4210 if (count == 0) {
4212 break;
4216 scsa2usbp->scsa2usb_work_thread_id = 0;
4218 ASSERT(scsa2usbp->scsa2usb_ugen_open_count == 0);
4220 scsa2usbp->scsa2usb_transport_busy--;
4221 scsa2usbp->scsa2usb_busy_proc = NULL;
4222 cv_signal(&scsa2usbp->scsa2usb_transport_busy_cv);
4224 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4225 "scsa2usb_work_thread: exit");
4227 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4229 scsa2usb_pm_idle_component(scsa2usbp);
4234 * scsa2usb_flush_waitQ:
4235 * empties the entire waitQ with errors asap.
4237 * It is called from scsa2usb_scsi_reset and scsa2usb_panic_callb.
4238 * If the device is reset; we should empty the waitQ right away.
4239 * If the system has paniced; we should empty the waitQ right away.
4241 * CPR suspend will only succeed if device is idle. No need to call
4242 * this function for CPR suspend case.
4244 static void
4245 scsa2usb_flush_waitQ(scsa2usb_state_t *scsa2usbp, uint_t lun,
4246 uchar_t error)
4248 struct scsi_pkt *pkt;
4249 struct scsa2usb_cmd *cmd;
4250 usba_list_entry_t head;
4252 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4254 usba_move_list(&scsa2usbp->scsa2usb_waitQ[lun], &head,
4255 scsa2usbp->scsa2usb_dev_data->dev_iblock_cookie);
4256 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4258 while ((cmd = (scsa2usb_cmd_t *)usba_rm_first_pvt_from_list(&head)) !=
4259 NULL) {
4260 pkt = cmd->cmd_pkt;
4261 pkt->pkt_reason = error; /* set error */
4263 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4264 scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_DO_COMP;
4265 scsa2usb_pkt_completion(scsa2usbp, pkt);
4266 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4267 } /* end of while */
4272 * scsa2usb_do_inquiry is performed before INIT CHILD and we have
4273 * to fake a few things normally done by SCSA
4275 static void
4276 scsa2usb_do_inquiry(scsa2usb_state_t *scsa2usbp, uint_t target, uint_t lun)
4278 struct buf *bp;
4279 struct scsi_pkt *pkt;
4280 struct scsi_address ap;
4281 int len = SCSA2USB_MAX_INQ_LEN;
4283 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4284 "scsa2usb_do_inquiry: %d bytes", len);
4286 /* is it inquiry-challenged? */
4287 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_INQUIRY)) {
4288 scsa2usb_fake_inquiry(scsa2usbp,
4289 &scsa2usbp->scsa2usb_lun_inquiry[lun]);
4290 return;
4293 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
4295 bzero(&ap, sizeof (struct scsi_address));
4296 ap.a_hba_tran = scsa2usbp->scsa2usb_tran;
4297 ap.a_target = (ushort_t)target;
4298 ap.a_lun = (uchar_t)lun;
4300 /* limit inquiry to 36 bytes */
4301 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4302 if ((bp = scsi_alloc_consistent_buf(&ap, NULL,
4303 len, B_READ, SLEEP_FUNC, NULL)) == NULL) {
4304 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4305 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
4306 scsa2usbp->scsa2usb_log_handle,
4307 "scsa2usb_do_inquiry: failed");
4309 return;
4312 pkt = scsi_init_pkt(&ap, NULL, bp, CDB_GROUP0, 1,
4313 PKT_PRIV_LEN, PKT_CONSISTENT, SLEEP_FUNC, NULL);
4315 RQ_MAKECOM_G0(pkt, FLAG_NOINTR, (char)SCMD_INQUIRY, 0, (char)len);
4317 pkt->pkt_comp = NULL;
4318 pkt->pkt_time = 5;
4319 bzero(bp->b_un.b_addr, len);
4321 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4322 "scsa2usb_do_inquiry:INQUIRY");
4324 (void) scsi_transport(pkt);
4326 if (pkt->pkt_reason) {
4327 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
4328 scsa2usbp->scsa2usb_log_handle,
4329 "INQUIRY failed, cannot determine device type, "
4330 "pkt_reason=0x%x", pkt->pkt_reason);
4332 /* not much hope for other cmds, reduce */
4333 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4334 scsa2usbp->scsa2usb_attrs &=
4335 ~SCSA2USB_ATTRS_REDUCED_CMD;
4336 scsa2usb_fake_inquiry(scsa2usbp,
4337 &scsa2usbp->scsa2usb_lun_inquiry[lun]);
4338 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4341 scsi_destroy_pkt(pkt);
4342 scsi_free_consistent_buf(bp);
4344 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4349 * scsa2usb_fake_inquiry:
4350 * build an inquiry for a given device that doesnt like inquiry
4351 * commands.
4353 static void
4354 scsa2usb_fake_inquiry(scsa2usb_state_t *scsa2usbp, struct scsi_inquiry *inqp)
4356 usb_client_dev_data_t *dev_data = scsa2usbp->scsa2usb_dev_data;
4357 int len;
4359 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4360 "scsa2usb_fake_inquiry:");
4362 bzero(inqp, sizeof (struct scsi_inquiry));
4363 for (len = 0; len < sizeof (inqp->inq_vid); len++) {
4364 *(inqp->inq_vid + len) = ' ';
4367 for (len = 0; len < sizeof (inqp->inq_pid); len++) {
4368 *(inqp->inq_pid + len) = ' ';
4371 inqp->inq_dtype = DTYPE_DIRECT;
4372 inqp->inq_rmb = 1;
4373 inqp->inq_ansi = 2;
4374 inqp->inq_rdf = RDF_SCSI2;
4375 inqp->inq_len = sizeof (struct scsi_inquiry)-4;
4377 /* Fill in the Vendor id/Product id strings */
4378 if (dev_data->dev_mfg) {
4379 if ((len = strlen(dev_data->dev_mfg)) >
4380 sizeof (inqp->inq_vid)) {
4381 len = sizeof (inqp->inq_vid);
4383 bcopy(dev_data->dev_mfg, inqp->inq_vid, len);
4386 if (dev_data->dev_product) {
4387 if ((len = strlen(dev_data->dev_product)) >
4388 sizeof (inqp->inq_pid)) {
4389 len = sizeof (inqp->inq_pid);
4391 bcopy(dev_data->dev_product, inqp->inq_pid, len);
4394 /* Set the Revision to the Device */
4395 inqp->inq_revision[0] = 0x30 +
4396 ((dev_data->dev_descr->bcdDevice>>12) & 0xF);
4397 inqp->inq_revision[1] = 0x30 +
4398 ((dev_data->dev_descr->bcdDevice>>8) & 0xF);
4399 inqp->inq_revision[2] = 0x30 +
4400 ((dev_data->dev_descr->bcdDevice>>4) & 0xF);
4401 inqp->inq_revision[3] = 0x30 +
4402 ((dev_data->dev_descr->bcdDevice) & 0xF);
4407 * scsa2usb_create_arq_pkt:
4408 * Create and ARQ packet to get request sense data
4410 static int
4411 scsa2usb_create_arq_pkt(scsa2usb_state_t *scsa2usbp, struct scsi_address *ap)
4413 struct buf *bp;
4414 scsa2usb_cmd_t *arq_cmd;
4416 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4417 "scsa2usb_create_arq_pkt: scsa2usbp: %p, ap: %p",
4418 (void *)scsa2usbp, (void *)ap);
4420 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
4422 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4423 if ((bp = scsi_alloc_consistent_buf(ap, NULL,
4424 SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL)) == NULL) {
4425 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4427 return (USB_FAILURE);
4430 arq_cmd = PKT2CMD(scsi_init_pkt(ap, NULL, bp, CDB_GROUP0, 1,
4431 PKT_PRIV_LEN, PKT_CONSISTENT, SLEEP_FUNC, NULL));
4432 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4434 RQ_MAKECOM_G0(arq_cmd->cmd_pkt,
4435 FLAG_SENSING | FLAG_HEAD | FLAG_NODISCON,
4436 (char)SCMD_REQUEST_SENSE, 0, (char)SENSE_LENGTH);
4438 arq_cmd->cmd_pkt->pkt_ha_private = arq_cmd;
4439 scsa2usbp->scsa2usb_arq_cmd = arq_cmd;
4440 scsa2usbp->scsa2usb_arq_bp = bp;
4441 arq_cmd->cmd_pkt->pkt_comp = NULL;
4442 bzero(bp->b_un.b_addr, SENSE_LENGTH);
4444 return (USB_SUCCESS);
4449 * scsa2usb_delete_arq_pkt:
4450 * Destroy the ARQ packet
4452 static void
4453 scsa2usb_delete_arq_pkt(scsa2usb_state_t *scsa2usbp)
4455 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4456 "scsa2usb_delete_arq_pkt: cmd: 0x%p",
4457 (void *)scsa2usbp->scsa2usb_arq_cmd);
4459 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
4461 if (scsa2usbp->scsa2usb_arq_cmd != NULL) {
4462 scsi_destroy_pkt(scsa2usbp->scsa2usb_arq_cmd->cmd_pkt);
4463 scsi_free_consistent_buf(scsa2usbp->scsa2usb_arq_bp);
4465 scsa2usbp->scsa2usb_arq_cmd = NULL;
4466 scsa2usbp->scsa2usb_arq_bp = NULL;
4471 * scsa2usb_complete_arq_pkt:
4472 * finish processing the arq packet
4474 static void
4475 scsa2usb_complete_arq_pkt(scsa2usb_state_t *scsa2usbp,
4476 struct scsi_pkt *pkt, scsa2usb_cmd_t *ssp, struct buf *bp)
4478 scsa2usb_cmd_t *sp = pkt->pkt_ha_private;
4479 struct scsi_arq_status *arqp;
4481 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
4483 arqp = (struct scsi_arq_status *)(ssp->cmd_pkt->pkt_scbp);
4484 arqp->sts_rqpkt_status = *((struct scsi_status *)
4485 (sp->cmd_pkt->pkt_scbp));
4486 arqp->sts_rqpkt_reason = CMD_CMPLT;
4487 arqp->sts_rqpkt_state |= STATE_XFERRED_DATA;
4488 arqp->sts_rqpkt_statistics = arqp->sts_rqpkt_resid = 0;
4490 /* is this meaningful sense data */
4491 if (*(bp->b_un.b_addr) != 0) {
4492 bcopy(bp->b_un.b_addr, &arqp->sts_sensedata, SENSE_LENGTH);
4493 ssp->cmd_pkt->pkt_state |= STATE_ARQ_DONE;
4496 /* we will not sense start cmd until we receive a NOT READY */
4497 if (arqp->sts_sensedata.es_key == KEY_NOT_READY) {
4498 scsa2usbp->scsa2usb_rcvd_not_ready = B_TRUE;
4504 * Miscellaneous functions for any command/transport
4507 * scsa2usb_open_usb_pipes:
4508 * set up a pipe policy
4509 * open usb bulk pipes (BO and CB/CBI)
4510 * open usb interrupt pipe (CBI)
4512 static int
4513 scsa2usb_open_usb_pipes(scsa2usb_state_t *scsa2usbp)
4515 int rval;
4516 usb_pipe_policy_t policy; /* bulk pipe policy */
4517 size_t sz;
4519 ASSERT(scsa2usbp);
4520 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
4522 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4523 "scsa2usb_open_usb_pipes: dip = 0x%p flag = 0x%x",
4524 (void *)scsa2usbp->scsa2usb_dip, scsa2usbp->scsa2usb_flags);
4526 if (!(scsa2usbp->scsa2usb_flags & SCSA2USB_FLAGS_PIPES_OPENED)) {
4529 * one pipe policy for all bulk pipes
4531 bzero(&policy, sizeof (usb_pipe_policy_t));
4532 /* at least 2, for the normal and exceptional callbacks */
4533 policy.pp_max_async_reqs = 1;
4535 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4536 "scsa2usb_open_usb_pipes: opening bulk pipes");
4538 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4540 /* Open the USB bulk-in pipe */
4541 if ((rval = usb_pipe_xopen(scsa2usbp->scsa2usb_dip,
4542 &scsa2usbp->scsa2usb_bulkin_xept, &policy, USB_FLAGS_SLEEP,
4543 &scsa2usbp->scsa2usb_bulkin_pipe)) != USB_SUCCESS) {
4544 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4545 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
4546 scsa2usbp->scsa2usb_log_handle,
4547 "scsa2usb_open_usb_pipes: bulk/in pipe open "
4548 " failed rval = %d", rval);
4550 return (USB_FAILURE);
4553 /* Open the bulk-out pipe using the same policy */
4554 if ((rval = usb_pipe_xopen(scsa2usbp->scsa2usb_dip,
4555 &scsa2usbp->scsa2usb_bulkout_xept, &policy, USB_FLAGS_SLEEP,
4556 &scsa2usbp->scsa2usb_bulkout_pipe)) != USB_SUCCESS) {
4557 usb_pipe_close(scsa2usbp->scsa2usb_dip,
4558 scsa2usbp->scsa2usb_bulkin_pipe,
4559 USB_FLAGS_SLEEP, NULL, NULL);
4561 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4562 scsa2usbp->scsa2usb_bulkin_pipe = NULL;
4564 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
4565 scsa2usbp->scsa2usb_log_handle,
4566 "scsa2usb_open_usb_pipes: bulk/out pipe open"
4567 " failed rval = %d", rval);
4569 return (USB_FAILURE);
4572 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4574 /* open interrupt pipe for CBI protocol */
4575 if (SCSA2USB_IS_CBI(scsa2usbp)) {
4576 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4578 if ((rval = usb_pipe_xopen(scsa2usbp->scsa2usb_dip,
4579 &scsa2usbp->scsa2usb_intr_xept, &policy,
4580 USB_FLAGS_SLEEP, &scsa2usbp->scsa2usb_intr_pipe)) !=
4581 USB_SUCCESS) {
4582 usb_pipe_close(scsa2usbp->scsa2usb_dip,
4583 scsa2usbp->scsa2usb_bulkin_pipe,
4584 USB_FLAGS_SLEEP, NULL, NULL);
4586 usb_pipe_close(scsa2usbp->scsa2usb_dip,
4587 scsa2usbp->scsa2usb_bulkout_pipe,
4588 USB_FLAGS_SLEEP, NULL, NULL);
4590 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4591 scsa2usbp->scsa2usb_bulkin_pipe = NULL;
4592 scsa2usbp->scsa2usb_bulkout_pipe = NULL;
4594 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
4595 scsa2usbp->scsa2usb_log_handle,
4596 "scsa2usb_open_usb_pipes: intr pipe open"
4597 " failed rval = %d", rval);
4599 return (USB_FAILURE);
4602 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4605 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4607 /* get the max transfer size of the bulk pipe */
4608 if (usb_pipe_get_max_bulk_transfer_size(scsa2usbp->scsa2usb_dip,
4609 &sz) == USB_SUCCESS) {
4610 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4611 scsa2usbp->scsa2usb_max_bulk_xfer_size = sz;
4612 } else {
4613 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4614 scsa2usbp->scsa2usb_max_bulk_xfer_size = DEV_BSIZE;
4617 /* limit the xfer size */
4618 scsa2usbp->scsa2usb_max_bulk_xfer_size = min(
4619 scsa2usbp->scsa2usb_max_bulk_xfer_size,
4620 scsa2usb_max_bulk_xfer_size);
4622 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4623 "scsa2usb_open_usb_pipes: max bulk transfer size = %lx",
4624 scsa2usbp->scsa2usb_max_bulk_xfer_size);
4626 /* Set the pipes opened flag */
4627 scsa2usbp->scsa2usb_flags |= SCSA2USB_FLAGS_PIPES_OPENED;
4629 scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_NORMAL;
4631 /* Set the state to NONE */
4632 scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_NONE;
4635 return (USB_SUCCESS);
4640 * scsa2usb_close_usb_pipes:
4641 * close all pipes synchronously
4643 void
4644 scsa2usb_close_usb_pipes(scsa2usb_state_t *scsa2usbp)
4646 usb_flags_t flags = USB_FLAGS_SLEEP;
4648 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4649 "scsa2usb_close_usb_pipes: scsa2usb_state = 0x%p",
4650 (void *)scsa2usbp);
4652 ASSERT(scsa2usbp);
4653 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
4655 if ((scsa2usbp->scsa2usb_flags & SCSA2USB_FLAGS_PIPES_OPENED) == 0) {
4657 return;
4660 scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_CLOSING;
4661 /* to avoid races, reset the flag first */
4662 scsa2usbp->scsa2usb_flags &= ~SCSA2USB_FLAGS_PIPES_OPENED;
4664 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4666 usb_pipe_close(scsa2usbp->scsa2usb_dip,
4667 scsa2usbp->scsa2usb_bulkout_pipe, flags, NULL, NULL);
4669 usb_pipe_close(scsa2usbp->scsa2usb_dip,
4670 scsa2usbp->scsa2usb_bulkin_pipe, flags, NULL, NULL);
4672 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4673 if (SCSA2USB_IS_CBI(scsa2usbp)) {
4674 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4675 usb_pipe_close(scsa2usbp->scsa2usb_dip,
4676 scsa2usbp->scsa2usb_intr_pipe, flags, NULL, NULL);
4677 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4679 scsa2usbp->scsa2usb_bulkout_pipe = NULL;
4680 scsa2usbp->scsa2usb_bulkin_pipe = NULL;
4681 scsa2usbp->scsa2usb_intr_pipe = NULL;
4683 scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_NORMAL;
4688 * scsa2usb_fill_up_cdb_lba:
4689 * fill up command CDBs' LBA part
4691 static void
4692 scsa2usb_fill_up_cdb_lba(scsa2usb_cmd_t *cmd, int lba)
4694 /* zero cdb1, lba bits so they won't get copied in the new cdb */
4695 cmd->cmd_cdb[SCSA2USB_LUN] &= 0xE0;
4696 cmd->cmd_cdb[SCSA2USB_LBA_0] = lba >> 24;
4697 cmd->cmd_cdb[SCSA2USB_LBA_1] = lba >> 16;
4698 cmd->cmd_cdb[SCSA2USB_LBA_2] = lba >> 8;
4699 cmd->cmd_cdb[SCSA2USB_LBA_3] = (uchar_t)lba;
4700 cmd->cmd_lba = lba;
4705 * scsa2usb_fill_up_ReadCD_cdb_len:
4706 * fill up READ_CD command CDBs' len part
4708 static void
4709 scsa2usb_fill_up_ReadCD_cdb_len(scsa2usb_cmd_t *cmd, int len, int actual_len)
4711 cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_0] = len >> 16;
4712 cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_1] = len >> 8;
4713 cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_2] = (uchar_t)len;
4714 cmd->cmd_actual_len = (uchar_t)actual_len;
4719 * scsa2usb_fill_up_12byte_cdb_len:
4720 * fill up generic 12-byte command CDBs' len part
4722 static void
4723 scsa2usb_fill_up_12byte_cdb_len(scsa2usb_cmd_t *cmd, int len, int actual_len)
4725 cmd->cmd_cdb[6] = len >> 24;
4726 cmd->cmd_cdb[7] = len >> 16;
4727 cmd->cmd_cdb[8] = len >> 8;
4728 cmd->cmd_cdb[9] = (uchar_t)len;
4729 cmd->cmd_actual_len = (uchar_t)actual_len;
4734 * scsa2usb_fill_up_cdb_len:
4735 * fill up generic 10-byte command CDBs' len part
4737 static void
4738 scsa2usb_fill_up_cdb_len(scsa2usb_cmd_t *cmd, int len)
4740 cmd->cmd_cdb[SCSA2USB_LEN_0] = len >> 8;
4741 cmd->cmd_cdb[SCSA2USB_LEN_1] = (uchar_t)len;
4746 * scsa2usb_read_cd_blk_size:
4747 * For SCMD_READ_CD opcode (0xbe). Figure out the
4748 * block size based on expected sector type field
4749 * definition. See MMC SCSI Specs section 6.1.15
4751 * Based on the value of the "expected_sector_type"
4752 * field, the block size could be different.
4754 static int
4755 scsa2usb_read_cd_blk_size(uchar_t expected_sector_type)
4757 int blk_size;
4759 switch (expected_sector_type) {
4760 case READ_CD_EST_CDDA:
4761 blk_size = CDROM_BLK_2352;
4762 break;
4763 case READ_CD_EST_MODE2:
4764 blk_size = CDROM_BLK_2336;
4765 break;
4766 case READ_CD_EST_MODE2FORM2:
4767 blk_size = CDROM_BLK_2324;
4768 break;
4769 case READ_CD_EST_MODE2FORM1:
4770 case READ_CD_EST_ALLTYPE:
4771 case READ_CD_EST_MODE1:
4772 default:
4773 blk_size = CDROM_BLK_2048;
4776 USB_DPRINTF_L4(DPRINT_MASK_SCSA, NULL, "scsa2usb_read_cd_blk_size: "
4777 "est = 0x%x blk_size = %d", expected_sector_type, blk_size);
4779 return (blk_size);
4784 * scsa2usb_bp_to_mblk:
4785 * Convert a bp to mblk_t. USBA framework understands mblk_t.
4787 static mblk_t *
4788 scsa2usb_bp_to_mblk(scsa2usb_state_t *scsa2usbp)
4790 size_t size;
4791 mblk_t *mp;
4792 struct buf *bp;
4793 scsa2usb_cmd_t *cmd = PKT2CMD(scsa2usbp->scsa2usb_cur_pkt);
4795 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4796 "scsa2usb_bp_to_mblk: ");
4798 ASSERT(scsa2usbp->scsa2usb_cur_pkt);
4799 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
4801 bp = cmd->cmd_bp;
4803 if (bp && (bp->b_bcount > 0)) {
4804 size = ((bp->b_bcount > cmd->cmd_xfercount) ?
4805 cmd->cmd_xfercount : bp->b_bcount);
4806 } else {
4808 return (NULL);
4811 mp = esballoc_wait((uchar_t *)bp->b_un.b_addr + cmd->cmd_offset,
4812 size, BPRI_LO, &frnop);
4814 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4815 "scsa2usb_bp_to_mblk: "
4816 "mp=0x%p bp=0x%p pkt=0x%p off=0x%lx sz=%lu add=0x%p",
4817 (void *)mp, (void *)bp, (void *)scsa2usbp->scsa2usb_cur_pkt,
4818 cmd->cmd_offset, bp->b_bcount - cmd->cmd_offset,
4819 (void *)bp->b_un.b_addr);
4821 mp->b_wptr += size;
4822 cmd->cmd_offset += size;
4824 return (mp);
4829 * scsa2usb_handle_data_start:
4830 * Initiate the data xfer. It could be IN/OUT direction.
4832 * Data IN:
4833 * Send out the bulk-xfer request
4834 * if rval implies STALL
4835 * clear endpoint stall and reset bulk-in pipe
4836 * handle data read in so far; set cmd->cmd_done
4837 * also adjust data xfer length accordingly
4838 * else other error
4839 * report back to transport
4840 * typically transport will call reset recovery
4841 * else (no error)
4842 * return success
4844 * Data OUT:
4845 * Send out the bulk-xfer request
4846 * if rval implies STALL
4847 * clear endpoint stall and reset bulk-in pipe
4848 * adjust data xfer length
4849 * else other error
4850 * report back to transport
4851 * typically transport will call reset recovery
4852 * else (no error)
4853 * return success
4855 * NOTE: We call this function only if there is xfercount.
4858 scsa2usb_handle_data_start(scsa2usb_state_t *scsa2usbp,
4859 scsa2usb_cmd_t *cmd, usb_bulk_req_t *req)
4861 int rval = USB_SUCCESS;
4862 uint_t ept_addr;
4863 usb_flags_t flags = USB_FLAGS_SLEEP;
4864 #ifdef SCSA2USB_BULK_ONLY_TEST
4865 usb_req_attrs_t attrs = 0;
4866 #else
4867 usb_req_attrs_t attrs = USB_ATTRS_SHORT_XFER_OK;
4868 #endif
4870 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
4871 "scsa2usb_handle_data_start: BEGIN cmd = %p, req = %p",
4872 (void *)cmd, (void *)req);
4874 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
4876 switch (cmd->cmd_dir) {
4877 case USB_EP_DIR_IN:
4878 #ifdef SCSA2USB_BULK_ONLY_TEST
4880 * This case occurs when the host expects to receive
4881 * more data than the device actually transfers. Hi > Di
4883 if (scsa2usb_test_case_5) {
4884 usb_bulk_req_t *req2;
4886 req->bulk_len = cmd->cmd_xfercount - 1;
4887 req->bulk_attributes = 0;
4888 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4889 SCSA2USB_FREE_MSG(req->bulk_data);
4890 req->bulk_data = allocb_wait(req->bulk_len, BPRI_LO,
4891 STR_NOSIG, NULL);
4893 ASSERT(req->bulk_timeout);
4894 rval = usb_pipe_bulk_xfer(
4895 scsa2usbp->scsa2usb_bulkin_pipe, req, flags);
4896 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4897 USB_DPRINTF_L1(DPRINT_MASK_SCSA,
4898 scsa2usbp->scsa2usb_log_handle, "rval = %x", rval);
4900 req2 = scsa2usb_init_bulk_req(scsa2usbp,
4901 cmd->cmd_xfercount + 2,
4902 cmd->cmd_timeout, 0, flags);
4903 req2->bulk_len = cmd->cmd_xfercount + 2;
4904 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4906 ASSERT(req2->bulk_timeout);
4907 rval = usb_pipe_bulk_xfer(
4908 scsa2usbp->scsa2usb_bulkin_pipe, req2, flags);
4909 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4911 USB_DPRINTF_L1(DPRINT_MASK_SCSA,
4912 scsa2usbp->scsa2usb_log_handle,
4913 "TEST 5: Hi > Di: rval = 0x%x", rval);
4914 scsa2usb_test_case_5 = 0;
4915 usb_free_bulk_req(req2);
4917 return (rval);
4921 * This happens when the host expects to send data to the
4922 * device while the device intends to send data to the host.
4924 if (scsa2usb_test_case_8 && (cmd->cmd_cdb[0] == SCMD_READ_G1)) {
4925 USB_DPRINTF_L1(DPRINT_MASK_SCSA,
4926 scsa2usbp->scsa2usb_log_handle,
4927 "TEST 8: Hi <> Do: Step 2");
4928 scsa2usb_test_mblk(scsa2usbp, B_TRUE);
4929 scsa2usb_test_case_8 = 0;
4931 return (rval);
4933 #endif /* SCSA2USB_BULK_ONLY_TEST */
4935 ept_addr = scsa2usbp->scsa2usb_bulkin_ept.bEndpointAddress;
4936 req->bulk_len = cmd->cmd_xfercount;
4937 req->bulk_attributes = attrs;
4938 SCSA2USB_FREE_MSG(req->bulk_data);
4939 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4941 req->bulk_data = esballoc_wait(
4942 (uchar_t *)cmd->cmd_bp->b_un.b_addr +
4943 cmd->cmd_offset,
4944 req->bulk_len, BPRI_LO, &frnop);
4946 ASSERT(req->bulk_timeout);
4947 rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkin_pipe,
4948 req, flags);
4949 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4951 break;
4953 case USB_EP_DIR_OUT:
4954 #ifdef SCSA2USB_BULK_ONLY_TEST
4956 * This happens when the host expects to receive data
4957 * from the device while the device intends to receive
4958 * data from the host.
4960 if (scsa2usb_test_case_10 &&
4961 (cmd->cmd_cdb[0] == SCMD_WRITE_G1)) {
4962 req->bulk_len = CSW_LEN;
4963 mutex_exit(&scsa2usbp->scsa2usb_mutex);
4965 ASSERT(req->bulk_timeout);
4966 rval = usb_pipe_bulk_xfer(
4967 scsa2usbp->scsa2usb_bulkin_pipe, req, flags);
4968 mutex_enter(&scsa2usbp->scsa2usb_mutex);
4970 USB_DPRINTF_L1(DPRINT_MASK_SCSA,
4971 scsa2usbp->scsa2usb_log_handle,
4972 "TEST 10: Ho <> Di: done rval = 0x%x", rval);
4973 scsa2usb_test_case_10 = 0;
4975 return (rval);
4977 #endif /* SCSA2USB_BULK_ONLY_TEST */
4979 req->bulk_data = scsa2usb_bp_to_mblk(scsa2usbp);
4980 if (req->bulk_data == NULL) {
4982 return (USB_FAILURE);
4985 #ifdef SCSA2USB_BULK_ONLY_TEST
4986 if (scsa2usb_test_case_11) {
4988 * Host expects to send data to the device and
4989 * device doesn't expect to receive any data
4991 USB_DPRINTF_L1(DPRINT_MASK_SCSA,
4992 scsa2usbp->scsa2usb_log_handle, "TEST 11: Ho > Do");
4994 scsa2usb_test_mblk(scsa2usbp, B_FALSE);
4995 scsa2usb_test_case_11 = 0;
4997 #endif /* SCSA2USB_BULK_ONLY_TEST */
4999 ept_addr = scsa2usbp->scsa2usb_bulkout_ept.bEndpointAddress;
5000 req->bulk_len = MBLKL(req->bulk_data);
5001 req->bulk_timeout = scsa2usb_bulk_timeout(cmd->cmd_timeout);
5002 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5004 ASSERT(req->bulk_timeout);
5005 rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkout_pipe,
5006 req, flags);
5007 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5008 break;
5011 USB_DPRINTF_L3(DPRINT_MASK_SCSA,
5012 scsa2usbp->scsa2usb_log_handle,
5013 "scsa2usb_handle_data_start: rval=%d cr=%d", rval,
5014 req->bulk_completion_reason);
5016 if (rval != USB_SUCCESS) {
5017 /* Handle Errors now */
5018 if (req->bulk_completion_reason == USB_CR_STALL) {
5019 if (cmd->cmd_dir == USB_EP_DIR_IN) {
5020 (void) scsa2usb_clear_ept_stall(
5021 scsa2usbp, ept_addr,
5022 scsa2usbp-> scsa2usb_bulkin_pipe,
5023 "bulk-in");
5024 } else {
5025 (void) scsa2usb_clear_ept_stall(
5026 scsa2usbp, ept_addr,
5027 scsa2usbp-> scsa2usb_bulkout_pipe,
5028 "bulk-out");
5032 /* no more data to transfer after this */
5033 cmd->cmd_done = 1;
5036 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
5037 "scsa2usb_handle_data_start: END %s data rval = %d",
5038 (cmd->cmd_dir == USB_EP_DIR_IN) ? "bulk-in" : "bulk-out", rval);
5040 return (rval);
5045 * scsa2usb_handle_data_done:
5046 * This function handles the completion of the data xfer.
5047 * It also massages the inquiry data. This function may
5048 * also be called after a stall.
5050 void
5051 scsa2usb_handle_data_done(scsa2usb_state_t *scsa2usbp,
5052 scsa2usb_cmd_t *cmd, usb_bulk_req_t *req)
5054 struct buf *bp = cmd->cmd_bp;
5055 struct scsi_pkt *pkt = scsa2usbp->scsa2usb_cur_pkt;
5056 mblk_t *data = req->bulk_data;
5057 int len = data ? MBLKL(data) : 0;
5058 uint32_t max_lba;
5060 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
5062 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
5063 "scsa2usb_handle_data_done:\n\tcmd = 0x%p data = 0x%p len = 0x%x",
5064 (void *)cmd, (void *)data, len);
5066 cmd->cmd_resid_xfercount = cmd->cmd_xfercount - len;
5068 if (len) {
5069 uchar_t *p;
5070 uchar_t dtype;
5071 scsa2usb_read_cap_t *cap;
5072 struct scsi_inquiry *inq;
5074 switch (cmd->cmd_cdb[SCSA2USB_OPCODE]) {
5075 case SCMD_INQUIRY:
5077 * cache a copy of the inquiry data for our own use
5078 * but ensure that we have at least up to
5079 * inq_revision, inq_serial is not required.
5080 * ignore inquiry data returned for inquiry commands
5081 * with SCSI-3 EVPD, CmdDt bits set.
5083 if (((cmd->cmd_cdb[SCSA2USB_LUN] & 0x1f) == 0) &&
5084 (len >= SCSA2USB_MAX_INQ_LEN)) {
5085 inq = (struct scsi_inquiry *)data->b_rptr;
5086 dtype = inq->inq_dtype & DTYPE_MASK;
5088 * scsi framework sends zero byte write(10) cmd
5089 * to (Simplified) direct-access devices with
5090 * inquiry version > 2 for reservation changes.
5091 * But some USB devices don't support zero byte
5092 * write(10) even though they have inquiry
5093 * version > 2. Considering scsa2usb driver
5094 * doesn't support reservation and all the
5095 * reservation cmds are being faked, we fake
5096 * the inquiry version to 0 to make scsi
5097 * framework send test unit ready cmd which is
5098 * supported by all the usb devices.
5100 if (((dtype == DTYPE_DIRECT) ||
5101 (dtype == DTYPE_RBC)) &&
5102 (inq->inq_ansi > 2)) {
5103 inq->inq_ansi = 0;
5106 bzero(&scsa2usbp->scsa2usb_lun_inquiry
5107 [pkt->pkt_address.a_lun],
5108 sizeof (struct scsi_inquiry));
5109 bcopy(data->b_rptr,
5110 &scsa2usbp->scsa2usb_lun_inquiry
5111 [pkt->pkt_address.a_lun], len);
5114 USB_DPRINTF_L3(DPRINT_MASK_SCSA,
5115 scsa2usbp->scsa2usb_log_handle,
5116 "scsi inquiry type = 0x%x",
5117 scsa2usbp->scsa2usb_lun_inquiry
5118 [pkt->pkt_address.a_lun].inq_dtype);
5120 cmd->cmd_done = 1;
5121 goto handle_data;
5123 case SCMD_READ_CAPACITY:
5124 cap = (scsa2usb_read_cap_t *)data->b_rptr;
5126 /* Figure out the logical block size */
5127 if ((len >= sizeof (struct scsa2usb_read_cap)) &&
5128 (req->bulk_completion_reason == USB_CR_OK)) {
5129 scsa2usbp->
5130 scsa2usb_lbasize[pkt->pkt_address.a_lun] =
5131 SCSA2USB_MK_32BIT(
5132 cap->scsa2usb_read_cap_blen3,
5133 cap->scsa2usb_read_cap_blen2,
5134 cap->scsa2usb_read_cap_blen1,
5135 cap->scsa2usb_read_cap_blen0);
5137 max_lba = SCSA2USB_MK_32BIT(
5138 cap->scsa2usb_read_cap_lba3,
5139 cap->scsa2usb_read_cap_lba2,
5140 cap->scsa2usb_read_cap_lba1,
5141 cap->scsa2usb_read_cap_lba0);
5144 * Some devices return total logical block
5145 * number instead of highest logical block
5146 * address. Adjust the value by minus 1.
5148 if (max_lba > 0 && (scsa2usbp->scsa2usb_attrs &
5149 SCSA2USB_ATTRS_NO_CAP_ADJUST) == 0) {
5150 max_lba -= 1;
5151 cap->scsa2usb_read_cap_lba0 =
5152 (uchar_t)(max_lba & 0xFF);
5153 cap->scsa2usb_read_cap_lba1 =
5154 (uchar_t)(max_lba >> 8 & 0xFF);
5155 cap->scsa2usb_read_cap_lba2 =
5156 (uchar_t)(max_lba >> 16 & 0xFF);
5157 cap->scsa2usb_read_cap_lba3 =
5158 (uchar_t)(max_lba >> 24 & 0xFF);
5161 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
5162 scsa2usbp->scsa2usb_log_handle,
5163 "bytes in each logical block=0x%lx,"
5164 "number of total logical blocks=0x%x",
5165 scsa2usbp->
5166 scsa2usb_lbasize[pkt->pkt_address.a_lun],
5167 max_lba + 1);
5169 cmd->cmd_done = 1;
5170 goto handle_data;
5172 case SCMD_REQUEST_SENSE:
5173 p = data->b_rptr;
5174 USB_DPRINTF_L2(DPRINT_MASK_SCSA,
5175 scsa2usbp->scsa2usb_log_handle,
5176 "cdb: %x rqsense: "
5177 "%x %x %x %x %x %x %x %x %x %x\n\t"
5178 "%x %x %x %x %x %x %x %x %x %x",
5179 cmd->cmd_cdb[0],
5180 p[0], p[1], p[2], p[3], p[4],
5181 p[5], p[6], p[7], p[8], p[9],
5182 p[10], p[11], p[12], p[13], p[14],
5183 p[15], p[16], p[17], p[18], p[19]);
5185 scsa2usbp->scsa2usb_last_cmd.status = p[2];
5186 cmd->cmd_done = 1;
5187 /* FALLTHROUGH */
5189 default:
5190 handle_data:
5191 if (bp && len && (cmd->cmd_dir == USB_EP_DIR_IN)) {
5193 * we don't have to copy the data, the
5194 * data pointers for the mblk_t for
5195 * the bulk-in xfer points to the
5196 * struct buf * data.
5198 cmd->cmd_offset += len;
5201 USB_DPRINTF_L3(DPRINT_MASK_SCSA,
5202 scsa2usbp->scsa2usb_log_handle,
5203 "len = 0x%x total = 0x%lx offset = 0x%lx",
5204 len, cmd->cmd_total_xfercount, cmd->cmd_offset);
5207 * update total_xfercount now but it may be
5208 * adjusted after receiving the residue
5210 cmd->cmd_total_xfercount -= len;
5212 if ((req->bulk_completion_reason != USB_CR_OK) ||
5213 (cmd->cmd_resid_xfercount != 0) ||
5214 (cmd->cmd_total_xfercount == 0)) {
5215 /* set pkt_resid to total to be sure */
5216 pkt->pkt_resid = cmd->cmd_total_xfercount;
5217 cmd->cmd_done = 1;
5220 break;
5222 } else {
5223 if (cmd->cmd_dir == USB_EP_DIR_OUT) {
5224 if (cmd->cmd_total_xfercount == 0) {
5225 cmd->cmd_done = 1;
5233 * scsa2usb_init_bulk_req:
5234 * Allocate (synchronously) and fill in a bulk-request
5236 usb_bulk_req_t *
5237 scsa2usb_init_bulk_req(scsa2usb_state_t *scsa2usbp, size_t length,
5238 uint_t timeout, usb_req_attrs_t attrs, usb_flags_t flags)
5240 usb_bulk_req_t *req;
5242 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
5244 req = usb_alloc_bulk_req(scsa2usbp->scsa2usb_dip, length,
5245 flags | USB_FLAGS_SLEEP);
5247 req->bulk_len = (uint_t)length; /* xfer length */
5248 req->bulk_timeout = scsa2usb_bulk_timeout(timeout); /* xfer timeout */
5249 req->bulk_attributes = attrs; /* xfer attrs */
5250 req->bulk_client_private = (usb_opaque_t)scsa2usbp; /* statep */
5252 return (req);
5257 * scsa2usb_bulk_timeout:
5258 * ensure that bulk requests do not have infinite timeout values
5261 scsa2usb_bulk_timeout(int timeout)
5263 return ((timeout == 0) ? scsa2usb_long_timeout : timeout);
5268 * scsa2usb_clear_ept_stall:
5269 * clear endpoint stall and reset pipes
5272 scsa2usb_clear_ept_stall(scsa2usb_state_t *scsa2usbp, uint_t ept_addr,
5273 usb_pipe_handle_t ph, char *what)
5275 int rval;
5276 dev_info_t *dip = scsa2usbp->scsa2usb_dip;
5278 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
5279 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) {
5281 return (USB_FAILURE);
5284 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5285 rval = usb_clr_feature(dip, USB_DEV_REQ_RCPT_EP, 0, ept_addr,
5286 USB_FLAGS_SLEEP, NULL, NULL);
5288 usb_pipe_reset(dip, ph, USB_FLAGS_SLEEP, NULL, NULL);
5290 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5291 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
5292 "scsa2usb_clear_ept_stall: on %s: ept = 0x%x rval = %d",
5293 what, ept_addr, rval);
5295 return (rval);
5300 * scsa2usb_pkt_completion:
5301 * Handle pkt completion.
5303 static void
5304 scsa2usb_pkt_completion(scsa2usb_state_t *scsa2usbp, struct scsi_pkt *pkt)
5306 scsa2usb_cmd_t *cmd = PKT2CMD(pkt);
5307 size_t len;
5309 ASSERT(pkt);
5310 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
5312 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
5313 "scsa2usb_pkt_completion:\n\tscsa2usbp = 0x%p "
5314 "reason=%d, status=%d state=0x%x stats=0x%x resid=0x%lx",
5315 (void *)scsa2usbp, pkt->pkt_reason, *(pkt->pkt_scbp),
5316 pkt->pkt_state, pkt->pkt_statistics, pkt->pkt_resid);
5318 if (pkt->pkt_reason == CMD_CMPLT) {
5319 pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET |
5320 STATE_SENT_CMD | STATE_GOT_STATUS;
5321 if (cmd->cmd_xfercount) {
5322 pkt->pkt_state |= STATE_XFERRED_DATA;
5324 } else {
5325 pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET |
5326 STATE_SENT_CMD;
5330 * don't zap the current state when in panic as this will
5331 * make debugging harder
5333 if ((scsa2usbp->scsa2usb_cur_pkt == pkt) && !ddi_in_panic()) {
5334 SCSA2USB_RESET_CUR_PKT(scsa2usbp);
5336 len = sizeof (scsa2usbp->scsa2usb_last_cmd.cdb);
5337 bzero(scsa2usbp->scsa2usb_last_cmd.cdb, len);
5339 len = (len < cmd->cmd_cdblen) ? len : cmd->cmd_cdblen;
5340 USB_DPRINTF_L3(DPRINT_MASK_SCSA,
5341 scsa2usbp->scsa2usb_log_handle,
5342 "scsa2usb_pkt_completion: save last cmd, len=%ld", len);
5344 /* save the last command */
5345 bcopy(pkt->pkt_cdbp, scsa2usbp->scsa2usb_last_cmd.cdb, len);
5347 /* reset the scsa2usb_last_cmd.status value */
5348 if ((pkt->pkt_cdbp[0] != SCMD_REQUEST_SENSE) &&
5349 (pkt->pkt_cdbp[0] != SCMD_INQUIRY)) {
5350 scsa2usbp->scsa2usb_last_cmd.status = 0;
5354 * set pkt state to NONE *before* calling back as the target
5355 * driver will immediately submit the next packet
5357 scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_NONE;
5360 if (pkt->pkt_comp) {
5361 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5362 scsi_hba_pkt_comp(pkt);
5363 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5370 * Even handling functions:
5372 * scsa2usb_reconnect_event_cb:
5373 * event handling
5375 static int
5376 scsa2usb_reconnect_event_cb(dev_info_t *dip)
5378 scsa2usb_state_t *scsa2usbp =
5379 ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip));
5380 dev_info_t *cdip;
5381 int circ;
5382 int rval = USB_SUCCESS;
5384 ASSERT(scsa2usbp != NULL);
5386 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
5387 "scsa2usb_reconnect_event_cb: dip = 0x%p", (void *)dip);
5389 scsa2usb_restore_device_state(dip, scsa2usbp);
5391 USB_DPRINTF_L0(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
5392 "Reinserted device is accessible again.");
5394 ndi_devi_enter(dip, &circ);
5395 for (cdip = ddi_get_child(dip); cdip; ) {
5396 dev_info_t *next = ddi_get_next_sibling(cdip);
5398 mutex_enter(&DEVI(cdip)->devi_lock);
5399 DEVI_SET_DEVICE_REINSERTED(cdip);
5400 mutex_exit(&DEVI(cdip)->devi_lock);
5402 cdip = next;
5404 ndi_devi_exit(dip, circ);
5406 /* stop suppressing warnings */
5407 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5408 scsa2usbp->scsa2usb_warning_given = B_FALSE;
5409 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5411 if (scsa2usbp->scsa2usb_ugen_hdl) {
5412 rval = usb_ugen_reconnect_ev_cb(
5413 scsa2usbp->scsa2usb_ugen_hdl);
5416 return (rval);
5421 * scsa2usb_all_waitQs_empty:
5422 * check if all waitQs empty
5424 static int
5425 scsa2usb_all_waitQs_empty(scsa2usb_state_t *scsa2usbp)
5427 uint_t lun;
5429 for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) {
5430 if (usba_list_entry_count(
5431 &scsa2usbp->scsa2usb_waitQ[lun])) {
5433 return (USB_FAILURE);
5437 return (USB_SUCCESS);
5442 * scsa2usb_disconnect_event_cb:
5443 * callback for disconnect events
5445 static int
5446 scsa2usb_disconnect_event_cb(dev_info_t *dip)
5448 scsa2usb_state_t *scsa2usbp =
5449 ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip));
5450 dev_info_t *cdip;
5451 int circ, i;
5452 int rval = USB_SUCCESS;
5454 ASSERT(scsa2usbp != NULL);
5456 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
5457 "scsa2usb_disconnect_event_cb: dip = 0x%p", (void *)dip);
5459 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5460 scsa2usbp->scsa2usb_dev_state = USB_DEV_DISCONNECTED;
5463 * wait till the work thread is done, carry on regardless
5464 * if not.
5466 for (i = 0; i < SCSA2USB_DRAIN_TIMEOUT; i++) {
5467 if ((scsa2usbp->scsa2usb_work_thread_id == NULL) &&
5468 (scsa2usbp->scsa2usb_cur_pkt == NULL) &&
5469 (scsa2usb_all_waitQs_empty(scsa2usbp) ==
5470 USB_SUCCESS)) {
5472 break;
5474 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5475 ddi_sleep(1);
5476 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5478 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5480 ndi_devi_enter(dip, &circ);
5481 for (cdip = ddi_get_child(dip); cdip; ) {
5482 dev_info_t *next = ddi_get_next_sibling(cdip);
5484 mutex_enter(&DEVI(cdip)->devi_lock);
5485 DEVI_SET_DEVICE_REMOVED(cdip);
5486 mutex_exit(&DEVI(cdip)->devi_lock);
5488 cdip = next;
5490 ndi_devi_exit(dip, circ);
5492 if (scsa2usbp->scsa2usb_ugen_hdl) {
5493 rval = usb_ugen_disconnect_ev_cb(
5494 scsa2usbp->scsa2usb_ugen_hdl);
5497 return (rval);
5502 * PM support
5504 * scsa2usb_create_pm_components:
5505 * create the pm components required for power management
5506 * no mutex is need when calling USBA interfaces
5508 static void
5509 scsa2usb_create_pm_components(dev_info_t *dip, scsa2usb_state_t *scsa2usbp)
5511 scsa2usb_power_t *pm;
5512 uint_t pwr_states;
5514 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
5516 USB_DPRINTF_L4(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle,
5517 "scsa2usb_create_pm_components: dip = 0x%p, scsa2usbp = 0x%p",
5518 (void *)dip, (void *)scsa2usbp);
5521 * determine if this device is on the blacklist
5522 * or if a conf file entry has disabled PM
5524 if ((scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_PM) == 0) {
5525 USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle,
5526 "device cannot be power managed");
5528 return;
5531 /* Allocate the PM state structure */
5532 pm = kmem_zalloc(sizeof (scsa2usb_power_t), KM_SLEEP);
5534 scsa2usbp->scsa2usb_pm = pm;
5535 pm->scsa2usb_current_power = USB_DEV_OS_FULL_PWR;
5536 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5538 if (usb_create_pm_components(dip, &pwr_states) ==
5539 USB_SUCCESS) {
5540 if (usb_handle_remote_wakeup(dip,
5541 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
5542 pm->scsa2usb_wakeup_enabled = 1;
5545 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5546 pm->scsa2usb_pwr_states = (uint8_t)pwr_states;
5547 scsa2usb_raise_power(scsa2usbp);
5548 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5551 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5556 * scsa2usb_raise_power:
5557 * check if the device is using full power or not
5559 static void
5560 scsa2usb_raise_power(scsa2usb_state_t *scsa2usbp)
5562 USB_DPRINTF_L4(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle,
5563 "scsa2usb_raise_power:");
5565 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
5567 if (scsa2usbp->scsa2usb_pm) {
5568 scsa2usb_pm_busy_component(scsa2usbp);
5569 if (scsa2usbp->scsa2usb_pm->scsa2usb_current_power !=
5570 USB_DEV_OS_FULL_PWR) {
5571 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5572 (void) pm_raise_power(scsa2usbp->scsa2usb_dip,
5573 0, USB_DEV_OS_FULL_PWR);
5574 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5581 * functions to handle power transition for OS levels 0 -> 3
5583 static int
5584 scsa2usb_pwrlvl0(scsa2usb_state_t *scsa2usbp)
5586 int rval;
5588 switch (scsa2usbp->scsa2usb_dev_state) {
5589 case USB_DEV_ONLINE:
5590 /* Deny the powerdown request if the device is busy */
5591 if (scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy != 0) {
5593 return (USB_FAILURE);
5597 * stop polling on interrupt pipe
5599 scsa2usb_cbi_stop_intr_polling(scsa2usbp);
5601 /* Issue USB D3 command to the device here */
5602 rval = usb_set_device_pwrlvl3(scsa2usbp->scsa2usb_dip);
5603 ASSERT(rval == USB_SUCCESS);
5605 scsa2usbp->scsa2usb_dev_state = USB_DEV_PWRED_DOWN;
5607 /* FALLTHRU */
5608 case USB_DEV_DISCONNECTED:
5609 case USB_DEV_SUSPENDED:
5610 case USB_DEV_PWRED_DOWN:
5611 default:
5612 scsa2usbp->scsa2usb_pm->scsa2usb_current_power =
5613 USB_DEV_OS_PWR_OFF;
5615 return (USB_SUCCESS);
5620 static int
5621 scsa2usb_pwrlvl1(scsa2usb_state_t *scsa2usbp)
5623 int rval;
5625 /* Issue USB D2 command to the device here */
5626 rval = usb_set_device_pwrlvl2(scsa2usbp->scsa2usb_dip);
5627 ASSERT(rval == USB_SUCCESS);
5629 return (DDI_FAILURE);
5633 static int
5634 scsa2usb_pwrlvl2(scsa2usb_state_t *scsa2usbp)
5636 int rval;
5638 /* Issue USB D1 command to the device here */
5639 rval = usb_set_device_pwrlvl1(scsa2usbp->scsa2usb_dip);
5640 ASSERT(rval == USB_SUCCESS);
5642 return (DDI_FAILURE);
5646 static int
5647 scsa2usb_pwrlvl3(scsa2usb_state_t *scsa2usbp)
5649 int rval;
5652 * PM framework tries to put us in full power
5653 * during system shutdown. If we are disconnected
5654 * return success anyways
5656 if (scsa2usbp->scsa2usb_dev_state != USB_DEV_DISCONNECTED) {
5657 /* Issue USB D0 command to the device here */
5658 rval = usb_set_device_pwrlvl0(scsa2usbp->scsa2usb_dip);
5659 ASSERT(rval == USB_SUCCESS);
5661 scsa2usbp->scsa2usb_dev_state = USB_DEV_ONLINE;
5663 scsa2usbp->scsa2usb_pm->scsa2usb_current_power = USB_DEV_OS_FULL_PWR;
5665 return (DDI_SUCCESS);
5670 * scsa2usb_power:
5671 * power entry point
5673 /* ARGSUSED */
5674 static int
5675 scsa2usb_power(dev_info_t *dip, int comp, int level)
5677 scsa2usb_state_t *scsa2usbp;
5678 scsa2usb_power_t *pm;
5679 int rval = DDI_FAILURE;
5681 scsa2usbp = ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip));
5683 USB_DPRINTF_L3(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle,
5684 "scsa2usb_power: Begin scsa2usbp (%p): level = %d",
5685 (void *)scsa2usbp, level);
5687 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5688 if (SCSA2USB_BUSY(scsa2usbp)) {
5689 USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle,
5690 "scsa2usb_power: busy");
5691 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5693 return (rval);
5696 pm = scsa2usbp->scsa2usb_pm;
5697 if (pm == NULL) {
5698 USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle,
5699 "scsa2usb_power: pm NULL");
5700 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5702 return (rval);
5705 /* check if we are transitioning to a legal power level */
5706 if (USB_DEV_PWRSTATE_OK(pm->scsa2usb_pwr_states, level)) {
5707 USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle,
5708 "scsa2usb_power: illegal power level = %d "
5709 "pwr_states: %x", level, pm->scsa2usb_pwr_states);
5710 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5712 return (rval);
5715 switch (level) {
5716 case USB_DEV_OS_PWR_OFF :
5717 rval = scsa2usb_pwrlvl0(scsa2usbp);
5718 break;
5719 case USB_DEV_OS_PWR_1 :
5720 rval = scsa2usb_pwrlvl1(scsa2usbp);
5721 break;
5722 case USB_DEV_OS_PWR_2 :
5723 rval = scsa2usb_pwrlvl2(scsa2usbp);
5724 break;
5725 case USB_DEV_OS_FULL_PWR :
5726 rval = scsa2usb_pwrlvl3(scsa2usbp);
5727 break;
5730 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5732 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
5736 static void
5737 scsa2usb_pm_busy_component(scsa2usb_state_t *scsa2usbp)
5739 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
5741 if (scsa2usbp->scsa2usb_pm) {
5742 scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy++;
5744 USB_DPRINTF_L4(DPRINT_MASK_PM,
5745 scsa2usbp->scsa2usb_log_handle,
5746 "scsa2usb_pm_busy_component: %d",
5747 scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy);
5749 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5751 if (pm_busy_component(scsa2usbp->scsa2usb_dip, 0) !=
5752 DDI_SUCCESS) {
5753 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5754 ASSERT(scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy > 0);
5755 scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy--;
5757 USB_DPRINTF_L2(DPRINT_MASK_PM,
5758 scsa2usbp->scsa2usb_log_handle,
5759 "scsa2usb_pm_busy_component failed: %d",
5760 scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy);
5762 return;
5764 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5770 * scsa2usb_pm_idle_component:
5771 * idles the device
5773 static void
5774 scsa2usb_pm_idle_component(scsa2usb_state_t *scsa2usbp)
5776 ASSERT(!mutex_owned(&scsa2usbp->scsa2usb_mutex));
5778 if (scsa2usbp->scsa2usb_pm) {
5779 if (pm_idle_component(scsa2usbp->scsa2usb_dip, 0) ==
5780 DDI_SUCCESS) {
5781 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5782 ASSERT(scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy > 0);
5783 scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy--;
5785 USB_DPRINTF_L4(DPRINT_MASK_PM,
5786 scsa2usbp->scsa2usb_log_handle,
5787 "scsa2usb_pm_idle_component: %d",
5788 scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy);
5790 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5796 #ifdef DEBUG
5798 * scsa2usb_print_cdb:
5799 * prints CDB
5801 void
5802 scsa2usb_print_cdb(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd)
5804 uchar_t *c = (uchar_t *)&cmd->cmd_cdb;
5806 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
5807 "cmd = 0x%p opcode=%s "
5808 "cdb: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
5809 (void *)cmd,
5810 scsi_cname(cmd->cmd_cdb[SCSA2USB_OPCODE], scsa2usb_cmds),
5811 c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8],
5812 c[9], c[10], c[11], c[12], c[13], c[14], c[15]);
5814 #endif /* DEBUG */
5817 #ifdef SCSA2USB_BULK_ONLY_TEST
5819 * scsa2usb_test_mblk:
5820 * This function sends a dummy data mblk_t to simulate
5821 * the following test cases: 5 and 11.
5823 static void
5824 scsa2usb_test_mblk(scsa2usb_state_t *scsa2usbp, boolean_t large)
5826 int i, rval;
5827 size_t len;
5828 usb_flags_t flags = USB_FLAGS_SLEEP;
5829 usb_bulk_req_t *req;
5831 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));
5833 /* should we create a larger mblk? */
5834 len = (large == B_TRUE) ? DEV_BSIZE : USB_BULK_CBWCMD_LEN;
5836 req = scsa2usb_init_bulk_req(scsa2usbp, len,
5837 SCSA2USB_BULK_PIPE_TIMEOUT, 0, flags);
5839 /* fill up the data mblk */
5840 for (i = 0; i < len; i++) {
5841 *req->bulk_data->b_wptr++ = (uchar_t)i;
5844 mutex_exit(&scsa2usbp->scsa2usb_mutex);
5845 ASSERT(req->bulk_timeout);
5846 rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkout_pipe, req, flags);
5847 mutex_enter(&scsa2usbp->scsa2usb_mutex);
5849 USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
5850 "scsa2usb_test_mblk: Sent Data Out rval = 0x%x", rval);
5852 usb_free_bulk_req(req);
5854 #endif /* SCSA2USB_BULK_ONLY_TEST */