• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <sys/cdefs.h>
2 __FBSDID("$FreeBSD: releng/12.2/sys/dev/usb/storage/umass.c 327173 2017-12-25 04:48:39Z kan $");
3 
4 /*-
5  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
6  *
7  * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>,
8  *		      Nick Hibma <n_hibma@FreeBSD.org>
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *	$FreeBSD: releng/12.2/sys/dev/usb/storage/umass.c 327173 2017-12-25 04:48:39Z kan $
33  *	$NetBSD: umass.c,v 1.28 2000/04/02 23:46:53 augustss Exp $
34  */
35 
36 /* Also already merged from NetBSD:
37  *	$NetBSD: umass.c,v 1.67 2001/11/25 19:05:22 augustss Exp $
38  *	$NetBSD: umass.c,v 1.90 2002/11/04 19:17:33 pooka Exp $
39  *	$NetBSD: umass.c,v 1.108 2003/11/07 17:03:25 wiz Exp $
40  *	$NetBSD: umass.c,v 1.109 2003/12/04 13:57:31 keihan Exp $
41  */
42 
43 /*
44  * Universal Serial Bus Mass Storage Class specs:
45  * http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf
46  * http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf
47  * http://www.usb.org/developers/devclass_docs/usb_msc_cbi_1.1.pdf
48  * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf
49  */
50 
51 /*
52  * Ported to NetBSD by Lennart Augustsson <augustss@NetBSD.org>.
53  * Parts of the code written by Jason R. Thorpe <thorpej@shagadelic.org>.
54  */
55 
56 /*
57  * The driver handles 3 Wire Protocols
58  * - Command/Bulk/Interrupt (CBI)
59  * - Command/Bulk/Interrupt with Command Completion Interrupt (CBI with CCI)
60  * - Mass Storage Bulk-Only (BBB)
61  *   (BBB refers Bulk/Bulk/Bulk for Command/Data/Status phases)
62  *
63  * Over these wire protocols it handles the following command protocols
64  * - SCSI
65  * - UFI (floppy command set)
66  * - 8070i (ATAPI)
67  *
68  * UFI and 8070i (ATAPI) are transformed versions of the SCSI command set. The
69  * sc->sc_transform method is used to convert the commands into the appropriate
70  * format (if at all necessary). For example, UFI requires all commands to be
71  * 12 bytes in length amongst other things.
72  *
73  * The source code below is marked and can be split into a number of pieces
74  * (in this order):
75  *
76  * - probe/attach/detach
77  * - generic transfer routines
78  * - BBB
79  * - CBI
80  * - CBI_I (in addition to functions from CBI)
81  * - CAM (Common Access Method)
82  * - SCSI
83  * - UFI
84  * - 8070i (ATAPI)
85  *
86  * The protocols are implemented using a state machine, for the transfers as
87  * well as for the resets. The state machine is contained in umass_t_*_callback.
88  * The state machine is started through either umass_command_start() or
89  * umass_reset().
90  *
91  * The reason for doing this is a) CAM performs a lot better this way and b) it
92  * avoids using tsleep from interrupt context (for example after a failed
93  * transfer).
94  */
95 
96 /*
97  * The SCSI related part of this driver has been derived from the
98  * dev/ppbus/vpo.c driver, by Nicolas Souchu (nsouch@FreeBSD.org).
99  *
100  * The CAM layer uses so called actions which are messages sent to the host
101  * adapter for completion. The actions come in through umass_cam_action. The
102  * appropriate block of routines is called depending on the transport protocol
103  * in use. When the transfer has finished, these routines call
104  * umass_cam_cb again to complete the CAM command.
105  */
106 
107 #include <driver.h>
108 #include <disk.h>
109 
110 #include "implementation/global_implementation.h"
111 #include "scsi_all.h"
112 #include "scsi.h"
113 #if USB_HAVE_DEVICE_TOPOLOGY
114 #include "implementation/usb_btree.h"
115 #endif
116 #include "user_copy.h"
117 
118 #ifdef LOSCFG_USB_DEBUG
119 #define	DIF(m, x)				\
120   do {						\
121     if (umass_debug & (m)) { x ; }		\
122   } while (0)
123 
124 #define	DPRINTF_UMASS(sc, m, fmt, ...)			\
125   do {							\
126 	if (umass_debug & (m)) {				\
127 		PRINTK("%s:%s: " fmt,				\
128 		    (sc) ? (const char *)(sc)->sc_name :	\
129 		    (const char *)"umassX",			\
130 		    __FUNCTION__ ,## __VA_ARGS__);		\
131 	}							\
132   } while (0)
133 
134 #define	UDMASS_GEN	0x00010000	/* general */
135 #define	UDMASS_SCSI	0x00020000	/* scsi */
136 #define	UDMASS_UFI	0x00040000	/* ufi command set */
137 #define	UDMASS_ATAPI	0x00080000	/* 8070i command set */
138 #define	UDMASS_CMD	(UDMASS_SCSI|UDMASS_UFI|UDMASS_ATAPI)
139 #define	UDMASS_USB	0x00100000	/* USB general */
140 #define	UDMASS_BBB	0x00200000	/* Bulk-Only transfers */
141 #define	UDMASS_CBI	0x00400000	/* CBI transfers */
142 #define	UDMASS_WIRE	(UDMASS_BBB|UDMASS_CBI)
143 #define	UDMASS_ALL	0xffff0000	/* all of the above */
144 static int umass_debug = 0; 	/* UDMASS_ALL; */
145 static int umass_throttle;
146 
147 void
148 umass_debug_func(int level)
149 {
150 	switch(level) {
151 		case 0:
152 			umass_debug = 0;
153 			PRINTK("Close the umass debug\n");
154 			break;
155 		case UDMASS_GEN:
156 		case UDMASS_SCSI:
157 		case UDMASS_UFI:
158 		case UDMASS_ATAPI:
159 		case UDMASS_CMD:
160 		case UDMASS_USB:
161 		case UDMASS_BBB:
162 		case UDMASS_CBI:
163 		case UDMASS_WIRE:
164 		case UDMASS_ALL:
165 			umass_debug = level;
166 			PRINTK("The level of umass debug is %x\n", level);
167 			break;
168 		default:
169 			PRINT_ERR("The level of umass debug is invalid, please refer to umass.c\n");
170 			break;
171 	}
172 }
173 DEBUG_MODULE(umass, umass_debug_func);
174 #else
175 #define	DIF(...) do { } while (0)
176 #define	DPRINTF_UMASS(...) do { } while (0)
177 #endif
178 
179 #define	UMASS_BULK_SIZE (1 << 17)
180 #define	UMASS_CBI_DIAGNOSTIC_CMDLEN 12	/* bytes */
181 #define	UMASS_MAX_CMDLEN MAX(12, CBWCDBLENGTH)	/* bytes */
182 
183 /* USB transfer definitions */
184 
185 #define	UMASS_T_BBB_RESET1		0	/* Bulk-Only */
186 #define	UMASS_T_BBB_RESET2		1
187 #define	UMASS_T_BBB_RESET3		2
188 #define	UMASS_T_BBB_COMMAND		3
189 #define	UMASS_T_BBB_DATA_READ	4
190 #define	UMASS_T_BBB_DATA_RD_CS	5
191 #define	UMASS_T_BBB_DATA_WRITE	6
192 #define	UMASS_T_BBB_DATA_WR_CS	7
193 #define	UMASS_T_BBB_STATUS		8
194 #define	UMASS_T_BBB_MAX			9
195 
196 #define	UMASS_T_CBI_RESET1		0	/* CBI */
197 #define	UMASS_T_CBI_RESET2		1
198 #define	UMASS_T_CBI_RESET3		2
199 #define	UMASS_T_CBI_COMMAND		3
200 #define	UMASS_T_CBI_DATA_READ	4
201 #define	UMASS_T_CBI_DATA_RD_CS	5
202 #define	UMASS_T_CBI_DATA_WRITE	6
203 #define	UMASS_T_CBI_DATA_WR_CS	7
204 #define	UMASS_T_CBI_STATUS		8
205 #define	UMASS_T_CBI_RESET4		9
206 #define	UMASS_T_CBI_MAX			10
207 
208 #define	UMASS_T_MAX MAX(UMASS_T_CBI_MAX, UMASS_T_BBB_MAX)
209 
210 /* Generic definitions */
211 
212 /* Direction for transfer */
213 #define	DIR_NONE	0
214 #define	DIR_IN		1
215 #define	DIR_OUT		2
216 
217 /* device name */
218 #define	DEVNAME		"umass"
219 #define	DEVNAME_SIM	"umass-sim"
220 
221 /* Approximate maximum transfer speeds (assumes 33% overhead). */
222 #define	UMASS_FULL_TRANSFER_SPEED	1000
223 #define	UMASS_HIGH_TRANSFER_SPEED	40000
224 #define	UMASS_SUPER_TRANSFER_SPEED	400000
225 #define	UMASS_FLOPPY_TRANSFER_SPEED	20
226 
227 #define	UMASS_TIMEOUT			20000	/* ms */
228 
229 /* CAM specific definitions */
230 #define	UMASS_SCSIID_MAX	1	/* maximum number of drives expected */
231 #define	UMASS_SCSIID_HOST	UMASS_SCSIID_MAX
232 
233 /* Bulk-Only features */
234 #define	UR_BBB_RESET		0xff	/* Bulk-Only reset */
235 #define	UR_BBB_GET_MAX_LUN	0xfe	/* Get maximum lun */
236 
237 #define UMASS_ATTACH_PRENAME		"/dev/sd"
238 #define MASS_NAME		10
239 #define MAX_DEVICE		5
240 
241 /*
242  * SCSI I/O Request CCB used for the XPT_SCSI_IO and XPT_CONT_TARGET_IO
243  * function codes.
244  */
245 struct ccb_scsiio {
246 	uint8_t *data_ptr;		/* Ptr to the data buf/SG list */
247 	uint32_t dxfer_len;		/* Data transfer length */
248 	uint32_t resid;			/* Transfer residual length: 2's comp */
249 	int32_t  status;
250 
251 	struct	 scsi_sense_data sense_data;
252 	uint8_t   sense_len;	/* Number of bytes to autosense */
253 };
254 
255 union ccb {
256 	struct	ccb_scsiio	csio;
257 };
258 
259 
260 /* Command Block Wrapper */
261 typedef struct {
262 	uDWord	dCBWSignature;
263 #define	CBWSIGNATURE	0x43425355
264 	uDWord	dCBWTag;
265 	uDWord	dCBWDataTransferLength;
266 	uByte	bCBWFlags;
267 #define	CBWFLAGS_OUT	0x00
268 #define	CBWFLAGS_IN		0x80
269 	uByte	bCBWLUN;
270 	uByte	bCDBLength;
271 #define	CBWCDBLENGTH	16
272 	uByte	CBWCDB[CBWCDBLENGTH];
273 } __packed umass_bbb_cbw_t;
274 
275 #define	UMASS_BBB_CBW_SIZE	31
276 
277 /* Command Status Wrapper */
278 typedef struct {
279 	uDWord	dCSWSignature;
280 #define	CSWSIGNATURE					0x53425355
281 #define	CSWSIGNATURE_IMAGINATION_DBX1	0x43425355
282 #define	CSWSIGNATURE_OLYMPUS_C1			0x55425355
283 	uDWord	dCSWTag;
284 	uDWord	dCSWDataResidue;
285 	uByte	bCSWStatus;
286 #define	CSWSTATUS_GOOD		0x0
287 #define	CSWSTATUS_FAILED	0x1
288 #define	CSWSTATUS_PHASE		0x2
289 } __packed umass_bbb_csw_t;
290 
291 #define	UMASS_BBB_CSW_SIZE	13
292 
293 /* CBI features */
294 
295 #define	UR_CBI_ADSC	0x00
296 
297 typedef union {
298 	struct {
299 		uint8_t	type;
300 #define	IDB_TYPE_CCI			0x00
301 		uint8_t	value;
302 #define	IDB_VALUE_PASS			0x00
303 #define	IDB_VALUE_FAIL			0x01
304 #define	IDB_VALUE_PHASE			0x02
305 #define	IDB_VALUE_PERSISTENT	0x03
306 #define	IDB_VALUE_STATUS_MASK	0x03
307 	} __packed common;
308 
309 	struct {
310 		uint8_t	asc;
311 		uint8_t	ascq;
312 	} __packed ufi;
313 } __packed umass_cbi_sbl_t;
314 
315 struct umass_info {
316 	uint32_t sectorsize;
317 	uint64_t sectornum;
318 };
319 
320 struct umass_softc;			/* see below */
321 
322 typedef void (umass_callback_t)(struct umass_softc *sc, union ccb *ccb,
323 		uint32_t residue, uint8_t status);
324 
325 #define	STATUS_CMD_OK		0	/* everything ok */
326 #define	STATUS_CMD_UNKNOWN	1	/* will have to fetch sense */
327 #define	STATUS_CMD_FAILED	2	/* transfer was ok, command failed */
328 #define	STATUS_WIRE_FAILED	3	/* couldn't even get command across */
329 
330 typedef uint8_t (umass_transform_t)(struct umass_softc *sc, uint8_t *cmd_ptr,
331 	    uint8_t cmd_len);
332 
333 /* Wire and command protocol */
334 #define	UMASS_PROTO_BBB		0x0001	/* USB wire protocol */
335 #define	UMASS_PROTO_CBI		0x0002
336 #define	UMASS_PROTO_CBI_I	0x0004
337 #define	UMASS_PROTO_WIRE	0x00ff	/* USB wire protocol mask */
338 #define	UMASS_PROTO_SCSI	0x0100	/* command protocol */
339 #define	UMASS_PROTO_ATAPI	0x0200
340 #define	UMASS_PROTO_UFI		0x0400
341 #define	UMASS_PROTO_RBC		0x0800
342 #define	UMASS_PROTO_COMMAND	0xff00	/* command protocol mask */
343 
344 /* Device specific quirks */
345 #define	NO_QUIRKS			0x0000
346 	/*
347 	 * The drive does not support Test Unit Ready. Convert to Start Unit
348 	 */
349 #define	NO_TEST_UNIT_READY	0x0001
350 	/*
351 	 * The drive does not reset the Unit Attention state after REQUEST
352 	 * SENSE has been sent. The INQUIRY command does not reset the UA
353 	 * either, and so CAM runs in circles trying to retrieve the initial
354 	 * INQUIRY data.
355 	 */
356 #define	RS_NO_CLEAR_UA		0x0002
357 	/* The drive does not support START STOP.  */
358 #define	NO_START_STOP		0x0004
359 	/* Don't ask for full inquiry data (255b).  */
360 #define	FORCE_SHORT_INQUIRY	0x0008
361 	/* Needs to be initialised the Shuttle way */
362 #define	SHUTTLE_INIT		0x0010
363 	/* Drive needs to be switched to alternate iface 1 */
364 #define	ALT_IFACE_1			0x0020
365 	/* Drive does not do 1Mb/s, but just floppy speeds (20kb/s) */
366 #define	FLOPPY_SPEED		0x0040
367 	/* The device can't count and gets the residue of transfers wrong */
368 #define	IGNORE_RESIDUE		0x0080
369 	/* No GetMaxLun call */
370 #define	NO_GETMAXLUN		0x0100
371 	/* The device uses a weird CSWSIGNATURE. */
372 #define	WRONG_CSWSIG		0x0200
373 	/* Device cannot handle INQUIRY so fake a generic response */
374 #define	NO_INQUIRY			0x0400
375 	/* Device cannot handle INQUIRY EVPD, return CHECK CONDITION */
376 #define	NO_INQUIRY_EVPD		0x0800
377 	/* Pad all RBC requests to 12 bytes. */
378 #define	RBC_PAD_TO_12		0x1000
379 	/*
380 	 * Device reports number of sectors from READ_CAPACITY, not max
381 	 * sector number.
382 	 */
383 #define	READ_CAPACITY_OFFBY1	0x2000
384 	/*
385 	 * Device cannot handle a SCSI synchronize cache command.  Normally
386 	 * this quirk would be handled in the cam layer, but for IDE bridges
387 	 * we need to associate the quirk with the bridge and not the
388 	 * underlying disk device.  This is handled by faking a success
389 	 * result.
390 	 */
391 #define	NO_SYNCHRONIZE_CACHE	0x4000
392 	/* Device does not support 'PREVENT/ALLOW MEDIUM REMOVAL'. */
393 #define	NO_PREVENT_ALLOW		0x8000
394 
395 #if USB_HAVE_DEVICE_TOPOLOGY
396 extern usbd_bt_tree hub_tree;
397 #endif
398 
399 struct umass_softc {
400 	union ccb *data_ccb;
401 	struct scsi_sense cam_scsi_sense;
402 	struct scsi_test_unit_ready cam_scsi_test_unit_ready;
403 	struct mtx sc_mtx;
404 	EVENT_CB_S sc_event;
405 	struct {
406 		uint8_t *data_ptr;
407 		union ccb *ccb;
408 		umass_callback_t *callback;
409 
410 		uint32_t data_len;		/* bytes */
411 		uint32_t data_rem;		/* bytes */
412 		uint32_t data_timeout;	/* ms */
413 		uint32_t actlen;		/* bytes */
414 
415 		uint8_t	cmd_data[UMASS_MAX_CMDLEN];
416 		uint8_t	cmd_len;		/* bytes */
417 		uint8_t	dir;
418 		uint8_t	lun;
419 	}	sc_transfer;
420 
421 	struct umass_info info;
422 
423 	/* Bulk specific variables for transfers in progress */
424 	umass_bbb_cbw_t cbw;		/* command block wrapper */
425 	umass_bbb_csw_t csw;		/* command status wrapper */
426 
427 	/* CBI specific variables for transfers in progress */
428 	umass_cbi_sbl_t sbl;		/* status block */
429 
430 	device_t sc_dev;
431 	struct usb_device *sc_udev;
432 	struct usb_xfer *sc_xfer[UMASS_T_MAX];
433 
434 	/*
435 	 * The command transform function is used to convert the SCSI
436 	 * commands into their derivatives, like UFI, ATAPI, and friends.
437 	 */
438 	umass_transform_t *sc_transform;
439 
440 	uint32_t sc_unit;
441 	uint32_t sc_quirks;		/* they got it almost right */
442 	uint32_t sc_proto;		/* wire and cmd protocol */
443 
444 	uint8_t	sc_name[16];
445 	uint8_t	sc_iface_no;	/* interface number */
446 	uint8_t	sc_maxlun;		/* maximum LUN number, inclusive */
447 	uint8_t	sc_last_xfer_index;
448 	uint8_t	sc_status_try;
449 	BOOL	sc_detach_status;
450 	BOOL	sc_super_disk;		/* TRUE: Disk is bigger than 2T; FALSE: Disk is less than 2T */
451 	struct mtx sc_umass_mtx;	/* The mtx is used to prevent data read and write competition */
452 };
453 
454 struct umass_probe_proto {
455 	uint32_t quirks;
456 	uint32_t proto;
457 
458 	int	error;
459 };
460 
461 #if USB_SUPPORT_SD_HOT_PLUG
462 struct umass_dev_info {
463 	struct umass_softc *sc;
464 	unsigned int dev_unit;
465 	int used;			/* 0: not use; 1: in use */
466 	int attached;		/* 0: not attach; 1: in attach */
467 	struct mtx dev_mtx;	/* The mtx is used to prevent U disk insertion or extraction competition */
468 };
469 
470 static struct umass_dev_info g_umass_dev_array[MAX_DEVICE] = {0};
471 static void umass_task_check(int flag);
472 static void umass_dev_delete(struct umass_softc *sc, unsigned int dev_unit);
473 int umass_dev_is_attached(unsigned int dev_unit);
474 static void umass_dev_attach_flag_set(int dev_unit);
475 pthread_t   umass_taskid;
476 #define	umass_dev_mtx_init(id, type) (void)mtx_init(&g_umass_dev_array[id].dev_mtx, NULL, NULL, type)
477 #define	umass_dev_mtx_destroy(id)	 (void)mtx_destroy(&g_umass_dev_array[id].dev_mtx)
478 #define	umass_dev_lock(id)			 (void)mtx_lock(&g_umass_dev_array[id].dev_mtx)
479 #define	umass_dev_unlock(id)		 (void)mtx_unlock(&g_umass_dev_array[id].dev_mtx)
480 #else
481 #define	umass_dev_lock(id) (void)mtx_lock(NULL)
482 #define	umass_dev_unlock(id) (void)mtx_unlock(NULL)
483 #endif
484 
485 struct umass_softc *p_umsf = NULL;
486 /* prototypes */
487 
488 static device_probe_t umass_probe;
489 static device_attach_t umass_attach;
490 static device_detach_t umass_detach;
491 
492 static usb_callback_t umass_tr_error;
493 static usb_callback_t umass_t_bbb_reset1_callback;
494 static usb_callback_t umass_t_bbb_reset2_callback;
495 static usb_callback_t umass_t_bbb_reset3_callback;
496 static usb_callback_t umass_t_bbb_command_callback;
497 static usb_callback_t umass_t_bbb_data_read_callback;
498 static usb_callback_t umass_t_bbb_data_rd_cs_callback;
499 static usb_callback_t umass_t_bbb_data_write_callback;
500 static usb_callback_t umass_t_bbb_data_wr_cs_callback;
501 static usb_callback_t umass_t_bbb_status_callback;
502 static usb_callback_t umass_t_cbi_reset1_callback;
503 static usb_callback_t umass_t_cbi_reset2_callback;
504 static usb_callback_t umass_t_cbi_reset3_callback;
505 static usb_callback_t umass_t_cbi_reset4_callback;
506 static usb_callback_t umass_t_cbi_command_callback;
507 static usb_callback_t umass_t_cbi_data_read_callback;
508 static usb_callback_t umass_t_cbi_data_rd_cs_callback;
509 static usb_callback_t umass_t_cbi_data_write_callback;
510 static usb_callback_t umass_t_cbi_data_wr_cs_callback;
511 static usb_callback_t umass_t_cbi_status_callback;
512 
513 static void	umass_cancel_ccb(struct umass_softc *);
514 static void	umass_init_shuttle(struct umass_softc *);
515 static void	umass_t_bbb_data_clear_stall_callback(struct usb_xfer *,
516 			uint8_t, uint8_t, usb_error_t);
517 static int	umass_command_start(struct umass_softc *, uint8_t, void *,
518 			uint32_t, uint32_t, umass_callback_t *, union ccb *);
519 static uint8_t	umass_bbb_get_max_lun(struct umass_softc *);
520 static void	umass_cbi_start_status(struct umass_softc *);
521 static void	umass_t_cbi_data_clear_stall_callback(struct usb_xfer *,
522 			uint8_t, uint8_t, usb_error_t);
523 static void	umass_cam_cb(struct umass_softc *, union ccb *, uint32_t, uint8_t);
524 static uint8_t	umass_scsi_transform(struct umass_softc *, uint8_t *, uint8_t);
525 static uint8_t	umass_rbc_transform(struct umass_softc *, uint8_t *, uint8_t);
526 static uint8_t	umass_ufi_transform(struct umass_softc *, uint8_t *, uint8_t);
527 static uint8_t	umass_atapi_transform(struct umass_softc *, uint8_t *,
528 			uint8_t);
529 static uint8_t	umass_no_transform(struct umass_softc *, uint8_t *, uint8_t);
530 
531 #ifdef LOSCFG_USB_DEBUG
532 static void	umass_bbb_dump_cbw(struct umass_softc *, umass_bbb_cbw_t *);
533 static void	umass_bbb_dump_csw(struct umass_softc *, umass_bbb_csw_t *);
534 static void	umass_cbi_dump_cmd(struct umass_softc *, void *, uint8_t);
535 #endif
536 
537 static void devunit_to_devname(unsigned int dev_unit, char *devname);
538 static int32_t umass_attach_dev(struct umass_softc *sc, unsigned int dev_unit);
539 static void umass_detach_dev_sub(struct umass_softc *sc, int dev_unit, int flag);
540 
541 static struct usb_config umass_bbb_config[UMASS_T_BBB_MAX] = {
542 
543 	[UMASS_T_BBB_RESET1] = {
544 		.type = UE_CONTROL,
545 		.endpoint = 0x00,	/* Control pipe */
546 		.direction = UE_DIR_ANY,
547 		.bufsize = sizeof(struct usb_device_request),
548 		.callback = &umass_t_bbb_reset1_callback,
549 		.timeout = 5000,	/* 5 seconds */
550 		.interval = 500,	/* 500 milliseconds */
551 	},
552 
553 	[UMASS_T_BBB_RESET2] = {
554 		.type = UE_CONTROL,
555 		.endpoint = 0x00,	/* Control pipe */
556 		.direction = UE_DIR_ANY,
557 		.bufsize = sizeof(struct usb_device_request),
558 		.callback = &umass_t_bbb_reset2_callback,
559 		.timeout = 5000,	/* 5 seconds */
560 		.interval = 50,	/* 50 milliseconds */
561 	},
562 
563 	[UMASS_T_BBB_RESET3] = {
564 		.type = UE_CONTROL,
565 		.endpoint = 0x00,	/* Control pipe */
566 		.direction = UE_DIR_ANY,
567 		.bufsize = sizeof(struct usb_device_request),
568 		.callback = &umass_t_bbb_reset3_callback,
569 		.timeout = 5000,	/* 5 seconds */
570 		.interval = 50,	/* 50 milliseconds */
571 	},
572 
573 	[UMASS_T_BBB_COMMAND] = {
574 		.type = UE_BULK,
575 		.endpoint = UE_ADDR_ANY,
576 		.direction = UE_DIR_OUT,
577 		.bufsize = sizeof(umass_bbb_cbw_t),
578 		.callback = &umass_t_bbb_command_callback,
579 		.timeout = 5000,	/* 5 seconds */
580 	},
581 
582 	[UMASS_T_BBB_DATA_READ] = {
583 		.type = UE_BULK,
584 		.endpoint = UE_ADDR_ANY,
585 		.direction = UE_DIR_IN,
586 		.bufsize = UMASS_BULK_SIZE,
587 		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
588 		.callback = &umass_t_bbb_data_read_callback,
589 		.timeout = 0,	/* overwritten later */
590 	},
591 
592 	[UMASS_T_BBB_DATA_RD_CS] = {
593 		.type = UE_CONTROL,
594 		.endpoint = 0x00,	/* Control pipe */
595 		.direction = UE_DIR_ANY,
596 		.bufsize = sizeof(struct usb_device_request),
597 		.callback = &umass_t_bbb_data_rd_cs_callback,
598 		.timeout = 5000,	/* 5 seconds */
599 	},
600 
601 	[UMASS_T_BBB_DATA_WRITE] = {
602 		.type = UE_BULK,
603 		.endpoint = UE_ADDR_ANY,
604 		.direction = UE_DIR_OUT,
605 		.bufsize = UMASS_BULK_SIZE,
606 		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
607 		.callback = &umass_t_bbb_data_write_callback,
608 		.timeout = 0,	/* overwritten later */
609 	},
610 
611 	[UMASS_T_BBB_DATA_WR_CS] = {
612 		.type = UE_CONTROL,
613 		.endpoint = 0x00,	/* Control pipe */
614 		.direction = UE_DIR_ANY,
615 		.bufsize = sizeof(struct usb_device_request),
616 		.callback = &umass_t_bbb_data_wr_cs_callback,
617 		.timeout = 5000,	/* 5 seconds */
618 	},
619 
620 	[UMASS_T_BBB_STATUS] = {
621 		.type = UE_BULK,
622 		.endpoint = UE_ADDR_ANY,
623 		.direction = UE_DIR_IN,
624 		.bufsize = sizeof(umass_bbb_csw_t),
625 		.flags = {.short_xfer_ok = 1,},
626 		.callback = &umass_t_bbb_status_callback,
627 		.timeout = 5000,	/* ms */
628 	},
629 };
630 
631 static struct usb_config umass_cbi_config[UMASS_T_CBI_MAX] = {
632 
633 	[UMASS_T_CBI_RESET1] = {
634 		.type = UE_CONTROL,
635 		.endpoint = 0x00,	/* Control pipe */
636 		.direction = UE_DIR_ANY,
637 		.bufsize = (sizeof(struct usb_device_request) +
638 		    UMASS_CBI_DIAGNOSTIC_CMDLEN),
639 		.callback = &umass_t_cbi_reset1_callback,
640 		.timeout = 5000,	/* 5 seconds */
641 		.interval = 500,	/* 500 milliseconds */
642 	},
643 
644 	[UMASS_T_CBI_RESET2] = {
645 		.type = UE_CONTROL,
646 		.endpoint = 0x00,	/* Control pipe */
647 		.direction = UE_DIR_ANY,
648 		.bufsize = sizeof(struct usb_device_request),
649 		.callback = &umass_t_cbi_reset2_callback,
650 		.timeout = 5000,	/* 5 seconds */
651 		.interval = 50,	/* 50 milliseconds */
652 	},
653 
654 	[UMASS_T_CBI_RESET3] = {
655 		.type = UE_CONTROL,
656 		.endpoint = 0x00,	/* Control pipe */
657 		.direction = UE_DIR_ANY,
658 		.bufsize = sizeof(struct usb_device_request),
659 		.callback = &umass_t_cbi_reset3_callback,
660 		.timeout = 5000,	/* 5 seconds */
661 		.interval = 50,	/* 50 milliseconds */
662 	},
663 
664 	[UMASS_T_CBI_COMMAND] = {
665 		.type = UE_CONTROL,
666 		.endpoint = 0x00,	/* Control pipe */
667 		.direction = UE_DIR_ANY,
668 		.bufsize = (sizeof(struct usb_device_request) +
669 		    UMASS_MAX_CMDLEN),
670 		.callback = &umass_t_cbi_command_callback,
671 		.timeout = 5000,	/* 5 seconds */
672 	},
673 
674 	[UMASS_T_CBI_DATA_READ] = {
675 		.type = UE_BULK,
676 		.endpoint = UE_ADDR_ANY,
677 		.direction = UE_DIR_IN,
678 		.bufsize = UMASS_BULK_SIZE,
679 		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
680 		.callback = &umass_t_cbi_data_read_callback,
681 		.timeout = 0,	/* overwritten later */
682 	},
683 
684 	[UMASS_T_CBI_DATA_RD_CS] = {
685 		.type = UE_CONTROL,
686 		.endpoint = 0x00,	/* Control pipe */
687 		.direction = UE_DIR_ANY,
688 		.bufsize = sizeof(struct usb_device_request),
689 		.callback = &umass_t_cbi_data_rd_cs_callback,
690 		.timeout = 5000,	/* 5 seconds */
691 	},
692 
693 	[UMASS_T_CBI_DATA_WRITE] = {
694 		.type = UE_BULK,
695 		.endpoint = UE_ADDR_ANY,
696 		.direction = UE_DIR_OUT,
697 		.bufsize = UMASS_BULK_SIZE,
698 		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
699 		.callback = &umass_t_cbi_data_write_callback,
700 		.timeout = 0,	/* overwritten later */
701 	},
702 
703 	[UMASS_T_CBI_DATA_WR_CS] = {
704 		.type = UE_CONTROL,
705 		.endpoint = 0x00,	/* Control pipe */
706 		.direction = UE_DIR_ANY,
707 		.bufsize = sizeof(struct usb_device_request),
708 		.callback = &umass_t_cbi_data_wr_cs_callback,
709 		.timeout = 5000,	/* 5 seconds */
710 	},
711 
712 	[UMASS_T_CBI_STATUS] = {
713 		.type = UE_INTERRUPT,
714 		.endpoint = UE_ADDR_ANY,
715 		.direction = UE_DIR_IN,
716 		.flags = {.short_xfer_ok = 1,.no_pipe_ok = 1,},
717 		.bufsize = sizeof(umass_cbi_sbl_t),
718 		.callback = &umass_t_cbi_status_callback,
719 		.timeout = 5000,	/* ms */
720 	},
721 
722 	[UMASS_T_CBI_RESET4] = {
723 		.type = UE_CONTROL,
724 		.endpoint = 0x00,	/* Control pipe */
725 		.direction = UE_DIR_ANY,
726 		.bufsize = sizeof(struct usb_device_request),
727 		.callback = &umass_t_cbi_reset4_callback,
728 		.timeout = 5000,	/* ms */
729 	},
730 };
731 
732 #define	UFI_COMMAND_LENGTH	12	/* UFI commands are always 12 bytes */
733 #define	ATAPI_COMMAND_LENGTH	12	/* ATAPI commands are always 12 bytes */
734 
735 static devclass_t umass_devclass;
736 
737 static device_method_t umass_methods[] = {
738 	/* Device interface */
739 	DEVMETHOD(device_probe, umass_probe),
740 	DEVMETHOD(device_attach, umass_attach),
741 	DEVMETHOD(device_detach, umass_detach),
742 
743 	DEVMETHOD_END
744 };
745 
746 static driver_t umass_driver = {
747 	.name = "umass",
748 	.methods = umass_methods,
749 	.size = sizeof(struct umass_softc),
750 };
751 
752 #if USB_HAVE_DEVICE_TOPOLOGY
753 UINT64 dev_quantity = 0;
754 #endif
755 
756 DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, NULL, 0);
757 
758 static uint16_t
759 umass_get_proto(struct usb_interface *iface)
760 {
761 	struct usb_interface_descriptor *id;
762 	uint16_t retval;
763 
764 	retval = 0;
765 
766 	/* Check for a standards compliant device */
767 	id = usbd_get_interface_descriptor(iface);
768 	if ((id == NULL) ||
769 	    (id->bInterfaceClass != UICLASS_MASS)) {
770 		goto done;
771 	}
772 	switch (id->bInterfaceSubClass) {
773 	case UISUBCLASS_SCSI:
774 		retval |= UMASS_PROTO_SCSI;
775 		break;
776 	case UISUBCLASS_UFI:
777 		retval |= UMASS_PROTO_UFI;
778 		break;
779 	case UISUBCLASS_RBC:
780 		retval |= UMASS_PROTO_RBC;
781 		break;
782 	case UISUBCLASS_SFF8020I:
783 	case UISUBCLASS_SFF8070I:
784 		retval |= UMASS_PROTO_ATAPI;
785 		break;
786 	default:
787 		goto done;
788 	}
789 
790 	switch (id->bInterfaceProtocol) {
791 	case UIPROTO_MASS_CBI:
792 		retval |= UMASS_PROTO_CBI;
793 		break;
794 	case UIPROTO_MASS_CBI_I:
795 		retval |= UMASS_PROTO_CBI_I;
796 		break;
797 	case UIPROTO_MASS_BBB_OLD:
798 	case UIPROTO_MASS_BBB:
799 		retval |= UMASS_PROTO_BBB;
800 		break;
801 	default:
802 		goto done;
803 	}
804 done:
805 	return (retval);
806 }
807 
808 /*
809  * Match the device we are seeing with the devices supported.
810  */
811 static struct umass_probe_proto
812 umass_probe_proto(device_t dev, struct usb_attach_arg *uaa)
813 {
814 	struct umass_probe_proto ret;
815 	uint32_t quirks = NO_QUIRKS;
816 	uint32_t proto = umass_get_proto(uaa->iface);
817 
818 	(void)memset_s(&ret, sizeof(ret), 0, sizeof(ret));
819 	ret.error = BUS_PROBE_GENERIC;
820 
821 	/* Search for protocol enforcement */
822 
823 	if (usb_test_quirk(uaa, UQ_MSC_FORCE_WIRE_BBB)) {
824 		proto &= ~UMASS_PROTO_WIRE;
825 		proto |= UMASS_PROTO_BBB;
826 	} else if (usb_test_quirk(uaa, UQ_MSC_FORCE_WIRE_CBI)) {
827 		proto &= ~UMASS_PROTO_WIRE;
828 		proto |= UMASS_PROTO_CBI;
829 	} else if (usb_test_quirk(uaa, UQ_MSC_FORCE_WIRE_CBI_I)) {
830 		proto &= ~UMASS_PROTO_WIRE;
831 		proto |= UMASS_PROTO_CBI_I;
832 	}
833 
834 	if (usb_test_quirk(uaa, UQ_MSC_FORCE_PROTO_SCSI)) {
835 		proto &= ~UMASS_PROTO_COMMAND;
836 		proto |= UMASS_PROTO_SCSI;
837 	} else if (usb_test_quirk(uaa, UQ_MSC_FORCE_PROTO_ATAPI)) {
838 		proto &= ~UMASS_PROTO_COMMAND;
839 		proto |= UMASS_PROTO_ATAPI;
840 	} else if (usb_test_quirk(uaa, UQ_MSC_FORCE_PROTO_UFI)) {
841 		proto &= ~UMASS_PROTO_COMMAND;
842 		proto |= UMASS_PROTO_UFI;
843 	} else if (usb_test_quirk(uaa, UQ_MSC_FORCE_PROTO_RBC)) {
844 		proto &= ~UMASS_PROTO_COMMAND;
845 		proto |= UMASS_PROTO_RBC;
846 	}
847 
848 	/* Check if the protocol is invalid */
849 
850 	if ((proto & UMASS_PROTO_COMMAND) == 0) {
851 		ret.error = ENXIO;
852 		goto done;
853 	}
854 
855 	if ((proto & UMASS_PROTO_WIRE) == 0) {
856 		ret.error = ENXIO;
857 		goto done;
858 	}
859 
860 	/* Search for quirks */
861 
862 	if (usb_test_quirk(uaa, UQ_MSC_NO_TEST_UNIT_READY))
863 		quirks |= NO_TEST_UNIT_READY;
864 	if (usb_test_quirk(uaa, UQ_MSC_NO_RS_CLEAR_UA))
865 		quirks |= RS_NO_CLEAR_UA;
866 	if (usb_test_quirk(uaa, UQ_MSC_NO_START_STOP))
867 		quirks |= NO_START_STOP;
868 	if (usb_test_quirk(uaa, UQ_MSC_NO_GETMAXLUN))
869 		quirks |= NO_GETMAXLUN;
870 	if (usb_test_quirk(uaa, UQ_MSC_NO_INQUIRY))
871 		quirks |= NO_INQUIRY;
872 	if (usb_test_quirk(uaa, UQ_MSC_NO_INQUIRY_EVPD))
873 		quirks |= NO_INQUIRY_EVPD;
874 	if (usb_test_quirk(uaa, UQ_MSC_NO_PREVENT_ALLOW))
875 		quirks |= NO_PREVENT_ALLOW;
876 	if (usb_test_quirk(uaa, UQ_MSC_NO_SYNC_CACHE))
877 		quirks |= NO_SYNCHRONIZE_CACHE;
878 	if (usb_test_quirk(uaa, UQ_MSC_SHUTTLE_INIT))
879 		quirks |= SHUTTLE_INIT;
880 	if (usb_test_quirk(uaa, UQ_MSC_ALT_IFACE_1))
881 		quirks |= ALT_IFACE_1;
882 	if (usb_test_quirk(uaa, UQ_MSC_FLOPPY_SPEED))
883 		quirks |= FLOPPY_SPEED;
884 	if (usb_test_quirk(uaa, UQ_MSC_IGNORE_RESIDUE))
885 		quirks |= IGNORE_RESIDUE;
886 	if (usb_test_quirk(uaa, UQ_MSC_WRONG_CSWSIG))
887 		quirks |= WRONG_CSWSIG;
888 	if (usb_test_quirk(uaa, UQ_MSC_RBC_PAD_TO_12))
889 		quirks |= RBC_PAD_TO_12;
890 	if (usb_test_quirk(uaa, UQ_MSC_READ_CAP_OFFBY1))
891 		quirks |= READ_CAPACITY_OFFBY1;
892 	if (usb_test_quirk(uaa, UQ_MSC_FORCE_SHORT_INQ))
893 		quirks |= FORCE_SHORT_INQUIRY;
894 
895 done:
896 	ret.quirks = quirks;
897 	ret.proto = proto;
898 	return (ret);
899 }
900 
901 static int
902 umass_probe(device_t dev)
903 {
904 	struct usb_attach_arg *uaa =
905 	    (struct usb_attach_arg *)device_get_ivars(dev);
906 	struct umass_probe_proto temp;
907 
908 	if (uaa->usb_mode != USB_MODE_HOST) {
909 		return (ENXIO);
910 	}
911 	temp = umass_probe_proto(dev, uaa);
912 
913 	return (temp.error);
914 }
915 
916 static int
917 umass_attach(device_t dev)
918 {
919 	struct umass_softc *sc =
920 		(struct umass_softc *)device_get_softc(dev);
921 	struct usb_attach_arg *uaa =
922 		(struct usb_attach_arg *)device_get_ivars(dev);
923 	struct umass_probe_proto temp = umass_probe_proto(dev, uaa);
924 	struct usb_interface_descriptor *id;
925 	usb_error_t err;
926 
927 	/*
928 	 * NOTE: the softc struct is cleared in device_set_driver.
929 	 * We can safely call umass_detach without specifically
930 	 * initializing the struct.
931 	 */
932 
933 	sc->sc_dev = dev;
934 	sc->sc_udev = uaa->device;
935 	sc->sc_proto = temp.proto;
936 	sc->sc_quirks = temp.quirks;
937 	sc->sc_unit = device_get_unit(dev);
938 	sc->data_ccb = NULL;
939 	sc->sc_detach_status = FALSE;
940 	sc->sc_super_disk = FALSE;
941 
942 #if USB_HAVE_DEVICE_TOPOLOGY
943 	dev_quantity |= 1ull << (unsigned int)device_get_unit(dev);
944 #endif
945 
946 	(void)snprintf_s((char *)sc->sc_name, sizeof(sc->sc_name), sizeof(sc->sc_name) - 1,
947 	    "%s", device_get_nameunit(dev));
948 
949 	device_set_usb_desc(dev);
950 
951 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev),
952 		    NULL, MTX_DEF | MTX_RECURSE);
953 	mtx_init(&sc->sc_umass_mtx, device_get_nameunit(dev),
954 		    NULL, MTX_DEF | MTX_RECURSE);
955 
956 	(void)LOS_EventInit(&sc->sc_event);
957 
958 	/* get interface index */
959 
960 	id = usbd_get_interface_descriptor(uaa->iface);
961 	if (id == NULL) {
962 		device_printf(dev, "failed to get "
963 			"interface number\n");
964 		goto detach;
965 	}
966 	sc->sc_iface_no = id->bInterfaceNumber;
967 
968 	device_printf(dev, " ");
969 
970 	switch (sc->sc_proto & UMASS_PROTO_COMMAND) {
971 	case UMASS_PROTO_SCSI:
972 		PRINTK("SCSI");
973 		break;
974 	case UMASS_PROTO_ATAPI:
975 		PRINTK("8070i (ATAPI)");
976 		break;
977 	case UMASS_PROTO_UFI:
978 		PRINTK("UFI");
979 		break;
980 	case UMASS_PROTO_RBC:
981 		PRINTK("RBC");
982 		break;
983 	default:
984 		PRINTK("(unknown 0x%02x)",
985 		    sc->sc_proto & UMASS_PROTO_COMMAND);
986 		break;
987 	}
988 
989 	PRINTK(" over ");
990 
991 	switch (sc->sc_proto & UMASS_PROTO_WIRE) {
992 	case UMASS_PROTO_BBB:
993 		PRINTK("Bulk-Only");
994 		break;
995 	case UMASS_PROTO_CBI:		/* uses Comand/Bulk pipes */
996 		PRINTK("CBI");
997 		break;
998 	case UMASS_PROTO_CBI_I:	/* uses Comand/Bulk/Interrupt pipes */
999 		PRINTK("CBI with CCI");
1000 		break;
1001 	default:
1002 		PRINTK("(unknown 0x%02x)",
1003 		    sc->sc_proto & UMASS_PROTO_WIRE);
1004 	}
1005 
1006 	PRINTK("; quirks = 0x%04x\n", sc->sc_quirks);
1007 
1008 	if (sc->sc_quirks & ALT_IFACE_1) {
1009 		err = usbd_set_alt_interface_index
1010 		    (uaa->device, uaa->info.bIfaceIndex, 1);
1011 
1012 		if (err) {
1013 			DPRINTF_UMASS(sc, UDMASS_USB, "could not switch to "
1014 			    "Alt Interface 1\n");
1015 			goto detach;
1016 		}
1017 	}
1018 	/* allocate all required USB transfers */
1019 
1020 	if (sc->sc_proto & UMASS_PROTO_BBB) {
1021 
1022 		err = usbd_transfer_setup(uaa->device,
1023 		    &uaa->info.bIfaceIndex, sc->sc_xfer, umass_bbb_config,
1024 		    UMASS_T_BBB_MAX, sc, &sc->sc_mtx);
1025 
1026 		/* skip reset first time */
1027 		sc->sc_last_xfer_index = UMASS_T_BBB_COMMAND;
1028 
1029 	} else if (sc->sc_proto & (UMASS_PROTO_CBI | UMASS_PROTO_CBI_I)) {
1030 
1031 		err = usbd_transfer_setup(uaa->device,
1032 		    &uaa->info.bIfaceIndex, sc->sc_xfer, umass_cbi_config,
1033 		    UMASS_T_CBI_MAX, sc, &sc->sc_mtx);
1034 
1035 		/* skip reset first time */
1036 		sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND;
1037 
1038 	} else {
1039 		err = USB_ERR_INVAL;
1040 	}
1041 
1042 	if (err) {
1043 		device_printf(dev, "could not setup required "
1044 		    "transfers, %s\n", usbd_errstr(err));
1045 		goto detach;
1046 	}
1047 #ifdef LOSCFG_USB_DEBUG
1048 	if (umass_throttle > 0) {
1049 		uint8_t x;
1050 		int iv;
1051 
1052 		iv = umass_throttle;
1053 
1054 		if (iv < 1)
1055 			iv = 1;
1056 		else if (iv > 8000)
1057 			iv = 8000;
1058 
1059 		for (x = 0; x != UMASS_T_MAX; x++) {
1060 			if (sc->sc_xfer[x] != NULL)
1061 				usbd_xfer_set_interval(sc->sc_xfer[x], iv);
1062 		}
1063 	}
1064 #endif
1065 	sc->sc_transform =
1066 	    (sc->sc_proto & UMASS_PROTO_SCSI) ? &umass_scsi_transform :
1067 	    (sc->sc_proto & UMASS_PROTO_UFI) ? &umass_ufi_transform :
1068 	    (sc->sc_proto & UMASS_PROTO_ATAPI) ? &umass_atapi_transform :
1069 	    (sc->sc_proto & UMASS_PROTO_RBC) ? &umass_rbc_transform :
1070 	    &umass_no_transform;
1071 
1072 	/* from here onwards the device can be used. */
1073 
1074 	if (sc->sc_quirks & SHUTTLE_INIT) {
1075 		umass_init_shuttle(sc);
1076 	}
1077 	/* get the maximum LUN supported by the device */
1078 
1079 	if (((sc->sc_proto & UMASS_PROTO_WIRE) == UMASS_PROTO_BBB) &&
1080 	    !(sc->sc_quirks & NO_GETMAXLUN))
1081 		sc->sc_maxlun = umass_bbb_get_max_lun(sc);
1082 	else
1083 		sc->sc_maxlun = 0;
1084 
1085 	/* Prepare the SCSI command block */
1086 	sc->cam_scsi_sense.opcode = REQUEST_SENSE;
1087 	sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY;
1088 
1089 #define	SOFT_CACHE_SIZE 0x40
1090 	sc->data_ccb = (union ccb *)malloc(sizeof(union ccb));
1091 	if (sc->data_ccb == NULL)
1092 		goto detach;
1093 	sc->data_ccb->csio.data_ptr = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(SOFT_CACHE_SIZE));
1094 	if (sc->data_ccb->csio.data_ptr == NULL)
1095 		goto detach;
1096 	sc->data_ccb->csio.dxfer_len = SOFT_CACHE_SIZE;
1097 
1098 	DPRINTF_UMASS(sc, UDMASS_GEN, "Attach finished\n");
1099 
1100 	/* register the device*/
1101 	if (umass_attach_dev(sc, device_get_unit(dev))) {
1102 		goto detach;
1103 	}
1104 
1105 	p_umsf = sc;
1106 	return (0);			/* success */
1107 
1108 detach:
1109 	(void)umass_detach(dev);
1110 	return (ENXIO);			/* failure */
1111 }
1112 
1113 static int
1114 umass_detach(device_t dev)
1115 {
1116 	struct umass_softc *sc = (struct umass_softc *)device_get_softc(dev);
1117 	unsigned int dev_unit = device_get_unit(dev);
1118 
1119 	DPRINTF_UMASS(sc, UDMASS_USB, "\n");
1120 
1121 	sc->sc_detach_status = TRUE;
1122 
1123 	/* teardown our statemachine */
1124 	usbd_transfer_unsetup(sc->sc_xfer, UMASS_T_MAX);
1125 
1126 	mtx_lock(&sc->sc_mtx);
1127 
1128 	/* cancel any leftover CCB's */
1129 	umass_cancel_ccb(sc);
1130 
1131 	mtx_lock(&sc->sc_umass_mtx);
1132 	if (sc->data_ccb != NULL) {
1133 		if (sc->data_ccb->csio.data_ptr != NULL) {
1134 			free((void*)sc->data_ccb->csio.data_ptr);
1135 			sc->data_ccb->csio.data_ptr = NULL;
1136 		}
1137 		free(sc->data_ccb);
1138 		sc->data_ccb = NULL;
1139 	}
1140 	mtx_unlock(&sc->sc_umass_mtx);
1141 
1142 	umass_detach_dev_sub(sc, dev_unit, 0);
1143 #if USB_SUPPORT_SD_HOT_PLUG
1144 	umass_task_check(1);
1145 #endif
1146 
1147 	mtx_unlock(&sc->sc_mtx);
1148 	sc->sc_detach_status = FALSE;
1149 	mtx_destroy(&sc->sc_mtx);
1150 	mtx_destroy(&sc->sc_umass_mtx);
1151 
1152 	p_umsf = NULL;
1153 	return (0);			/* success */
1154 }
1155 
1156 static void
1157 umass_init_shuttle(struct umass_softc *sc)
1158 {
1159 	struct usb_device_request req;
1160 	usb_error_t err;
1161 	uint8_t status[2] = {0, 0};
1162 
1163 	/*
1164 	 * The Linux driver does this, but no one can tell us what the
1165 	 * command does.
1166 	 */
1167 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
1168 	req.bRequest = 1;	/* XXX unknown command */
1169 	USETW(req.wValue, 0);
1170 	req.wIndex[0] = sc->sc_iface_no;
1171 	req.wIndex[1] = 0;
1172 	USETW(req.wLength, sizeof(status));
1173 	err = usbd_do_request(sc->sc_udev, NULL, &req, &status);
1174 	if (err)
1175 		DPRINTF_UMASS(sc, UDMASS_GEN, "request failed in %s %d, err=%d\n",
1176 	    __FUNCTION__, __LINE__, err);
1177 
1178 	DPRINTF_UMASS(sc, UDMASS_GEN, "Shuttle init returned 0x%02x%02x\n",
1179 	    status[0], status[1]);
1180 }
1181 
1182 /*
1183  * Generic functions to handle transfers
1184  */
1185 
1186 static void
1187 umass_transfer_start(struct umass_softc *sc, uint8_t xfer_index)
1188 {
1189 	DPRINTF_UMASS(sc, UDMASS_GEN, "transfer index = "
1190 	    "%d\n", xfer_index);
1191 
1192 	if (sc->sc_xfer[xfer_index]) {
1193 		sc->sc_last_xfer_index = xfer_index;
1194 		usbd_transfer_start(sc->sc_xfer[xfer_index]);
1195 	} else {
1196 		umass_cancel_ccb(sc);
1197 	}
1198 }
1199 
1200 static void
1201 umass_cancel_ccb(struct umass_softc *sc)
1202 {
1203 	union ccb *umass_ccb;
1204 
1205 	mtx_assert(&sc->sc_mtx, MA_OWNED);
1206 
1207 	umass_ccb = sc->sc_transfer.ccb;
1208 	sc->sc_transfer.ccb = NULL;
1209 	sc->sc_last_xfer_index = 0;
1210 
1211 	if (umass_ccb != NULL) {
1212 		(sc->sc_transfer.callback)
1213 		    (sc, umass_ccb, (sc->sc_transfer.data_len -
1214 		    sc->sc_transfer.actlen), STATUS_WIRE_FAILED);
1215 	}
1216 }
1217 
1218 static void
1219 umass_tr_error(struct usb_xfer *xfer, usb_error_t error)
1220 {
1221 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1222 
1223 	if (error != USB_ERR_CANCELLED) {
1224 
1225 		DPRINTF_UMASS(sc, UDMASS_GEN, "transfer error, %s -> "
1226 		    "reset\n", usbd_errstr(error));
1227 	}
1228 	umass_cancel_ccb(sc);
1229 }
1230 
1231 /*
1232  *return 0: find the corresponding LUN;
1233  *		 1: find the SBC Direct-access;
1234  *		 -1: did not find the LUN.
1235  */
1236 static int
1237 umass_scsi_inquiry_data(struct umass_softc *sc, void *data, int len)
1238 {
1239 	struct scsiresp_inquiry_s *cur_i;
1240 	uint8_t pdt;
1241 	uint8_t rmb;
1242 	int is_dir;
1243 	char *name;
1244 
1245 	if (len != SCSIRESP_INQUIRY_SIZEOF)
1246 		return (-1);
1247 
1248 	is_dir = 0;
1249 	cur_i = (struct scsiresp_inquiry_s *)data;
1250 
1251 	pdt = SCSI_GET_INQUIRY_PDT(cur_i->qualtype);
1252 	rmb = SCSI_GET_INQUIRY_RMB(cur_i->flags1);
1253 	switch (pdt) {
1254 	case T_DIRECT:
1255 		name = "SBC Direct-access";
1256 		is_dir = 1;
1257 		break;
1258 	case T_CDROM:
1259 		name = "CD-ROM";
1260 		break;
1261 	case T_OPTICAL:
1262 		name = "Optical memory";
1263 		break;
1264 	case T_RBC:
1265 		name = "RBC Direct-access";
1266 		break;
1267 	default:
1268 		name = "PDT out of scope";
1269 		break;
1270 	}
1271 	DPRINTF_UMASS(sc, UDMASS_BBB, "SCSI: LUN-%d %s %s\n", sc->sc_transfer.lun, name,
1272 		    (rmb ? "Removable" : "Not Removable"));
1273 
1274 	(void)name;
1275 	(void)rmb; /* this is for clearing warning */
1276 	return (is_dir);
1277 }
1278 
1279 /*
1280  * BBB protocol specific functions
1281  */
1282 
1283 static void
1284 umass_t_bbb_reset1_callback(struct usb_xfer *xfer, usb_error_t error)
1285 {
1286 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1287 	struct usb_device_request req;
1288 	struct usb_page_cache *pc;
1289 
1290 	switch (USB_GET_STATE(xfer)) {
1291 	case USB_ST_TRANSFERRED:
1292 		umass_transfer_start(sc, UMASS_T_BBB_RESET2);
1293 		return;
1294 
1295 	case USB_ST_SETUP:
1296 		/*
1297 		 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
1298 		 *
1299 		 * For Reset Recovery the host shall issue in the following order:
1300 		 * a) a Bulk-Only Mass Storage Reset
1301 		 * b) a Clear Feature HALT to the Bulk-In endpoint
1302 		 * c) a Clear Feature HALT to the Bulk-Out endpoint
1303 		 *
1304 		 * This is done in 3 steps, using 3 transfers:
1305 		 * UMASS_T_BBB_RESET1
1306 		 * UMASS_T_BBB_RESET2
1307 		 * UMASS_T_BBB_RESET3
1308 		 */
1309 
1310 		DPRINTF_UMASS(sc, UDMASS_BBB, "BBB reset!\n");
1311 
1312 		req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1313 		req.bRequest = UR_BBB_RESET;	/* bulk only reset */
1314 		USETW(req.wValue, 0);
1315 		req.wIndex[0] = sc->sc_iface_no;
1316 		req.wIndex[1] = 0;
1317 		USETW(req.wLength, 0);
1318 
1319 		pc = usbd_xfer_get_frame(xfer, 0);
1320 		usbd_copy_in(pc, 0, &req, sizeof(req));
1321 
1322 		usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
1323 		usbd_xfer_set_frames(xfer, 1);
1324 		usbd_transfer_submit(xfer);
1325 		return;
1326 
1327 	default:			/* Error */
1328 		umass_tr_error(xfer, error);
1329 		return;
1330 	}
1331 }
1332 
1333 static void
1334 umass_t_bbb_reset2_callback(struct usb_xfer *xfer, usb_error_t error)
1335 {
1336 	umass_t_bbb_data_clear_stall_callback(xfer, UMASS_T_BBB_RESET3,
1337 	    UMASS_T_BBB_DATA_READ, error);
1338 }
1339 
1340 static void
1341 umass_t_bbb_reset3_callback(struct usb_xfer *xfer, usb_error_t error)
1342 {
1343 	umass_t_bbb_data_clear_stall_callback(xfer, UMASS_T_BBB_COMMAND,
1344 	    UMASS_T_BBB_DATA_WRITE, error);
1345 }
1346 
1347 static void
1348 umass_t_bbb_data_clear_stall_callback(struct usb_xfer *xfer,
1349 	uint8_t next_xfer, uint8_t stall_xfer, usb_error_t error)
1350 {
1351 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1352 
1353 	switch (USB_GET_STATE(xfer)) {
1354 	case USB_ST_TRANSFERRED:
1355 tr_transferred:
1356 		umass_transfer_start(sc, next_xfer);
1357 		return;
1358 
1359 	case USB_ST_SETUP:
1360 		if (usbd_clear_stall_callback(xfer, sc->sc_xfer[stall_xfer])) {
1361 			goto tr_transferred;
1362 		}
1363 		return;
1364 
1365 	default:			/* Error */
1366 		umass_tr_error(xfer, error);
1367 		return;
1368 	}
1369 }
1370 
1371 static void
1372 umass_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
1373 {
1374 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1375 	struct usb_page_cache *pc;
1376 	uint32_t tag;
1377 	int ret;
1378 
1379 	switch (USB_GET_STATE(xfer)) {
1380 	case USB_ST_TRANSFERRED:
1381 		umass_transfer_start
1382 		    (sc, ((sc->sc_transfer.dir == DIR_IN) ? UMASS_T_BBB_DATA_READ :
1383 		    (sc->sc_transfer.dir == DIR_OUT) ? UMASS_T_BBB_DATA_WRITE :
1384 		    UMASS_T_BBB_STATUS));
1385 		return;
1386 
1387 	case USB_ST_SETUP:
1388 
1389 		sc->sc_status_try = 0;
1390 
1391 		/*
1392 		 * the initial value is not important,
1393 		 * as long as the values are unique:
1394 		 */
1395 		tag = UGETDW(sc->cbw.dCBWTag) + 1;
1396 
1397 		USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
1398 		USETDW(sc->cbw.dCBWTag, tag);
1399 
1400 		/*
1401 		* dCBWDataTransferLength:
1402 		*   This field indicates the number of bytes of data that the host
1403 		*   intends to transfer on the IN or OUT Bulk endpoint(as indicated by
1404 		*   the Direction bit) during the execution of this command. If this
1405 		*   field is set to 0, the device will expect that no data will be
1406 		*   transferred IN or OUT during this command, regardless of the value
1407 		*   of the Direction bit defined in dCBWFlags.
1408 		*/
1409 		USETDW(sc->cbw.dCBWDataTransferLength, sc->sc_transfer.data_len);
1410 
1411 		/*
1412 		* dCBWFlags:
1413 		* The bits of the Flags field are defined as follows:
1414 		*	 Bits 0-6  reserved
1415 		*	 Bit  7	Direction - this bit shall be ignored if the
1416 		*						dCBWDataTransferLength field is zero.
1417 		*				0 = data Out from host to device
1418 		*				1 = data In from device to host
1419 		*/
1420 		sc->cbw.bCBWFlags = ((sc->sc_transfer.dir == DIR_IN) ?
1421 		    CBWFLAGS_IN : CBWFLAGS_OUT);
1422 		sc->cbw.bCBWLUN = sc->sc_transfer.lun;
1423 
1424 		if (sc->sc_transfer.cmd_len > sizeof(sc->cbw.CBWCDB)) {
1425 			sc->sc_transfer.cmd_len = sizeof(sc->cbw.CBWCDB);
1426 			DPRINTF_UMASS(sc, UDMASS_BBB, "Truncating long command!\n");
1427 		}
1428 		sc->cbw.bCDBLength = sc->sc_transfer.cmd_len;
1429 
1430 		/* copy SCSI command data */
1431 		ret = memcpy_s(sc->cbw.CBWCDB, CBWCDBLENGTH,
1432 			sc->sc_transfer.cmd_data, sc->sc_transfer.cmd_len);
1433 		if (ret != EOK) {
1434 			DPRINTF_UMASS(sc, UDMASS_BBB, "memcpy_s fail, %d\n", ret);
1435 			return;
1436 		}
1437 
1438 		/* clear remaining command area */
1439 		(void)memset_s(sc->cbw.CBWCDB + sc->sc_transfer.cmd_len,
1440 		    sizeof(sc->cbw.CBWCDB) - sc->sc_transfer.cmd_len, 0,
1441 		    sizeof(sc->cbw.CBWCDB) - sc->sc_transfer.cmd_len);
1442 
1443 		DIF(UDMASS_BBB,  umass_bbb_dump_cbw(sc, &sc->cbw));
1444 
1445 		pc = usbd_xfer_get_frame(xfer, 0);
1446 		usbd_copy_in(pc, 0, &sc->cbw, sizeof(sc->cbw));
1447 		usbd_xfer_set_frame_len(xfer, 0, sizeof(sc->cbw));
1448 
1449 		usbd_transfer_submit(xfer);
1450 
1451 		return;
1452 
1453 	default:			/* Error */
1454 		umass_tr_error(xfer, error);
1455 		return;
1456 	}
1457 }
1458 
1459 static void
1460 umass_t_bbb_data_callback(struct usb_xfer *xfer, usb_error_t error,
1461 	uint8_t xfer_index)
1462 {
1463 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1464 	uint32_t max_bulk = usbd_xfer_max_len(xfer);
1465 	int actlen, sumlen;
1466 
1467 	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
1468 
1469 	switch (USB_GET_STATE(xfer)) {
1470 	case USB_ST_TRANSFERRED:
1471 		sc->sc_transfer.data_rem -= actlen;
1472 		sc->sc_transfer.data_ptr += actlen;
1473 		sc->sc_transfer.actlen += actlen;
1474 
1475 		if (actlen < sumlen) {
1476 			/* short transfer */
1477 			sc->sc_transfer.data_rem = 0;
1478 		}
1479 	case USB_ST_SETUP:
1480 		DPRINTF_UMASS(sc, UDMASS_BBB, "max_bulk=%u, data_rem=%u\n",
1481 		    max_bulk, sc->sc_transfer.data_rem);
1482 
1483 		if (sc->sc_transfer.data_rem == 0) {
1484 			umass_transfer_start(sc, UMASS_T_BBB_STATUS);
1485 			return;
1486 		}
1487 		if (max_bulk > sc->sc_transfer.data_rem) {
1488 			max_bulk = sc->sc_transfer.data_rem;
1489 		}
1490 		usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
1491 
1492 		usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
1493 		    max_bulk);
1494 
1495 		usbd_transfer_submit(xfer);
1496 		return;
1497 
1498 	default:			/* Error */
1499 		if (error == USB_ERR_CANCELLED) {
1500 			umass_tr_error(xfer, error);
1501 		} else {
1502 			umass_transfer_start(sc, xfer_index);
1503 		}
1504 		return;
1505 	}
1506 }
1507 
1508 static void
1509 umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
1510 {
1511 	umass_t_bbb_data_callback(xfer, error, UMASS_T_BBB_DATA_RD_CS);
1512 }
1513 
1514 static void
1515 umass_t_bbb_data_rd_cs_callback(struct usb_xfer *xfer, usb_error_t error)
1516 {
1517 	umass_t_bbb_data_clear_stall_callback(xfer, UMASS_T_BBB_STATUS,
1518 	    UMASS_T_BBB_DATA_READ, error);
1519 }
1520 
1521 static void
1522 umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
1523 {
1524 	umass_t_bbb_data_callback(xfer, error, UMASS_T_BBB_DATA_WR_CS);
1525 }
1526 
1527 static void
1528 umass_t_bbb_data_wr_cs_callback(struct usb_xfer *xfer, usb_error_t error)
1529 {
1530 	umass_t_bbb_data_clear_stall_callback(xfer, UMASS_T_BBB_STATUS,
1531 	    UMASS_T_BBB_DATA_WRITE, error);
1532 }
1533 
1534 static void
1535 umass_t_bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
1536 {
1537 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1538 	union ccb *umass_ccb = sc->sc_transfer.ccb;
1539 	struct usb_page_cache *pc;
1540 	uint32_t residue;
1541 	int actlen;
1542 
1543 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1544 
1545 	switch (USB_GET_STATE(xfer)) {
1546 	case USB_ST_TRANSFERRED:
1547 
1548 		/*
1549 		 * Do a full reset if there is something wrong with the CSW:
1550 		 */
1551 		sc->sc_status_try = 1;
1552 
1553 		/* Zero missing parts of the CSW: */
1554 
1555 		if (actlen < (int)sizeof(sc->csw)) {
1556 			(void)memset_s(&sc->csw, sizeof(sc->csw), 0, sizeof(sc->csw));
1557 		}
1558 
1559 		pc = usbd_xfer_get_frame(xfer, 0);
1560 
1561 		usbd_copy_out(pc, 0, &sc->csw, actlen);
1562 
1563 		DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw));
1564 
1565 		residue = UGETDW(sc->csw.dCSWDataResidue);
1566 
1567 		if ((!residue) || (sc->sc_quirks & IGNORE_RESIDUE)) {
1568 			residue = (sc->sc_transfer.data_len -
1569 			    sc->sc_transfer.actlen);
1570 		}
1571 		if (residue > sc->sc_transfer.data_len) {
1572 			DPRINTF_UMASS(sc, UDMASS_BBB, "truncating residue from %d "
1573 			    "to %d bytes\n", residue, sc->sc_transfer.data_len);
1574 			residue = sc->sc_transfer.data_len;
1575 		}
1576 		/* translate weird command-status signatures: */
1577 		if (sc->sc_quirks & WRONG_CSWSIG) {
1578 
1579 			uint32_t temp = UGETDW(sc->csw.dCSWSignature);
1580 
1581 			if ((temp == CSWSIGNATURE_OLYMPUS_C1) ||
1582 			    (temp == CSWSIGNATURE_IMAGINATION_DBX1)) {
1583 				USETDW(sc->csw.dCSWSignature, CSWSIGNATURE);
1584 			}
1585 		}
1586 		/* check CSW and handle eventual error */
1587 		if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) {
1588 			DPRINTF_UMASS(sc, UDMASS_BBB, "bad CSW signature 0x%08x != 0x%08x\n",
1589 			    UGETDW(sc->csw.dCSWSignature), CSWSIGNATURE);
1590 			/*
1591 			 * Invalid CSW: Wrong signature or wrong tag might
1592 			 * indicate that we lost synchronization. Reset the
1593 			 * device.
1594 			 */
1595 			goto tr_error;
1596 		} else if (UGETDW(sc->csw.dCSWTag) != UGETDW(sc->cbw.dCBWTag)) {
1597 			DPRINTF_UMASS(sc, UDMASS_BBB, "Invalid CSW: tag 0x%08x should be "
1598 			    "0x%08x\n", UGETDW(sc->csw.dCSWTag),
1599 			    UGETDW(sc->cbw.dCBWTag));
1600 			goto tr_error;
1601 		} else if (sc->csw.bCSWStatus > CSWSTATUS_PHASE) {
1602 			DPRINTF_UMASS(sc, UDMASS_BBB, "Invalid CSW: status %d > %d\n",
1603 			    sc->csw.bCSWStatus, CSWSTATUS_PHASE);
1604 			goto tr_error;
1605 		} else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) {
1606 			DPRINTF_UMASS(sc, UDMASS_BBB, "Phase error, residue = "
1607 			    "%d\n", residue);
1608 			goto tr_error;
1609 		} else if (sc->sc_transfer.actlen > sc->sc_transfer.data_len) {
1610 			DPRINTF_UMASS(sc, UDMASS_BBB, "Buffer overrun %d > %d\n",
1611 			    sc->sc_transfer.actlen, sc->sc_transfer.data_len);
1612 			goto tr_error;
1613 		} else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) {
1614 			DPRINTF_UMASS(sc, UDMASS_BBB, "Command failed, residue = "
1615 			    "%d\n", residue);
1616 
1617 			sc->sc_transfer.ccb = NULL;
1618 
1619 			sc->sc_last_xfer_index = UMASS_T_BBB_COMMAND;
1620 
1621 			(sc->sc_transfer.callback)
1622 			    (sc, umass_ccb, residue, STATUS_CMD_FAILED);
1623 		} else {
1624 			sc->sc_transfer.ccb = NULL;
1625 
1626 			sc->sc_last_xfer_index = UMASS_T_BBB_COMMAND;
1627 
1628 			(sc->sc_transfer.callback)
1629 			    (sc, umass_ccb, residue, STATUS_CMD_OK);
1630 		}
1631 		return;
1632 
1633 	case USB_ST_SETUP:
1634 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1635 		usbd_transfer_submit(xfer);
1636 		return;
1637 
1638 	default:
1639 tr_error:
1640 		DPRINTF_UMASS(sc, UDMASS_BBB, "Failed to read CSW: %s, try %d\n",
1641 		    usbd_errstr(error), sc->sc_status_try);
1642 
1643 		if ((error == USB_ERR_CANCELLED) ||
1644 		    (sc->sc_status_try)) {
1645 			umass_tr_error(xfer, error);
1646 		} else {
1647 			sc->sc_status_try = 1;
1648 			umass_transfer_start(sc, UMASS_T_BBB_DATA_RD_CS);
1649 		}
1650 		return;
1651 	}
1652 }
1653 
1654 static int
1655 umass_command_start(struct umass_softc *sc, uint8_t dir,
1656     void *data_ptr, uint32_t data_len,
1657     uint32_t data_timeout, umass_callback_t *callback,
1658     union ccb *umass_ccb)
1659 {
1660 	if (sc->sc_detach_status)
1661 	{
1662 		PRINT_WARN("[%s][%d] usb is detaching\n",__FUNCTION__,__LINE__);
1663 		return (-1);
1664 	}
1665 
1666 	/*
1667 	 * NOTE: assumes that "sc->sc_transfer.cmd_data" and
1668 	 * "sc->sc_transfer.cmd_len" has been properly
1669 	 * initialized.
1670 	 */
1671 
1672 	sc->sc_transfer.dir = data_len ? dir : DIR_NONE;
1673 	sc->sc_transfer.data_ptr = (uint8_t *)data_ptr;
1674 	sc->sc_transfer.data_len = data_len;
1675 	sc->sc_transfer.data_rem = data_len;
1676 	sc->sc_transfer.data_timeout = (data_timeout + UMASS_TIMEOUT);
1677 
1678 	sc->sc_transfer.actlen = 0;
1679 	sc->sc_transfer.callback = callback;
1680 	sc->sc_transfer.ccb = umass_ccb;
1681 
1682 	if (sc->sc_xfer[sc->sc_last_xfer_index]) {
1683 		usbd_transfer_start(sc->sc_xfer[sc->sc_last_xfer_index]);
1684 	} else {
1685 		umass_cancel_ccb(sc);
1686 	}
1687 
1688 	(void)LOS_EventRead(&sc->sc_event, 0xFF,
1689 	    LOS_WAITMODE_OR | LOS_WAITMODE_CLR, 10 * LOSCFG_BASE_CORE_TICK_PER_SECOND); /* 10 seconds. */
1690 
1691 	return (0);
1692 }
1693 
1694 static uint8_t
1695 umass_bbb_get_max_lun(struct umass_softc *sc)
1696 {
1697 	struct usb_device_request req;
1698 	usb_error_t err;
1699 	uint8_t buf = 0;
1700 
1701 	/* The Get Max Lun command is a class-specific request. */
1702 	req.bmRequestType = UT_READ_CLASS_INTERFACE;
1703 	req.bRequest = UR_BBB_GET_MAX_LUN;
1704 	USETW(req.wValue, 0);
1705 	req.wIndex[0] = sc->sc_iface_no;
1706 	req.wIndex[1] = 0;
1707 	USETW(req.wLength, 1);
1708 
1709 	err = usbd_do_request(sc->sc_udev, NULL, &req, &buf);
1710 	if (err) {
1711 		buf = 0;
1712 
1713 		/* Device doesn't support Get Max Lun request. */
1714 		PRINTK("%s: Get Max Lun not supported (%s)\n",
1715 		    sc->sc_name, usbd_errstr(err));
1716 	}
1717 	return (buf);
1718 }
1719 
1720 /*
1721  * Command/Bulk/Interrupt (CBI) specific functions
1722  */
1723 
1724 static void
1725 umass_cbi_start_status(struct umass_softc *sc)
1726 {
1727 	if (sc->sc_xfer[UMASS_T_CBI_STATUS]) {
1728 		umass_transfer_start(sc, UMASS_T_CBI_STATUS);
1729 	} else {
1730 		union ccb *umass_ccb = sc->sc_transfer.ccb;
1731 
1732 		sc->sc_transfer.ccb = NULL;
1733 
1734 		sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND;
1735 
1736 		(sc->sc_transfer.callback)
1737 		    (sc, umass_ccb, (sc->sc_transfer.data_len -
1738 		    sc->sc_transfer.actlen), STATUS_CMD_UNKNOWN);
1739 	}
1740 }
1741 
1742 static void
1743 umass_t_cbi_reset1_callback(struct usb_xfer *xfer, usb_error_t error)
1744 {
1745 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1746 	struct usb_device_request req;
1747 	struct usb_page_cache *pc;
1748 	uint8_t buf[UMASS_CBI_DIAGNOSTIC_CMDLEN];
1749 
1750 	uint8_t i;
1751 
1752 	switch (USB_GET_STATE(xfer)) {
1753 	case USB_ST_TRANSFERRED:
1754 		umass_transfer_start(sc, UMASS_T_CBI_RESET2);
1755 		break;
1756 
1757 	case USB_ST_SETUP:
1758 		/*
1759 		 * Command Block Reset Protocol
1760 		 *
1761 		 * First send a reset request to the device. Then clear
1762 		 * any possibly stalled bulk endpoints.
1763 		 *
1764 		 * This is done in 3 steps, using 3 transfers:
1765 		 * UMASS_T_CBI_RESET1
1766 		 * UMASS_T_CBI_RESET2
1767 		 * UMASS_T_CBI_RESET3
1768 		 * UMASS_T_CBI_RESET4 (only if there is an interrupt endpoint)
1769 		 */
1770 
1771 		DPRINTF_UMASS(sc, UDMASS_CBI, "CBI reset!\n");
1772 
1773 		req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1774 		req.bRequest = UR_CBI_ADSC;
1775 		USETW(req.wValue, 0);
1776 		req.wIndex[0] = sc->sc_iface_no;
1777 		req.wIndex[1] = 0;
1778 		USETW(req.wLength, UMASS_CBI_DIAGNOSTIC_CMDLEN);
1779 
1780 		/*
1781 		 * The 0x1d code is the SEND DIAGNOSTIC command. To
1782 		 * distinguish between the two, the last 10 bytes of the CBL
1783 		 * is filled with 0xff (section 2.2 of the CBI
1784 		 * specification)
1785 		 */
1786 		buf[0] = 0x1d;		/* Command Block Reset */
1787 		buf[1] = 0x04;
1788 
1789 		for (i = 2; i < UMASS_CBI_DIAGNOSTIC_CMDLEN; i++) {
1790 			buf[i] = 0xff;
1791 		}
1792 
1793 		pc = usbd_xfer_get_frame(xfer, 0);
1794 		usbd_copy_in(pc, 0, &req, sizeof(req));
1795 		pc = usbd_xfer_get_frame(xfer, 1);
1796 		usbd_copy_in(pc, 0, buf, sizeof(buf));
1797 
1798 		usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
1799 		usbd_xfer_set_frame_len(xfer, 1, sizeof(buf));
1800 		usbd_xfer_set_frames(xfer, 2);
1801 		usbd_transfer_submit(xfer);
1802 		break;
1803 
1804 	default:			/* Error */
1805 		if (error == USB_ERR_CANCELLED)
1806 			umass_tr_error(xfer, error);
1807 		else
1808 			umass_transfer_start(sc, UMASS_T_CBI_RESET2);
1809 		break;
1810 	}
1811 }
1812 
1813 static void
1814 umass_t_cbi_reset2_callback(struct usb_xfer *xfer, usb_error_t error)
1815 {
1816 	umass_t_cbi_data_clear_stall_callback(xfer, UMASS_T_CBI_RESET3,
1817 	    UMASS_T_CBI_DATA_READ, error);
1818 }
1819 
1820 static void
1821 umass_t_cbi_reset3_callback(struct usb_xfer *xfer, usb_error_t error)
1822 {
1823 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1824 
1825 	umass_t_cbi_data_clear_stall_callback
1826 	    (xfer, (sc->sc_xfer[UMASS_T_CBI_RESET4] &&
1827 	    sc->sc_xfer[UMASS_T_CBI_STATUS]) ?
1828 	    UMASS_T_CBI_RESET4 : UMASS_T_CBI_COMMAND,
1829 	    UMASS_T_CBI_DATA_WRITE, error);
1830 }
1831 
1832 static void
1833 umass_t_cbi_reset4_callback(struct usb_xfer *xfer, usb_error_t error)
1834 {
1835 	umass_t_cbi_data_clear_stall_callback(xfer, UMASS_T_CBI_COMMAND,
1836 	    UMASS_T_CBI_STATUS, error);
1837 }
1838 
1839 static void
1840 umass_t_cbi_data_clear_stall_callback(struct usb_xfer *xfer,
1841     uint8_t next_xfer, uint8_t stall_xfer, usb_error_t error)
1842 {
1843 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1844 
1845 	switch (USB_GET_STATE(xfer)) {
1846 	case USB_ST_TRANSFERRED:
1847 tr_transferred:
1848 		if (next_xfer == UMASS_T_CBI_STATUS) {
1849 			umass_cbi_start_status(sc);
1850 		} else {
1851 			umass_transfer_start(sc, next_xfer);
1852 		}
1853 		break;
1854 
1855 	case USB_ST_SETUP:
1856 		if (usbd_clear_stall_callback(xfer, sc->sc_xfer[stall_xfer])) {
1857 			goto tr_transferred;	/* should not happen */
1858 		}
1859 		break;
1860 
1861 	default:			/* Error */
1862 		umass_tr_error(xfer, error);
1863 		break;
1864 	}
1865 }
1866 
1867 static void
1868 umass_t_cbi_command_callback(struct usb_xfer *xfer, usb_error_t error)
1869 {
1870 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1871 	union ccb *umass_ccb = sc->sc_transfer.ccb;
1872 	struct usb_device_request req;
1873 	struct usb_page_cache *pc;
1874 
1875 	switch (USB_GET_STATE(xfer)) {
1876 	case USB_ST_TRANSFERRED:
1877 
1878 		if (sc->sc_transfer.dir == DIR_NONE) {
1879 			umass_cbi_start_status(sc);
1880 		} else {
1881 			umass_transfer_start
1882 			    (sc, (sc->sc_transfer.dir == DIR_IN) ?
1883 			    UMASS_T_CBI_DATA_READ : UMASS_T_CBI_DATA_WRITE);
1884 		}
1885 		break;
1886 
1887 	case USB_ST_SETUP:
1888 
1889 		if (umass_ccb) {
1890 
1891 			/*
1892 				 * do a CBI transfer with cmd_len bytes from
1893 				 * cmd_data, possibly a data phase of data_len
1894 				 * bytes from/to the device and finally a status
1895 				 * read phase.
1896 				 */
1897 
1898 			req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1899 			req.bRequest = UR_CBI_ADSC;
1900 			USETW(req.wValue, 0);
1901 			req.wIndex[0] = sc->sc_iface_no;
1902 			req.wIndex[1] = 0;
1903 			req.wLength[0] = sc->sc_transfer.cmd_len;
1904 			req.wLength[1] = 0;
1905 
1906 			pc = usbd_xfer_get_frame(xfer, 0);
1907 			usbd_copy_in(pc, 0, &req, sizeof(req));
1908 			pc = usbd_xfer_get_frame(xfer, 1);
1909 			usbd_copy_in(pc, 0, sc->sc_transfer.cmd_data,
1910 			    sc->sc_transfer.cmd_len);
1911 
1912 			usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
1913 			usbd_xfer_set_frame_len(xfer, 1, sc->sc_transfer.cmd_len);
1914 			usbd_xfer_set_frames(xfer,
1915 			    sc->sc_transfer.cmd_len ? 2 : 1);
1916 
1917 			DIF(UDMASS_CBI,
1918 			    umass_cbi_dump_cmd(sc,
1919 			    sc->sc_transfer.cmd_data,
1920 			    sc->sc_transfer.cmd_len));
1921 
1922 			usbd_transfer_submit(xfer);
1923 		}
1924 		break;
1925 
1926 	default:			/* Error */
1927 		/*
1928 		 * STALL on the control pipe can be result of the command error.
1929 		 * Attempt to clear this STALL same as for bulk pipe also
1930 		 * results in command completion interrupt, but ASC/ASCQ there
1931 		 * look like not always valid, so don't bother about it.
1932 		 */
1933 		if ((error == USB_ERR_STALLED) ||
1934 		    (sc->sc_transfer.callback == &umass_cam_cb)) {
1935 			sc->sc_transfer.ccb = NULL;
1936 			(sc->sc_transfer.callback)
1937 			    (sc, umass_ccb, sc->sc_transfer.data_len,
1938 			    STATUS_CMD_UNKNOWN);
1939 		} else {
1940 			umass_tr_error(xfer, error);
1941 			/* skip reset */
1942 			sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND;
1943 		}
1944 		break;
1945 	}
1946 }
1947 
1948 static void
1949 umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
1950 {
1951 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
1952 	uint32_t max_bulk = usbd_xfer_max_len(xfer);
1953 	int actlen, sumlen;
1954 
1955 	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
1956 
1957 	switch (USB_GET_STATE(xfer)) {
1958 	case USB_ST_TRANSFERRED:
1959 		sc->sc_transfer.data_rem -= actlen;
1960 		sc->sc_transfer.data_ptr += actlen;
1961 		sc->sc_transfer.actlen += actlen;
1962 
1963 		if (actlen < sumlen) {
1964 			/* short transfer */
1965 			sc->sc_transfer.data_rem = 0;
1966 		}
1967 	case USB_ST_SETUP:
1968 		DPRINTF_UMASS(sc, UDMASS_CBI, "max_bulk=%d, data_rem=%d\n",
1969 		    max_bulk, sc->sc_transfer.data_rem);
1970 
1971 		if (sc->sc_transfer.data_rem == 0) {
1972 			umass_cbi_start_status(sc);
1973 			break;
1974 		}
1975 		if (max_bulk > sc->sc_transfer.data_rem) {
1976 			max_bulk = sc->sc_transfer.data_rem;
1977 		}
1978 		usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
1979 
1980 		usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
1981 		    max_bulk);
1982 
1983 		usbd_transfer_submit(xfer);
1984 		break;
1985 
1986 	default:			/* Error */
1987 		if ((error == USB_ERR_CANCELLED) ||
1988 		    (sc->sc_transfer.callback != &umass_cam_cb)) {
1989 			umass_tr_error(xfer, error);
1990 		} else {
1991 			umass_transfer_start(sc, UMASS_T_CBI_DATA_RD_CS);
1992 		}
1993 		break;
1994 	}
1995 }
1996 
1997 static void
1998 umass_t_cbi_data_rd_cs_callback(struct usb_xfer *xfer, usb_error_t error)
1999 {
2000 	umass_t_cbi_data_clear_stall_callback(xfer, UMASS_T_CBI_STATUS,
2001 	    UMASS_T_CBI_DATA_READ, error);
2002 }
2003 
2004 static void
2005 umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
2006 {
2007 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
2008 	uint32_t max_bulk = usbd_xfer_max_len(xfer);
2009 	int actlen, sumlen;
2010 
2011 	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
2012 
2013 	switch (USB_GET_STATE(xfer)) {
2014 	case USB_ST_TRANSFERRED:
2015 		sc->sc_transfer.data_rem -= actlen;
2016 		sc->sc_transfer.data_ptr += actlen;
2017 		sc->sc_transfer.actlen += actlen;
2018 
2019 		if (actlen < sumlen) {
2020 			/* short transfer */
2021 			sc->sc_transfer.data_rem = 0;
2022 		}
2023 	case USB_ST_SETUP:
2024 		DPRINTF_UMASS(sc, UDMASS_CBI, "max_bulk=%d, data_rem=%d\n",
2025 		    max_bulk, sc->sc_transfer.data_rem);
2026 
2027 		if (sc->sc_transfer.data_rem == 0) {
2028 			umass_cbi_start_status(sc);
2029 			break;
2030 		}
2031 		if (max_bulk > sc->sc_transfer.data_rem) {
2032 			max_bulk = sc->sc_transfer.data_rem;
2033 		}
2034 		usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
2035 
2036 		usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
2037 		    max_bulk);
2038 
2039 		usbd_transfer_submit(xfer);
2040 		break;
2041 
2042 	default:			/* Error */
2043 		if ((error == USB_ERR_CANCELLED) ||
2044 		    (sc->sc_transfer.callback != &umass_cam_cb)) {
2045 			umass_tr_error(xfer, error);
2046 		} else {
2047 			umass_transfer_start(sc, UMASS_T_CBI_DATA_WR_CS);
2048 		}
2049 		break;
2050 	}
2051 }
2052 
2053 static void
2054 umass_t_cbi_data_wr_cs_callback(struct usb_xfer *xfer, usb_error_t error)
2055 {
2056 	umass_t_cbi_data_clear_stall_callback(xfer, UMASS_T_CBI_STATUS,
2057 	    UMASS_T_CBI_DATA_WRITE, error);
2058 }
2059 
2060 static void
2061 umass_t_cbi_status_callback(struct usb_xfer *xfer, usb_error_t error)
2062 {
2063 	struct umass_softc *sc = (struct umass_softc *)usbd_xfer_softc(xfer);
2064 	union ccb *umass_ccb = sc->sc_transfer.ccb;
2065 	struct usb_page_cache *pc;
2066 	uint32_t residue;
2067 	uint8_t status;
2068 	int actlen;
2069 
2070 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
2071 
2072 	switch (USB_GET_STATE(xfer)) {
2073 	case USB_ST_TRANSFERRED:
2074 
2075 		if (actlen < (int)sizeof(sc->sbl)) {
2076 			goto tr_setup;
2077 		}
2078 		pc = usbd_xfer_get_frame(xfer, 0);
2079 		usbd_copy_out(pc, 0, &sc->sbl, sizeof(sc->sbl));
2080 
2081 		residue = (sc->sc_transfer.data_len -
2082 		    sc->sc_transfer.actlen);
2083 
2084 		/* dissect the information in the buffer */
2085 
2086 		if (sc->sc_proto & UMASS_PROTO_UFI) {
2087 
2088 			/*
2089 			 * Section 3.4.3.1.3 specifies that the UFI command
2090 			 * protocol returns an ASC and ASCQ in the interrupt
2091 			 * data block.
2092 			 */
2093 
2094 			DPRINTF_UMASS(sc, UDMASS_CBI, "UFI CCI, ASC = 0x%02x, "
2095 			    "ASCQ = 0x%02x\n", sc->sbl.ufi.asc,
2096 			    sc->sbl.ufi.ascq);
2097 
2098 			status = (((sc->sbl.ufi.asc == 0) &&
2099 			    (sc->sbl.ufi.ascq == 0)) ?
2100 			    STATUS_CMD_OK : STATUS_CMD_FAILED);
2101 
2102 			sc->sc_transfer.ccb = NULL;
2103 
2104 			sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND;
2105 
2106 			(sc->sc_transfer.callback)
2107 			    (sc, umass_ccb, residue, status);
2108 
2109 			break;
2110 
2111 		} else {
2112 
2113 			/* Command Interrupt Data Block */
2114 
2115 			DPRINTF_UMASS(sc, UDMASS_CBI, "type=0x%02x, value=0x%02x\n",
2116 			    sc->sbl.common.type, sc->sbl.common.value);
2117 
2118 			if (sc->sbl.common.type == IDB_TYPE_CCI) {
2119 
2120 				status = (sc->sbl.common.value & IDB_VALUE_STATUS_MASK);
2121 
2122 				status = ((status == IDB_VALUE_PASS) ? STATUS_CMD_OK :
2123 				    (status == IDB_VALUE_FAIL) ? STATUS_CMD_FAILED :
2124 				    (status == IDB_VALUE_PERSISTENT) ? STATUS_CMD_FAILED :
2125 				    STATUS_WIRE_FAILED);
2126 
2127 				sc->sc_transfer.ccb = NULL;
2128 
2129 				sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND;
2130 
2131 				(sc->sc_transfer.callback)
2132 				    (sc, umass_ccb, residue, status);
2133 
2134 				break;
2135 			}
2136 		}
2137 
2138 		/* fallthrough */
2139 
2140 	case USB_ST_SETUP:
2141 tr_setup:
2142 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
2143 		usbd_transfer_submit(xfer);
2144 		break;
2145 
2146 	default:			/* Error */
2147 		DPRINTF_UMASS(sc, UDMASS_CBI, "Failed to read CSW: %s\n",
2148 		    usbd_errstr(error));
2149 		umass_tr_error(xfer, error);
2150 		break;
2151 	}
2152 }
2153 
2154 /* umass_cam_cb
2155  *	finalise a completed CAM command
2156  */
2157 
2158 static void
2159 umass_cam_cb(struct umass_softc *sc, union ccb *umass_ccb, uint32_t residue,
2160 	uint8_t status)
2161 {
2162 	umass_ccb->csio.resid = residue;
2163 	umass_ccb->csio.status = status;
2164 
2165 	switch (status) {
2166 	case STATUS_CMD_OK:
2167 		(void)LOS_EventWrite(&sc->sc_event, 0x01);
2168 		break;
2169 
2170 	case STATUS_CMD_UNKNOWN:
2171 	case STATUS_CMD_FAILED:
2172 		/* fetch sense data */
2173 		(void)LOS_EventWrite(&sc->sc_event, 0x02);
2174 		break;
2175 
2176 	default:
2177 		(void)LOS_EventWrite(&sc->sc_event, 0x04);
2178 		break;
2179 	}
2180 }
2181 
2182 /*
2183  * SCSI specific functions
2184  */
2185 
2186 static uint8_t
2187 umass_scsi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
2188 	uint8_t cmd_len)
2189 {
2190 	int ret;
2191 
2192 	if ((cmd_len == 0) ||
2193 		(cmd_len > sizeof(sc->sc_transfer.cmd_data))) {
2194 		DPRINTF_UMASS(sc, UDMASS_SCSI, "Invalid command "
2195 		    "length: %d bytes\n", cmd_len);
2196 		return (0);		/* failure */
2197 	}
2198 	sc->sc_transfer.cmd_len = cmd_len;
2199 
2200 	switch (cmd_ptr[0]) {
2201 	case TEST_UNIT_READY:
2202 		if (sc->sc_quirks & NO_TEST_UNIT_READY) {
2203 			DPRINTF_UMASS(sc, UDMASS_SCSI, "Converted TEST_UNIT_READY "
2204 			    "to START_UNIT\n");
2205 			ret = memset_s(sc->sc_transfer.cmd_data, sizeof(sc->sc_transfer.cmd_data), 0, cmd_len);
2206 			if (ret != EOK) {
2207 				usb_err("memset_s failed!, ret:%d\n", ret);
2208 				return (0);
2209 			}
2210 			sc->sc_transfer.cmd_data[0] = START_STOP_UNIT;
2211 			sc->sc_transfer.cmd_data[4] = SSS_START;
2212 			return (1);
2213 		}
2214 		break;
2215 
2216 	case INQUIRY:
2217 		/*
2218 		 * some drives wedge when asked for full inquiry
2219 		 * information.
2220 		 */
2221 		if (sc->sc_quirks & FORCE_SHORT_INQUIRY) {
2222 			ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len);
2223 			if (ret != EOK) {
2224 				usb_err("memcpy_s failed!, ret:%d\n", ret);
2225 				return (0);
2226 			}
2227 			sc->sc_transfer.cmd_data[4] = SHORT_INQUIRY_LENGTH;
2228 			return (1);
2229 		}
2230 		break;
2231 	}
2232 
2233 	ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len);
2234 	if (ret != EOK) {
2235 		usb_err("memcpy_s failed!, ret:%d\n", ret);
2236 		return (0);
2237 	}
2238 
2239 	return (1);
2240 }
2241 
2242 static uint8_t
2243 umass_rbc_transform(struct umass_softc *sc, uint8_t *cmd_ptr, uint8_t cmd_len)
2244 {
2245 	int ret;
2246 
2247 	if ((cmd_len == 0) ||
2248 		(cmd_len > sizeof(sc->sc_transfer.cmd_data))) {
2249 		DPRINTF_UMASS(sc, UDMASS_SCSI, "Invalid command "
2250 		    "length: %d bytes\n", cmd_len);
2251 		return (0);		/* failure */
2252 	}
2253 	switch (cmd_ptr[0]) {
2254 	/* these commands are defined in RBC: */
2255 	case READ_10:
2256 	case READ_CAPACITY:
2257 	case START_STOP_UNIT:
2258 	case SYNCHRONIZE_CACHE:
2259 	case WRITE_10:
2260 	case 0x2f:			/* VERIFY_10 is absent from * scsi_all.h??? */
2261 	case INQUIRY:
2262 	case MODE_SELECT_10:
2263 	case MODE_SENSE_10:
2264 	case TEST_UNIT_READY:
2265 	case WRITE_BUFFER:
2266 		/*
2267 		 * The following commands are not listed in my copy of the
2268 		 * RBC specs. CAM however seems to want those, and at least
2269 		 * the Sony DSC device appears to support those as well
2270 		 */
2271 	case REQUEST_SENSE:
2272 	case PREVENT_ALLOW:
2273 
2274 		ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len);
2275 		if (ret != EOK) {
2276 			usb_err("memcpy_s failed!, ret:%d\n", ret);
2277 			return (0);
2278 		}
2279 
2280 		if ((sc->sc_quirks & RBC_PAD_TO_12) && (cmd_len < 12)) {
2281 			ret = memset_s(sc->sc_transfer.cmd_data + cmd_len,
2282 			    (size_t)(UMASS_MAX_CMDLEN - cmd_len), 0, (size_t)(12 - cmd_len));
2283 			if (ret != EOK){
2284 				usb_err("memset_s failed!, ret:%d\n", ret);
2285 				return (0);
2286 			}
2287 			cmd_len = 12;
2288 		}
2289 		sc->sc_transfer.cmd_len = cmd_len;
2290 		return (1);		/* sucess */
2291 
2292 		/* All other commands are not legal in RBC */
2293 	default:
2294 		DPRINTF_UMASS(sc, UDMASS_SCSI, "Unsupported RBC "
2295 		    "command 0x%02x\n", cmd_ptr[0]);
2296 		return (0);		/* failure */
2297 	}
2298 }
2299 
2300 static uint8_t
2301 umass_ufi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
2302     uint8_t cmd_len)
2303 {
2304 	int ret;
2305 
2306 	if ((cmd_len == 0) ||
2307 		(cmd_len > sizeof(sc->sc_transfer.cmd_data))) {
2308 		DPRINTF_UMASS(sc, UDMASS_SCSI, "Invalid command "
2309 		    "length: %d bytes\n", cmd_len);
2310 		return (0);		/* failure */
2311 	}
2312 	/* An UFI command is always 12 bytes in length */
2313 	sc->sc_transfer.cmd_len = UFI_COMMAND_LENGTH;
2314 
2315 	/* Zero the command data */
2316 	ret = memset_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, 0, UFI_COMMAND_LENGTH);
2317 	if (ret != EOK) {
2318 		usb_err("memset_s failed!, ret:%d\n", ret);
2319 		return (0);
2320 	}
2321 
2322 	switch (cmd_ptr[0]) {
2323 		/*
2324 		 * Commands of which the format has been verified. They
2325 		 * should work. Copy the command into the (zeroed out)
2326 		 * destination buffer.
2327 		 */
2328 	case TEST_UNIT_READY:
2329 		if (sc->sc_quirks & NO_TEST_UNIT_READY) {
2330 			/*
2331 			 * Some devices do not support this command. Start
2332 			 * Stop Unit should give the same results
2333 			 */
2334 			DPRINTF_UMASS(sc, UDMASS_UFI, "Converted TEST_UNIT_READY "
2335 			    "to START_UNIT\n");
2336 
2337 			sc->sc_transfer.cmd_data[0] = START_STOP_UNIT;
2338 			sc->sc_transfer.cmd_data[4] = SSS_START;
2339 			return (1);
2340 		}
2341 		break;
2342 
2343 	case REZERO_UNIT:
2344 	case REQUEST_SENSE:
2345 	case FORMAT_UNIT:
2346 	case INQUIRY:
2347 	case START_STOP_UNIT:
2348 	case SEND_DIAGNOSTIC:
2349 	case PREVENT_ALLOW:
2350 	case READ_CAPACITY:
2351 	case READ_10:
2352 	case WRITE_10:
2353 	case POSITION_TO_ELEMENT:	/* SEEK_10 */
2354 	case WRITE_AND_VERIFY:
2355 	case VERIFIED:
2356 	case MODE_SELECT_10:
2357 	case MODE_SENSE_10:
2358 	case READ_12:
2359 	case WRITE_12:
2360 	case READ_FORMAT_CAPACITIES:
2361 		break;
2362 
2363 		/*
2364 		 * SYNCHRONIZE_CACHE isn't supported by UFI, nor should it be
2365 		 * required for UFI devices, so it is appropriate to fake
2366 		 * success.
2367 		 */
2368 	case SYNCHRONIZE_CACHE:
2369 		return (2);
2370 
2371 	default:
2372 		DPRINTF_UMASS(sc, UDMASS_SCSI, "Unsupported UFI "
2373 		    "command 0x%02x\n", cmd_ptr[0]);
2374 		return (0);		/* failure */
2375 	}
2376 
2377 	ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len);
2378 	if (ret != EOK) {
2379 		usb_err("memcpy_s failed!, ret:%d\n", ret);
2380 		return (0);
2381 	}
2382 
2383 	return (1);			/* success */
2384 }
2385 
2386 /*
2387  * 8070i (ATAPI) specific functions
2388  */
2389 static uint8_t
2390 umass_atapi_transform(struct umass_softc *sc, uint8_t *cmd_ptr,
2391     uint8_t cmd_len)
2392 {
2393 	int ret;
2394 
2395 	if ((cmd_len == 0) ||
2396 		(cmd_len > sizeof(sc->sc_transfer.cmd_data))) {
2397 		DPRINTF_UMASS(sc, UDMASS_SCSI, "Invalid command "
2398 		    "length: %d bytes\n", cmd_len);
2399 		return (0);		/* failure */
2400 	}
2401 	/* An ATAPI command is always 12 bytes in length. */
2402 	sc->sc_transfer.cmd_len = ATAPI_COMMAND_LENGTH;
2403 
2404 	/* Zero the command data */
2405 	ret = memset_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, 0, ATAPI_COMMAND_LENGTH);
2406 	if (ret != EOK) {
2407 		usb_err("memset_s failed!, ret:%d\n", ret);
2408 		return (0);
2409 	}
2410 
2411 	switch (cmd_ptr[0]) {
2412 		/*
2413 		 * Commands of which the format has been verified. They
2414 		 * should work. Copy the command into the destination
2415 		 * buffer.
2416 		 */
2417 	case INQUIRY:
2418 		/*
2419 		 * some drives wedge when asked for full inquiry
2420 		 * information.
2421 		 */
2422 		if (sc->sc_quirks & FORCE_SHORT_INQUIRY) {
2423 			ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len);
2424 			if (ret != EOK) {
2425 				usb_err("memcpy_s failed!, ret:%d\n", ret);
2426 				return (0);
2427 			}
2428 			sc->sc_transfer.cmd_data[4] = SHORT_INQUIRY_LENGTH;
2429 			return (1);
2430 		}
2431 		break;
2432 
2433 	case TEST_UNIT_READY:
2434 		if (sc->sc_quirks & NO_TEST_UNIT_READY) {
2435 			DPRINTF_UMASS(sc, UDMASS_SCSI, "Converted TEST_UNIT_READY "
2436 			    "to START_UNIT\n");
2437 			sc->sc_transfer.cmd_data[0] = START_STOP_UNIT;
2438 			sc->sc_transfer.cmd_data[4] = SSS_START;
2439 			return (1);
2440 		}
2441 		break;
2442 
2443 	case REZERO_UNIT:
2444 	case REQUEST_SENSE:
2445 	case START_STOP_UNIT:
2446 	case SEND_DIAGNOSTIC:
2447 	case PREVENT_ALLOW:
2448 	case READ_CAPACITY:
2449 	case READ_10:
2450 	case WRITE_10:
2451 	case POSITION_TO_ELEMENT:	/* SEEK_10 */
2452 	case SYNCHRONIZE_CACHE:
2453 	case MODE_SELECT_10:
2454 	case MODE_SENSE_10:
2455 	case READ_BUFFER:
2456 	case 0x42:			/* READ_SUBCHANNEL */
2457 	case 0x43:			/* READ_TOC */
2458 	case 0x44:			/* READ_HEADER */
2459 	case 0x47:			/* PLAY_MSF (Play Minute/Second/Frame) */
2460 	case 0x48:			/* PLAY_TRACK */
2461 	case 0x49:			/* PLAY_TRACK_REL */
2462 	case 0x4b:			/* PAUSE */
2463 	case 0x51:			/* READ_DISK_INFO */
2464 	case 0x52:			/* READ_TRACK_INFO */
2465 	case 0x54:			/* SEND_OPC */
2466 	case 0x59:			/* READ_MASTER_CUE */
2467 	case 0x5b:			/* CLOSE_TR_SESSION */
2468 	case 0x5c:			/* READ_BUFFER_CAP */
2469 	case 0x5d:			/* SEND_CUE_SHEET */
2470 	case 0xa1:			/* BLANK */
2471 	case 0xa5:			/* PLAY_12 */
2472 	case 0xa6:			/* EXCHANGE_MEDIUM */
2473 	case 0xad:			/* READ_DVD_STRUCTURE */
2474 	case 0xbb:			/* SET_CD_SPEED */
2475 	case 0xe5:			/* READ_TRACK_INFO_PHILIPS */
2476 		break;
2477 
2478 	case READ_12:
2479 	case WRITE_12:
2480 	default:
2481 		DPRINTF_UMASS(sc, UDMASS_SCSI, "Unsupported ATAPI "
2482 		    "command 0x%02x - trying anyway\n",
2483 		    cmd_ptr[0]);
2484 		break;
2485 	}
2486 
2487 	ret = memcpy_s(sc->sc_transfer.cmd_data, UMASS_MAX_CMDLEN, cmd_ptr, cmd_len);
2488 	if (ret != EOK) {
2489 		usb_err("memcpy_s failed!, ret:%d\n", ret);
2490 		return (0);
2491 	}
2492 
2493 	return (1);			/* success */
2494 }
2495 
2496 static uint8_t
2497 umass_no_transform(struct umass_softc *sc, uint8_t *cmd,
2498 	uint8_t cmdlen)
2499 {
2500 	return (0);			/* failure */
2501 }
2502 
2503 #ifdef LOSCFG_USB_DEBUG
2504 static void
2505 umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw)
2506 {
2507 	uint8_t *c = cbw->CBWCDB;
2508 
2509 	uint32_t dlen = UGETDW(cbw->dCBWDataTransferLength);
2510 	uint32_t tag = UGETDW(cbw->dCBWTag);
2511 
2512 	uint8_t clen = cbw->bCDBLength;
2513 	uint8_t flags = cbw->bCBWFlags;
2514 	uint8_t lun = cbw->bCBWLUN;
2515 
2516 	DPRINTF_UMASS(sc, UDMASS_BBB, "CBW %d: cmd = %db "
2517 	    "(0x%02x%02x%02x%02x%02x%02x%s), "
2518 	    "data = %db, lun = %d, dir = %s\n",
2519 	    tag, clen,
2520 	    c[0], c[1], c[2], c[3], c[4], c[5], (clen > 6 ? "..." : ""),
2521 	    dlen, lun, (flags == CBWFLAGS_IN ? "in" :
2522 	    (flags == CBWFLAGS_OUT ? "out" : "<invalid>")));
2523 }
2524 
2525 static void
2526 umass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw)
2527 {
2528 	uint32_t sig = UGETDW(csw->dCSWSignature);
2529 	uint32_t tag = UGETDW(csw->dCSWTag);
2530 	uint32_t res = UGETDW(csw->dCSWDataResidue);
2531 	uint8_t status = csw->bCSWStatus;
2532 
2533 	DPRINTF_UMASS(sc, UDMASS_BBB, "CSW %d: sig = 0x%08x (%s), tag = 0x%08x, "
2534 	    "res = %d, status = 0x%02x (%s)\n",
2535 	    tag, sig, (sig == CSWSIGNATURE ? "valid" : "invalid"),
2536 	    tag, res,
2537 	    status, (status == CSWSTATUS_GOOD ? "good" :
2538 	    (status == CSWSTATUS_FAILED ? "failed" :
2539 	    (status == CSWSTATUS_PHASE ? "phase" : "<invalid>"))));
2540 }
2541 
2542 static void
2543 umass_cbi_dump_cmd(struct umass_softc *sc, void *cmd, uint8_t cmdlen)
2544 {
2545 	uint8_t *c = cmd;
2546 	uint8_t dir = sc->sc_transfer.dir;
2547 
2548 	DPRINTF_UMASS(sc, UDMASS_BBB, "cmd = %db "
2549 	    "(0x%02x%02x%02x%02x%02x%02x%s), "
2550 	    "data = %db, dir = %s\n",
2551 	    cmdlen,
2552 	    c[0], c[1], c[2], c[3], c[4], c[5], (cmdlen > 6 ? "..." : ""),
2553 	    sc->sc_transfer.data_len,
2554 	    (dir == DIR_IN ? "in" :
2555 	    (dir == DIR_OUT ? "out" :
2556 	    (dir == DIR_NONE ? "no data phase" : "<invalid>"))));
2557 }
2558 
2559 #endif
2560 
2561 #define	SCSI_INQ_LEN	0x24
2562 
2563 static uint8_t scsi_test_unit_ready[] = {
2564 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2565 };
2566 static uint8_t scsi_inquiry[] = {
2567 	0x12, 0x00, 0x00, 0x00, SCSI_INQ_LEN, 0x00
2568 };
2569 static uint8_t scsi_request_sense[] = {
2570 	0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
2571 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2572 };
2573 static uint8_t scsi_read_capacity[] = {
2574 	0x25, 0x00, 0x00, 0x00, 0x00,
2575 	0x00, 0x00, 0x00, 0x00, 0x00
2576 };
2577 
2578 static uint8_t scsi_read_capacity_16[] = {
2579 	0x9e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2580 	0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00
2581 };
2582 
2583 /* Description: Get a (possibly unaligned) 16-bit big endian value. */
2584 static inline uint16_t
2585 usbhost_getbe16(const uint8_t *val)
2586 {
2587 	return ((uint16_t)val[0] << 8 | (uint16_t)val[1]);
2588 }
2589 
2590 /* Description: Put a (possibly unaligned) 16-bit little endian value. */
2591 void
2592 usbhost_putle16(uint8_t *dest, uint16_t val)
2593 {
2594 	dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
2595 	dest[1] = val >> 8;
2596 }
2597 
2598 /* Description: Put a (possibly unaligned) 16-bit big endian value. */
2599 void
2600 usbhost_putbe16(uint8_t *dest, uint16_t val)
2601 {
2602 	dest[0] = val >> 8; /* Big endian means MS byte first in byte stream */
2603 	dest[1] = val & 0xff;
2604 }
2605 
2606 /* Description: Get a (possibly unaligned) 32-bit big endian value. */
2607 uint32_t
2608 usbhost_getbe32(const uint8_t *val)
2609 {
2610 	/* Big endian means MS halfword first in byte stream */
2611 	return ((uint32_t)usbhost_getbe16(val) << 16 |
2612 	    (uint32_t)usbhost_getbe16(&val[2]));
2613 }
2614 
2615 /* Description: Get a (possibly unaligned) 64-bit big endian value. */
2616 uint64_t
2617 usbhost_getbe64(const uint8_t *val)
2618 {
2619 	/* Big endian means MS halfword first in byte stream */
2620 	return ((uint64_t)usbhost_getbe32(val) << 32 |
2621 	    (uint64_t)usbhost_getbe32(&val[4]));
2622 }
2623 
2624 /* Description: Put a (possibly unaligned) 32-bit little endian value. */
2625 void
2626 usbhost_putle32(uint8_t *dest, uint32_t val)
2627 {
2628 	/* Little endian means LS halfword first in byte stream  */
2629 	usbhost_putle16(dest, (uint16_t)(val & 0xffff));
2630 	usbhost_putle16(dest+2, (uint16_t)(val >> 16));
2631 }
2632 
2633 /* Put a (possibly unaligned) 32-bit big endian value. */
2634 void
2635 usbhost_putbe32(uint8_t *dest, uint32_t val)
2636 {
2637 	/* Big endian means MS halfword first in byte stream */
2638 	usbhost_putbe16(dest, (uint16_t)(val >> 16));
2639 	usbhost_putbe16(dest+2, (uint16_t)(val & 0xffff));
2640 }
2641 
2642 /* Put a (possibly unaligned) 64-bit big endian value. */
2643 void
2644 usbhost_putbe64(uint8_t *dest, uint64_t val)
2645 {
2646 	/* Big endian means MS halfword first in byte stream */
2647 	usbhost_putbe32(dest, (uint32_t)(val >> 32));
2648 	usbhost_putbe32(dest+4, (uint32_t)(val & 0xffffffff));
2649 }
2650 
2651 void
2652 usbhost_readcdb16(uint64_t startsector, uint16_t blocksize,
2653     unsigned int nsectors, struct scsicmd_read16_s *cdb)
2654 {
2655 	struct scsicmd_read16_s *rd16 = (struct scsicmd_read16_s *)cdb;
2656 
2657 	/* Format the CDB */
2658 	rd16->opcode = SCSI_CMD_READ16;
2659 	usbhost_putbe64(rd16->lba, startsector);
2660 	usbhost_putbe32(rd16->xfrlen, nsectors);
2661 }
2662 
2663 void
2664 usbhost_readcdb10(size_t startsector, uint16_t blocksize,
2665     unsigned int nsectors, struct scsicmd_read10_s *cdb)
2666 {
2667 	struct scsicmd_read10_s *rd10 = (struct scsicmd_read10_s *)cdb;
2668 
2669 	/* Format the CDB */
2670 	rd10->opcode = SCSI_CMD_READ10;
2671 	usbhost_putbe32(rd10->lba, startsector);
2672 	usbhost_putbe16(rd10->xfrlen, nsectors);
2673 }
2674 
2675 void
2676 usbhost_writecbw16(uint64_t startsector, uint16_t blocksize,
2677     unsigned int nsectors, struct scsicmd_write16_s *cdb)
2678 {
2679 	struct scsicmd_write16_s *wr16 = (struct scsicmd_write16_s *)cdb;
2680 
2681 	wr16->opcode = SCSI_CMD_WRITE16;
2682 	usbhost_putbe64(wr16->lba, startsector);
2683 	usbhost_putbe32(wr16->xfrlen, nsectors);
2684 }
2685 
2686 void
2687 usbhost_writecbw10(size_t startsector, uint16_t blocksize,
2688     unsigned int nsectors, struct scsicmd_write10_s *cdb)
2689 {
2690 	struct scsicmd_write10_s *wr10 = (struct scsicmd_write10_s *)cdb;
2691 
2692 	wr10->opcode = SCSI_CMD_WRITE10;
2693 	usbhost_putbe32(wr10->lba, startsector);
2694 	usbhost_putbe16(wr10->xfrlen, nsectors);
2695 }
2696 
2697 int
2698 umass_test_unit_ready(struct umass_softc *sc)
2699 {
2700 	uint32_t status;
2701 	int32_t res;
2702 
2703 	if((sc == NULL) || (sc->data_ccb == NULL)) {
2704 		return (-1);
2705 	}
2706 
2707 	(void)umass_scsi_transform(sc, scsi_test_unit_ready, SCSICMD_TESTUNITREADY8_SIZEOF);
2708 	res = umass_command_start(sc, DIR_NONE, NULL, 0, 1000, umass_cam_cb, sc->data_ccb);
2709 	if (STATUS_CMD_OK != res) {
2710 		return (-1);
2711 	}
2712 
2713 	status = sc->data_ccb->csio.status;
2714 	if (status != STATUS_CMD_OK) {
2715 		return (-1);
2716 	}
2717 
2718 	return (0);
2719 }
2720 
2721 int
2722 umass_read_capacity_16(struct umass_softc *sc)
2723 {
2724 	struct scsiresp_readcapacity16_s resp;
2725 	uint32_t res;
2726 	int ret;
2727 
2728 	(void)umass_scsi_transform(sc, scsi_read_capacity_16, SCSICMD_READCAPACITY16_SIZEOF);
2729 	res = (uint32_t)umass_command_start(sc, DIR_IN, sc->data_ccb->csio.data_ptr,
2730 	    (uint32_t)SCSIRESP_READCAPACITY16_SIZEOF,
2731 	    (uint32_t)1000, umass_cam_cb, sc->data_ccb);
2732 	if (STATUS_CMD_OK != res) {
2733 		return (-1);
2734 	}
2735 
2736 	ret = memcpy_s((void *)&resp, sizeof(resp), sc->data_ccb->csio.data_ptr,
2737 	    SCSIRESP_READCAPACITY16_SIZEOF);
2738 	if (ret != EOK) {
2739 		usb_err("memcpy_s failed, %d\n", ret);
2740 		return (-1);
2741 	}
2742 
2743 	sc->info.sectornum= usbhost_getbe64(resp.lba) + 1;
2744 	sc->info.sectorsize= usbhost_getbe32(resp.blklen);
2745 
2746 	return (0);
2747 }
2748 
2749 int
2750 umass_read_capacity(struct umass_softc *sc)
2751 {
2752 	struct scsiresp_readcapacity10_s resp;
2753 	int32_t ret;
2754 
2755 	if ((sc == NULL) || (sc->data_ccb == NULL)) {
2756 		return (-1);
2757 	}
2758 
2759 	(void)umass_scsi_transform(sc, scsi_read_capacity, SCSICMD_READCAPACITY10_SIZEOF);
2760 	ret = umass_command_start(sc, DIR_IN, sc->data_ccb->csio.data_ptr,
2761 	    SCSIRESP_READCAPACITY10_SIZEOF,
2762 	    1000, umass_cam_cb, sc->data_ccb);
2763 	if (STATUS_CMD_OK != ret) {
2764 		return (-1);
2765 	}
2766 
2767 	ret = memcpy_s((void *)&resp, sizeof(resp), sc->data_ccb->csio.data_ptr,
2768 	    SCSIRESP_READCAPACITY10_SIZEOF);
2769 	if (ret != EOK) {
2770 		usb_err("memcpy_s failed, %d\n", ret);
2771 		return (-1);
2772 	}
2773 
2774 	/* The disk Capacity is bigger than 2T */
2775 	if (usbhost_getbe32(resp.lba) == 0xffffffff) {
2776 		ret = umass_read_capacity_16(sc);
2777 		if (ret != 0) {
2778 			usb_err("Read Capacity failed, %d\n", ret);
2779 			return (-1);
2780 		}
2781 		sc->sc_super_disk = TRUE;
2782 
2783 		return (0);
2784 	}
2785 
2786 	sc->info.sectornum= usbhost_getbe32(resp.lba) + 1;
2787 	sc->info.sectorsize= usbhost_getbe32(resp.blklen);
2788 	sc->sc_super_disk = FALSE;
2789 
2790 	return (0);
2791 }
2792 
2793 int
2794 umass_read10(struct umass_softc *sc, size_t startsector, uint16_t blocksize,
2795     unsigned int nsectors, unsigned char *buf)
2796 {
2797 	struct scsicmd_read10_s cdb;
2798 	uint8_t *data_buf = buf;
2799 	uint32_t status;
2800 	int32_t ret;
2801 	uint32_t flag = 0;
2802 
2803 	if ((sc == NULL) || (sc->data_ccb == NULL)) {
2804 		return (-1);
2805 	}
2806 
2807 	if ((sc->info.sectornum < (startsector + nsectors)) || (sc->info.sectorsize < blocksize))
2808 		return (-1);
2809 
2810 	if (((uintptr_t)data_buf & (USB_CACHE_ALIGN_SIZE - 1)) != 0)
2811 	{
2812 		data_buf = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(nsectors * blocksize));
2813 		if (data_buf == NULL) {
2814 			PRINT_ERR("Malloc failed!->%s %d\n", __FUNCTION__, __LINE__);
2815 			return (-1);
2816 		}
2817 		flag = 1;
2818 	}
2819 
2820 	(void)memset_s(&cdb, sizeof(struct scsicmd_read10_s), 0, sizeof(struct scsicmd_read10_s));
2821 	usbhost_readcdb10(startsector, blocksize, nsectors, &cdb);
2822 	(void)umass_scsi_transform(sc, (uint8_t *)&cdb, SCSICMD_READ10_SIZEOF);
2823 	ret = umass_command_start(sc, DIR_IN, (void *)data_buf, blocksize * nsectors, 0,
2824 	    umass_cam_cb, sc->data_ccb);
2825 	if (ret != STATUS_CMD_OK) {
2826 		if (flag == 1)
2827 			free(data_buf);
2828 		return (-1);
2829 	}
2830 
2831 	if (flag == 1) {
2832 		if (!LOS_IsUserAddressRange((vaddr_t)buf, blocksize * nsectors - sc->data_ccb->csio.resid)) {
2833 			ret = memcpy_s(buf, nsectors * blocksize, data_buf, blocksize * nsectors - sc->data_ccb->csio.resid);
2834 		} else {
2835 			ret = ((nsectors * blocksize >= blocksize * nsectors - sc->data_ccb->csio.resid) ?
2836 				LOS_ArchCopyToUser(buf, data_buf, blocksize * nsectors - sc->data_ccb->csio.resid) : ERANGE_AND_RESET);
2837 		}
2838 		free(data_buf);
2839 		if (ret != EOK) {
2840 			return (-1);
2841 		}
2842 	}
2843 
2844 	status = sc->data_ccb->csio.status;
2845 	if (status != STATUS_CMD_OK) {
2846 		return (-1);
2847 	}
2848 
2849 	return (0);
2850 }
2851 
2852 int
2853 umass_read16(struct umass_softc *sc, uint64_t startsector, uint16_t blocksize,
2854     unsigned int nsectors, unsigned char *buf)
2855 {
2856 	struct scsicmd_read16_s cdb;
2857 	uint8_t *data_buf = buf;
2858 	uint32_t status;
2859 	uint32_t res;
2860 	uint32_t flag = 0;
2861 	int ret;
2862 
2863 	if ((sc == NULL) || (sc->data_ccb == NULL)) {
2864 		return (-1);
2865 	}
2866 
2867 	if ((sc->info.sectornum < (startsector + nsectors)) || (sc->info.sectorsize < blocksize))
2868 		return (-1);
2869 
2870 	if (((uintptr_t)data_buf & (USB_CACHE_ALIGN_SIZE - 1)) != 0) {
2871 		data_buf = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(nsectors * blocksize));
2872 		if (data_buf == NULL) {
2873 			PRINT_ERR("Malloc failed!->%s %d\n", __FUNCTION__, __LINE__);
2874 			return (-1);
2875 		}
2876 		flag = 1;
2877 	}
2878 
2879 	(void)memset_s(&cdb, sizeof(struct scsicmd_read16_s), 0, sizeof(struct scsicmd_read16_s));
2880 	usbhost_readcdb16(startsector, blocksize, nsectors, &cdb);
2881 	(void)umass_scsi_transform(sc, (uint8_t *)&cdb, SCSICMD_READ16_SIZEOF);
2882 	res = umass_command_start(sc, DIR_IN, (void *)data_buf, blocksize * nsectors, 0,
2883 	    umass_cam_cb, sc->data_ccb);
2884 	if (STATUS_CMD_OK != res) {
2885 		if (flag == 1)
2886 			free(data_buf);
2887 		return (-1);
2888 	}
2889 
2890 	if (flag == 1) {
2891 		if (!LOS_IsUserAddressRange((vaddr_t)buf, blocksize * nsectors - sc->data_ccb->csio.resid)) {
2892 			ret = memcpy_s(buf, nsectors * blocksize, data_buf, blocksize * nsectors - sc->data_ccb->csio.resid);
2893 		} else {
2894 			ret = ((nsectors * blocksize >= blocksize * nsectors - sc->data_ccb->csio.resid) ?
2895 				LOS_ArchCopyToUser(buf, data_buf, blocksize * nsectors - sc->data_ccb->csio.resid) : ERANGE_AND_RESET);
2896 		}
2897 		free(data_buf);
2898 		if (ret != EOK) {
2899 			return (-1);
2900 		}
2901 	}
2902 
2903 	status = sc->data_ccb->csio.status;
2904 	if (status != STATUS_CMD_OK) {
2905 		return (-1);
2906 	}
2907 
2908 	return (0);
2909 }
2910 
2911 int
2912 umass_write10(struct umass_softc *sc, size_t startsector, uint16_t blocksize,
2913     unsigned int nsectors, const unsigned char *buf)
2914 {
2915 	struct scsicmd_write10_s cdb;
2916 	uint8_t *data_buf = (uint8_t *)buf;
2917 	uint32_t status;
2918 	int32_t ret;
2919 	uint32_t flag = 0;
2920 
2921 	if((sc == NULL) || (sc->data_ccb == NULL)) {
2922 		return (-1);
2923 	}
2924 
2925 	if ((sc->info.sectornum < (startsector + nsectors)) || (sc->info.sectorsize < blocksize))
2926 		return (-1);
2927 
2928 	if (((uintptr_t)data_buf & (USB_CACHE_ALIGN_SIZE - 1)) != 0) {
2929 		data_buf = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(nsectors * blocksize));
2930 		if (data_buf == NULL) {
2931 			PRINT_ERR("Malloc failed!->%s %d\n", __FUNCTION__, __LINE__);
2932 			return (-1);
2933 		}
2934 
2935 		if (!LOS_IsUserAddressRange((vaddr_t)buf, blocksize * nsectors)) {
2936 			(void)memcpy_s(data_buf, blocksize * nsectors, buf, blocksize * nsectors);
2937 		} else {
2938 			ret = LOS_ArchCopyFromUser(data_buf, buf, blocksize * nsectors);
2939 			if (ret != 0) {
2940 				free(data_buf);
2941 				PRINT_ERR("copy failed!->%s %d\n", __FUNCTION__, __LINE__);
2942 				return (-1);
2943 			}
2944 		}
2945 		flag = 1;
2946 	}
2947 
2948 	(void)memset_s(&cdb, sizeof(struct scsicmd_write10_s), 0, sizeof(struct scsicmd_write10_s));
2949 	usbhost_writecbw10(startsector, blocksize, nsectors, &cdb);
2950 	(void)umass_scsi_transform(sc, (uint8_t *)&cdb, SCSICMD_WRITE10_SIZEOF);
2951 	ret = umass_command_start(sc, DIR_OUT, (void *)data_buf, blocksize * nsectors, 1000,
2952 	    umass_cam_cb, sc->data_ccb);
2953 
2954 	if (flag == 1) {
2955 		free(data_buf);
2956 	}
2957 
2958 	status = sc->data_ccb->csio.status;
2959 	if ((ret != STATUS_CMD_OK) || (status != STATUS_CMD_OK)) {
2960 		return (-1);
2961 	}
2962 
2963 	return (0);
2964 }
2965 
2966 int
2967 umass_write16(struct umass_softc *sc, uint64_t startsector, uint16_t blocksize,
2968     unsigned int nsectors, const unsigned char *buf)
2969 {
2970 	struct scsicmd_write16_s cdb;
2971 	uint8_t *data_buf = (uint8_t *)buf;
2972 	uint32_t status;
2973 	int32_t  res;
2974 	int32_t ret;
2975 	uint32_t flag = 0;
2976 
2977 	if((sc == NULL) || (sc->data_ccb == NULL)) {
2978 		return (-1);
2979 	}
2980 
2981 	if ((sc->info.sectornum < (startsector + nsectors)) || (sc->info.sectorsize < blocksize)) {
2982 		return (-1);
2983 	}
2984 
2985 	if (((uintptr_t)data_buf & (USB_CACHE_ALIGN_SIZE - 1)) != 0)
2986 	{
2987 		data_buf = (uint8_t *)memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(nsectors * blocksize));
2988 		if (data_buf == NULL) {
2989 			PRINT_ERR("Malloc failed!->%s %d\n", __FUNCTION__, __LINE__);
2990 			return (-1);
2991 		}
2992 
2993 		if (!LOS_IsUserAddressRange((vaddr_t)buf, blocksize * nsectors)) {
2994 			(void)memcpy_s(data_buf, blocksize * nsectors, buf, blocksize * nsectors);
2995 		} else {
2996 			ret = LOS_ArchCopyFromUser(data_buf, buf, blocksize * nsectors);
2997 			if (ret != 0) {
2998 				free(data_buf);
2999 				PRINT_ERR("copy failed!->%s %d\n", __FUNCTION__, __LINE__);
3000 				return (-1);
3001 			}
3002 		}
3003 		flag = 1;
3004 	}
3005 
3006 	(void)memset_s(&cdb, sizeof(struct scsicmd_write16_s), 0, sizeof(struct scsicmd_write16_s));
3007 	usbhost_writecbw16(startsector, blocksize, nsectors, &cdb);
3008 	(void)umass_scsi_transform(sc, (uint8_t *)&cdb, SCSICMD_WRITE16_SIZEOF);
3009 	res = umass_command_start(sc, DIR_OUT, (void *)data_buf, blocksize * nsectors, 1000,
3010 	    umass_cam_cb, sc->data_ccb);
3011 
3012 	if (flag == 1)
3013 	{
3014 		free(data_buf);
3015 	}
3016 
3017 	status = sc->data_ccb->csio.status;
3018 	if ((res != STATUS_CMD_OK) || (status != STATUS_CMD_OK)) {
3019 		return (-1);
3020 	}
3021 
3022 	return (0);
3023 }
3024 
3025 int
3026 umass_inquiry(struct umass_softc *sc)
3027 {
3028 	uint32_t status;
3029 	int32_t ret;
3030 
3031 	if ((sc == NULL) || (sc->data_ccb == NULL)) {
3032 		goto error;
3033 	}
3034 
3035 	(void)umass_scsi_transform(sc, scsi_inquiry, SCSICMD_INQUIRY_SIZEOF);
3036 	ret = umass_command_start(sc, DIR_IN, sc->data_ccb->csio.data_ptr, SCSIRESP_INQUIRY_SIZEOF,
3037 	    1000, umass_cam_cb, sc->data_ccb);
3038 	if (ret != STATUS_CMD_OK) {
3039 		goto error;
3040 	}
3041 
3042 	status = sc->data_ccb->csio.status;
3043 	if (status != STATUS_CMD_OK) {
3044 		PRINT_WARN("Failed to get the inquiry_status [status=%d].\n", status);
3045 		goto error;
3046 	}
3047 
3048 	ret = umass_scsi_inquiry_data(sc, sc->data_ccb->csio.data_ptr, SCSIRESP_INQUIRY_SIZEOF);
3049 	if (ret == -1){
3050 		PRINT_WARN("Failed to get the scsi_inquiry data .\n");
3051 		goto error;
3052 	}else if (ret == 1) {
3053 		/* find Direct-access LUN */
3054 		return (0);
3055 	}
3056 
3057 error:
3058 	return (-1);
3059 }
3060 
3061 int
3062 umass_request_sense(struct umass_softc *sc)
3063 {
3064 	uint32_t status;
3065 	int32_t ret;
3066 	if ((sc == NULL) || (sc->data_ccb == NULL)) {
3067 		return (-1);
3068 	}
3069 
3070 	(void)umass_scsi_transform(sc, scsi_request_sense, SCSICMD_REQUESTSENSE_SIZEOF);
3071 	ret = umass_command_start(sc, DIR_IN, sc->data_ccb->csio.data_ptr, SCSIRESP_FIXEDSENSEDATA_SIZEOF,
3072 	    1000, umass_cam_cb, sc->data_ccb);
3073 	if (ret != STATUS_CMD_OK) {
3074 		return (-1);
3075 	}
3076 
3077 	status = sc->data_ccb->csio.status;
3078 	if (status != STATUS_CMD_OK) {
3079 		return (-1);
3080 	}
3081 
3082 	return (0);
3083 }
3084 
3085 void *
3086 umass_bind(void)
3087 {
3088 	return ((void*)p_umsf);
3089 }
3090 
3091 void
3092 umass_status(void)
3093 {
3094 	struct umass_softc *sc = p_umsf;
3095 	UINT8 cmd;
3096 	UINT8 lun;
3097 	UINT8 max;
3098 	UINT8 speed;
3099 	UINT8 phase;
3100 	UINT8 state;
3101 	UINT16 vid;
3102 	UINT16 pid;
3103 	UINT32 tag, residuce;
3104 
3105 	if (sc == NULL) {
3106 		return;
3107 	}
3108 
3109 	cmd = sc->sc_transfer.cmd_data[0];
3110 	lun = sc->sc_transfer.lun;
3111 	max = sc->sc_maxlun + 1;
3112 	speed = sc->sc_udev->speed;
3113 	phase = sc->sc_last_xfer_index;
3114 	state = USB_GET_STATE(sc->sc_xfer[phase]);
3115 	vid = UGETW(sc->sc_udev->ddesc.idVendor);
3116 	pid = UGETW(sc->sc_udev->ddesc.idProduct);
3117 	tag = UGETDW(sc->cbw.dCBWTag);
3118 	residuce = UGETDW(sc->csw.dCSWDataResidue);
3119 
3120 	dprintf("VID:%04X/PID:%04X/SPD:%02d",vid,pid,speed);
3121 	if (sc->sc_transfer.ccb) {
3122 		dprintf("/ST:%02d ",state);
3123 		if (state == USB_ST_SETUP) {
3124 			dprintf("[SP]");
3125 		} else if (state == USB_ST_TRANSFERRED) {
3126 			dprintf("[TD]");
3127 		}
3128 		dprintf("/cPHASE:%02d ",phase);
3129 	} else {
3130 		dprintf("/nPHASE:%02d ",phase);
3131 	}
3132 	if (phase == UMASS_T_BBB_COMMAND) {
3133 		dprintf("[CBW]");
3134 	} else if (phase == UMASS_T_BBB_DATA_READ) {
3135 		dprintf("[DATA]");
3136 	} else if (phase == UMASS_T_BBB_DATA_WRITE) {
3137 		dprintf("[DATA]");
3138 	} else if (phase == UMASS_T_BBB_STATUS) {
3139 		dprintf("[CSW]");
3140 	} else if (phase == UMASS_T_BBB_DATA_RD_CS) {
3141 		dprintf("[STAL]");
3142 	} else if (phase == UMASS_T_BBB_DATA_WR_CS) {
3143 		dprintf("[STAL]");
3144 	}
3145 	dprintf("\n");
3146 
3147 	dprintf("CL:%d/ML:%d/TG:%08X/RDU:%d/CMD:%X ",lun,max,tag,residuce,cmd);
3148 	if (cmd == SCSI_CMD_READ10) {
3149 		dprintf("[RD]\n");
3150 	} else if (cmd == SCSI_CMD_WRITE10) {
3151 		dprintf("[WR]\n");
3152 	} else if (cmd == SCSI_CMD_INQUIRY) {
3153 		dprintf("[INQ]\n");
3154 	} else if (cmd == SCSI_CMD_TESTUNITREADY) {
3155 		dprintf("[TUR]\n");
3156 	} else if (cmd == SCSI_CMD_REQUESTSENSE) {
3157 		dprintf("[RS]\n");
3158 	} else if (cmd == SCSI_CMD_READCAPACITY10) {
3159 		dprintf("[RC]\n");
3160 	} else {
3161 		dprintf("\n");
3162 	}
3163 }
3164 
3165 static int
3166 umass_open(struct Vnode *filep)
3167 {
3168 	(void)filep;
3169 	return (0);
3170 }
3171 
3172 static int
3173 umass_close(struct Vnode *filep)
3174 {
3175 	(void)filep;
3176 	return (0);
3177 }
3178 
3179 static ssize_t
3180 umass_read(struct Vnode *umass_inode, unsigned char *buffer,
3181 		    uint64_t start_sector, unsigned int nsectors)
3182 {
3183 	int status;
3184 	struct umass_softc *sc = (struct umass_softc *)((struct drv_data*)umass_inode->data)->priv;
3185 
3186 	mtx_lock(&sc->sc_umass_mtx);
3187 	if (sc->sc_super_disk == TRUE) {
3188 		status = umass_read16(sc, start_sector, (uint16_t)sc->info.sectorsize, nsectors, buffer);
3189 	} else {
3190 		status = umass_read10(sc, (size_t)start_sector, (uint16_t)sc->info.sectorsize, nsectors, buffer);
3191 	}
3192 	mtx_unlock(&sc->sc_umass_mtx);
3193 
3194 	if(status)
3195 		return (-1);
3196 	else
3197 		return ((ssize_t)nsectors);
3198 }
3199 
3200 static ssize_t
3201 umass_write(struct Vnode *umass_inode, const unsigned char *buffer,
3202 		    uint64_t start_sector, unsigned int nsectors)
3203 {
3204 	int status;
3205 	struct umass_softc *sc = (struct umass_softc *)((struct drv_data*)umass_inode->data)->priv;
3206 
3207 	mtx_lock(&sc->sc_umass_mtx);
3208 	if (sc->sc_super_disk == TRUE) {
3209 		status = umass_write16(sc, start_sector, (uint16_t)sc->info.sectorsize, nsectors, buffer);
3210 	} else {
3211 		status = umass_write10(sc, (size_t)start_sector, (uint16_t)sc->info.sectorsize, nsectors, buffer);
3212 	}
3213 	mtx_unlock(&sc->sc_umass_mtx);
3214 
3215 	if(status)
3216 		return (-1);
3217 	else
3218 		return ((ssize_t)nsectors);
3219 }
3220 
3221 static int
3222 umass_geometry(struct Vnode *umass_inode, struct geometry *ugeometry)
3223 {
3224 	struct umass_softc *sc;
3225 
3226 	if ((ugeometry == NULL) || (umass_inode == NULL))
3227 		return (-1);
3228 
3229 	sc = (struct umass_softc *)(struct umass_softc *)((struct drv_data*)umass_inode->data)->priv;
3230 
3231 	if (sc == NULL)
3232 		return (-1);
3233 
3234 	mtx_lock(&sc->sc_umass_mtx);
3235 	ugeometry->geo_available	= true;
3236 	ugeometry->geo_mediachanged = false;
3237 	ugeometry->geo_writeenabled = true;
3238 	ugeometry->geo_nsectors	 = sc->info.sectornum;
3239 	ugeometry->geo_sectorsize   = sc->info.sectorsize;
3240 	mtx_unlock(&sc->sc_umass_mtx);
3241 
3242 	return (0);
3243 }
3244 
3245 static int
3246 umass_ioctl(struct Vnode *umass_inode, int cmd, unsigned long arg)
3247 {
3248 	(void)umass_inode;
3249 	(void)cmd;
3250 	(void)arg;
3251 	return (0);
3252 }
3253 
3254 const struct block_operations g_dev_umass_ops = {
3255 	.open  = umass_open,
3256 	.close = umass_close,
3257 	.read  = umass_read,
3258 	.write = umass_write,
3259 	.geometry = umass_geometry,
3260 	.ioctl = umass_ioctl,
3261 	.unlink = NULL
3262 };
3263 
3264 static int
3265 umass_dev_is_ready(struct umass_softc *sc)
3266 {
3267 	int lun;
3268 	int ret;
3269 	uint8_t valid_lun;
3270 
3271 	mtx_lock(&sc->sc_umass_mtx);
3272 	for (lun = 0; lun <= sc->sc_maxlun; lun++) {
3273 		sc->sc_transfer.lun = lun;
3274 		if (umass_inquiry(sc) < 0)
3275 			continue;
3276 
3277 		valid_lun = lun;
3278 		ret = umass_test_unit_ready(sc);
3279 		if(ret == 0) {
3280 			sc->sc_transfer.lun = valid_lun;
3281 			ret = umass_read_capacity(sc);
3282 			if (ret < 0) {
3283 				mtx_unlock(&sc->sc_umass_mtx);
3284 				PRINT_ERR("umass read capacity fail!\n");
3285 				return (0);
3286 			}
3287 			mtx_unlock(&sc->sc_umass_mtx);
3288 			return (1);
3289 		}
3290 
3291 		ret = umass_request_sense(sc);
3292 		if(ret < 0) {
3293 			PRINT_ERR("Request sense fail!\n");
3294 			mtx_unlock(&sc->sc_umass_mtx);
3295 			return (0);
3296 		}
3297 	}
3298 	mtx_unlock(&sc->sc_umass_mtx);
3299 	return (0);
3300 }
3301 
3302 static int
3303 umass_attach_dev_sub(struct umass_softc *sc, unsigned int dev_unit)
3304 {
3305 	int ret;
3306 	int disk_id;
3307 	char devname[MASS_NAME]= {0};
3308 #if USB_HAVE_DEVICE_TOPOLOGY
3309 	device_t dev;
3310 	struct usb_device *udev;
3311 	usbd_bt_node *cur_node;
3312 	struct node_info parent_info;
3313 	struct node_info cur_info;
3314 #endif
3315 
3316 	umass_dev_lock(dev_unit);
3317 
3318 #if USB_HAVE_DEVICE_TOPOLOGY
3319 	dev = sc->sc_dev;
3320 	udev = sc->sc_udev;
3321 	dev_quantity |= 1ull << (unsigned int)device_get_unit(dev);
3322 #endif
3323 
3324 #if USB_SUPPORT_SD_HOT_PLUG
3325 	if (!umass_dev_is_attached(dev_unit))
3326 #endif
3327 	{
3328 		devunit_to_devname(dev_unit, devname);
3329 		disk_id = los_alloc_diskid_byname(devname);
3330 		OsSetUsbStatus(disk_id);
3331 		ret = los_disk_init(devname, &g_dev_umass_ops, (void *)sc, disk_id, NULL);
3332 		if (ret) {
3333 			PRINT_ERR("umass_attach_dev : los_disk_init fail!\n");
3334 			goto error;
3335 		}
3336 	}
3337 #if USB_SUPPORT_SD_HOT_PLUG
3338 	umass_dev_attach_flag_set(dev_unit);
3339 #endif
3340 
3341 #if USB_HAVE_DEVICE_TOPOLOGY
3342 	cur_info.nameunit = device_get_nameunit(dev);
3343 	cur_info.port_no = udev->port_no;
3344 	cur_node = usbd_create_bt_node(&cur_info);
3345 	if (cur_node == NULL) {
3346 		goto error;
3347 	}
3348 
3349 	parent_info.nameunit = device_get_nameunit(device_get_parent(dev));
3350 	parent_info.port_no = udev->port_no;
3351 
3352 	(void)usbd_insert_bt_node(cur_node, hub_tree, &parent_info);
3353 #endif
3354 
3355 	umass_dev_unlock(dev_unit);
3356 	return (0);
3357 
3358 error:
3359 	umass_dev_unlock(dev_unit);
3360 	return (-1);
3361 }
3362 
3363 static void
3364 umass_detach_dev_sub(struct umass_softc *sc, int dev_unit, int flag)
3365 {
3366 	int disk_id;
3367 	char devname[MASS_NAME]= {0};
3368 #if USB_HAVE_DEVICE_TOPOLOGY
3369 	struct node_info cur_info;
3370 	struct node_info parent_info;
3371 	device_t dev = NULL;
3372 	struct usb_device *udev = NULL;
3373 #endif
3374 
3375 	umass_dev_lock(dev_unit);
3376 
3377 #if USB_HAVE_DEVICE_TOPOLOGY
3378 	dev = sc->sc_dev;
3379 	udev = sc->sc_udev;
3380 #if USB_SUPPORT_SD_HOT_PLUG
3381 	if (umass_dev_is_attached(dev_unit))
3382 #endif
3383 	{
3384 		parent_info.nameunit = device_get_nameunit(device_get_parent(dev));
3385 		parent_info.port_no = udev->port_no;
3386 
3387 		cur_info.nameunit = device_get_nameunit(dev);
3388 		cur_info.port_no = udev->port_no;
3389 		(void)usbd_remove_bt_node(hub_tree, &parent_info, &cur_info);
3390 	}
3391 #endif
3392 
3393 #if USB_SUPPORT_SD_HOT_PLUG
3394 	if (umass_dev_is_attached(dev_unit))
3395 #endif
3396 	{
3397 		devunit_to_devname(dev_unit, devname);
3398 		disk_id = los_get_diskid_byname(devname);
3399 		(void)los_disk_deinit(disk_id);
3400 		(void)OsClearUsbStatus(disk_id);
3401 	}
3402 
3403 	if (flag == 0) { /* 0: This interface is called from umass_detach, or is called elsewhere. */
3404 #if USB_SUPPORT_SD_HOT_PLUG
3405 		umass_dev_delete(sc, dev_unit);
3406 #endif
3407 	}
3408 
3409 #if USB_HAVE_DEVICE_TOPOLOGY
3410 	dev_quantity &= ~(1ull << (unsigned int)device_get_unit(dev));
3411 #endif
3412 
3413 	umass_dev_unlock(dev_unit);
3414 }
3415 
3416 #if USB_SUPPORT_SD_HOT_PLUG
3417 void
3418 umass_dev_status_check(UINTPTR arg)
3419 {
3420 	(void)arg;
3421 	int ret;
3422 	int i;
3423 	struct umass_dev_info *dev = g_umass_dev_array;
3424 	struct umass_softc *sc;
3425 
3426 	while(1) {
3427 		for (i = 0; i < MAX_DEVICE; i++) {
3428 			umass_dev_lock(i);
3429 			if (dev[i].used == 1) {
3430 				sc = dev[i].sc;
3431 				ret = umass_dev_is_ready(sc);
3432 				if (ret == 0) {
3433 					if (dev[i].attached == 1) {
3434 						umass_detach_dev_sub(sc, dev[i].dev_unit, 1);
3435 						dev[i].attached = 0;
3436 					}
3437 					umass_dev_unlock(i);
3438 					continue;
3439 				}
3440 
3441 				if (dev[i].attached == 1) {
3442 					umass_dev_unlock(i);
3443 					continue;
3444 				}
3445 
3446 				ret = umass_attach_dev_sub(sc, dev[i].dev_unit);
3447 				if (ret< 0) {
3448 					umass_dev_unlock(i);
3449 					PRINT_ERR("umass attach device sub failed!\n");
3450 					continue;
3451 				}
3452 			}
3453 			umass_dev_unlock(i);
3454 		}
3455 		(void)LOS_Msleep(1000);
3456 	}
3457 }
3458 
3459 int
3460 umass_dev_is_attached(unsigned int dev_unit)
3461 {
3462 	if (dev_unit >= MAX_DEVICE) {
3463 		PRINT_ERR("%s %d, The device unit is wrong!\n", __FUNCTION__, __LINE__);
3464 		return (-1);
3465 	}
3466 
3467 	return (g_umass_dev_array[dev_unit].attached);
3468 }
3469 
3470 static void
3471 umass_dev_add(struct umass_softc *sc, int dev_unit)
3472 {
3473 	int id = dev_unit;
3474 
3475 	if (g_umass_dev_array[id].used == 1) {
3476 		PRINT_ERR("The id of umass device array is used!, id=%d\n", dev_unit);
3477 		return;
3478 	}
3479 
3480 	g_umass_dev_array[id].sc = sc;
3481 	g_umass_dev_array[id].dev_unit = dev_unit;
3482 	g_umass_dev_array[id].used = 1;
3483 	umass_dev_mtx_init(id, MTX_DEF | MTX_RECURSE);
3484 }
3485 
3486 static void
3487 umass_dev_delete(struct umass_softc *sc, unsigned int dev_unit)
3488 {
3489 	unsigned int id = dev_unit;
3490 
3491 	if (g_umass_dev_array[id].used == 0) {
3492 		PRINT_ERR("The id of umass device array is not used!\n");
3493 		return;
3494 	}
3495 
3496 	if (g_umass_dev_array[id].dev_unit == dev_unit &&
3497 		g_umass_dev_array[id].sc == sc) {
3498 		g_umass_dev_array[id].used = 0;
3499 		g_umass_dev_array[id].sc = NULL;
3500 		g_umass_dev_array[id].attached = 0;
3501 		umass_dev_mtx_destroy(id);
3502 	} else {
3503 		PRINT_ERR("Can not find the umass device!\n");
3504 	}
3505 }
3506 
3507 static void
3508 umass_dev_attach_flag_set(int dev_unit)
3509 {
3510 	g_umass_dev_array[dev_unit].attached = 1;
3511 }
3512 
3513 static void
3514 umass_task_check(int flag)
3515 {
3516 	int i;
3517 	int ret;
3518 
3519 	for (i = 0; i < MAX_DEVICE; i++) {
3520 		if (g_umass_dev_array[i].used)
3521 			break;
3522 	}
3523 
3524 	if (i == MAX_DEVICE) {
3525 		if (flag == 0) { /* create task */
3526 			ret = usb_os_task_creat(&umass_taskid, (TSK_ENTRY_FUNC)umass_dev_status_check,
3527 			    LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO, "umass_task", 0);
3528 			if (ret) {
3529 				PRINT_ERR("Create umass task fail!\n");
3530 				return;
3531 			}
3532 		} else if (flag == 1) { /* delete task */
3533 			ret = usb_os_task_delete(umass_taskid);
3534 			if (ret) {
3535 				PRINT_ERR("Delete umass task fail!\n");
3536 				return;
3537 			}
3538 		} else {
3539 			PRINT_ERR("%s flag error!\n", __FUNCTION__);
3540 		}
3541 	}
3542 }
3543 #endif
3544 
3545 static void
3546 devunit_to_devname(unsigned int dev_unit, char *devname)
3547 {
3548 	char name_suf;
3549 	int ret;
3550 
3551 #if USB_HAVE_DEVICE_TOPOLOGY
3552 	if (!(0x1 & (dev_quantity >> dev_unit)))
3553 #else
3554 	if (dev_unit >= MAX_DEVICE)
3555 #endif
3556 	{
3557 		dprintf("sorry, we don't support so many devices\n");
3558 		return;
3559 	}
3560 
3561 	name_suf = 'a' + dev_unit;
3562 	ret = snprintf_s(devname, MASS_NAME, MASS_NAME - 1, "%s%c", UMASS_ATTACH_PRENAME, name_suf);
3563 	if (ret < 0) {
3564 		usb_err("snprintf_s failed!, ret:%d\n", ret);
3565 		return;
3566 	}
3567 }
3568 static int32_t
3569 umass_attach_dev(struct umass_softc *sc, unsigned int dev_unit)
3570 {
3571 	int ret;
3572 
3573 	if (dev_unit >= MAX_DEVICE) {
3574 		PRINT_ERR("sorry, we don't support so many devices\n");
3575 		return (-1);
3576 	}
3577 #if USB_SUPPORT_SD_HOT_PLUG
3578 	umass_task_check(0);
3579 	umass_dev_add(sc, dev_unit);
3580 #endif
3581 
3582 	ret = umass_dev_is_ready(sc);
3583 	if (ret) {
3584 		ret = umass_attach_dev_sub(sc, dev_unit);
3585 		if (ret < 0) {
3586 #if USB_SUPPORT_SD_HOT_PLUG
3587 			umass_dev_delete(sc, dev_unit);
3588 #endif
3589 			PRINT_ERR("umass attach device fail!\n");
3590 			return (-1);
3591 		}
3592 	}
3593 
3594 	return (0);
3595 }
3596 
3597 #if USB_HAVE_DEVICE_TOPOLOGY
3598 int
3599 umass_medium_probe(uint8_t medium, char *devname)
3600 {
3601 	struct usbd_bt_node *node;
3602 	uint8_t dev_unit;
3603 
3604 	if ((devname == NULL) || strlen(devname) > 7) { /* /dev/sd* */
3605 		return (-1);
3606 	}
3607 
3608 	if ((medium < 1) || (medium > usbd_get_hub_quantity())) {
3609 		return (-1);
3610 	}
3611 
3612 	node = usbd_per_order_probe(hub_tree, "umass", &medium);
3613 	if (node != NULL) {
3614 		dev_unit = usbd_atoi(node->info.nameunit + 5); /* 5 = umass */
3615 		devunit_to_devname(dev_unit, devname);
3616 	} else {
3617 		return (-1);
3618 	}
3619 	return (0);
3620 }
3621 #endif
3622 
3623