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