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