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