usb_msctest.c (242364) | usb_msctest.c (244503) |
---|---|
1/* $FreeBSD: head/sys/dev/usb/usb_msctest.c 242364 2012-10-30 16:56:16Z hselasky $ */ | 1/* $FreeBSD: head/sys/dev/usb/usb_msctest.c 244503 2012-12-20 18:38:02Z hselasky $ */ |
2/*- 3 * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. --- 124 unchanged lines hidden (view full) --- 134#define CSWSTATUS_GOOD 0x0 135#define CSWSTATUS_FAILED 0x1 136#define CSWSTATUS_PHASE 0x2 137} __packed; 138 139struct bbb_transfer { 140 struct mtx mtx; 141 struct cv cv; | 2/*- 3 * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. --- 124 unchanged lines hidden (view full) --- 134#define CSWSTATUS_GOOD 0x0 135#define CSWSTATUS_FAILED 0x1 136#define CSWSTATUS_PHASE 0x2 137} __packed; 138 139struct bbb_transfer { 140 struct mtx mtx; 141 struct cv cv; |
142 struct bbb_cbw cbw; 143 struct bbb_csw csw; | 142 struct bbb_cbw *cbw; 143 struct bbb_csw *csw; |
144 145 struct usb_xfer *xfer[ST_MAX]; 146 147 uint8_t *data_ptr; 148 149 usb_size_t data_len; /* bytes */ 150 usb_size_t data_rem; /* bytes */ 151 usb_timeout_t data_timeout; /* ms */ 152 usb_frlength_t actlen; /* bytes */ 153 154 uint8_t cmd_len; /* bytes */ 155 uint8_t dir; 156 uint8_t lun; 157 uint8_t state; 158 uint8_t status_try; 159 int error; 160 | 144 145 struct usb_xfer *xfer[ST_MAX]; 146 147 uint8_t *data_ptr; 148 149 usb_size_t data_len; /* bytes */ 150 usb_size_t data_rem; /* bytes */ 151 usb_timeout_t data_timeout; /* ms */ 152 usb_frlength_t actlen; /* bytes */ 153 154 uint8_t cmd_len; /* bytes */ 155 uint8_t dir; 156 uint8_t lun; 157 uint8_t state; 158 uint8_t status_try; 159 int error; 160 |
161 uint8_t buffer[SCSI_MAX_LEN] __aligned(4); | 161 uint8_t *buffer; |
162}; 163 164static usb_callback_t bbb_command_callback; 165static usb_callback_t bbb_data_read_callback; 166static usb_callback_t bbb_data_rd_cs_callback; 167static usb_callback_t bbb_data_write_callback; 168static usb_callback_t bbb_data_wr_cs_callback; 169static usb_callback_t bbb_status_callback; --- 9 unchanged lines hidden (view full) --- 179 180static const struct usb_config bbb_config[ST_MAX] = { 181 182 [ST_COMMAND] = { 183 .type = UE_BULK, 184 .endpoint = UE_ADDR_ANY, 185 .direction = UE_DIR_OUT, 186 .bufsize = sizeof(struct bbb_cbw), | 162}; 163 164static usb_callback_t bbb_command_callback; 165static usb_callback_t bbb_data_read_callback; 166static usb_callback_t bbb_data_rd_cs_callback; 167static usb_callback_t bbb_data_write_callback; 168static usb_callback_t bbb_data_wr_cs_callback; 169static usb_callback_t bbb_status_callback; --- 9 unchanged lines hidden (view full) --- 179 180static const struct usb_config bbb_config[ST_MAX] = { 181 182 [ST_COMMAND] = { 183 .type = UE_BULK, 184 .endpoint = UE_ADDR_ANY, 185 .direction = UE_DIR_OUT, 186 .bufsize = sizeof(struct bbb_cbw), |
187 .flags = {.ext_buffer = 1,}, | |
188 .callback = &bbb_command_callback, 189 .timeout = 4 * USB_MS_HZ, /* 4 seconds */ 190 }, 191 192 [ST_DATA_RD] = { 193 .type = UE_BULK, 194 .endpoint = UE_ADDR_ANY, 195 .direction = UE_DIR_IN, | 187 .callback = &bbb_command_callback, 188 .timeout = 4 * USB_MS_HZ, /* 4 seconds */ 189 }, 190 191 [ST_DATA_RD] = { 192 .type = UE_BULK, 193 .endpoint = UE_ADDR_ANY, 194 .direction = UE_DIR_IN, |
196 .bufsize = BULK_SIZE, 197 .flags = {.ext_buffer = 1,.proxy_buffer = 1,.short_xfer_ok = 1,}, | 195 .bufsize = MAX(SCSI_MAX_LEN, BULK_SIZE), 196 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,}, |
198 .callback = &bbb_data_read_callback, 199 .timeout = 4 * USB_MS_HZ, /* 4 seconds */ 200 }, 201 202 [ST_DATA_RD_CS] = { 203 .type = UE_CONTROL, 204 .endpoint = 0x00, /* Control pipe */ 205 .direction = UE_DIR_ANY, --- 21 unchanged lines hidden (view full) --- 227 .timeout = 1 * USB_MS_HZ, /* 1 second */ 228 }, 229 230 [ST_STATUS] = { 231 .type = UE_BULK, 232 .endpoint = UE_ADDR_ANY, 233 .direction = UE_DIR_IN, 234 .bufsize = sizeof(struct bbb_csw), | 197 .callback = &bbb_data_read_callback, 198 .timeout = 4 * USB_MS_HZ, /* 4 seconds */ 199 }, 200 201 [ST_DATA_RD_CS] = { 202 .type = UE_CONTROL, 203 .endpoint = 0x00, /* Control pipe */ 204 .direction = UE_DIR_ANY, --- 21 unchanged lines hidden (view full) --- 226 .timeout = 1 * USB_MS_HZ, /* 1 second */ 227 }, 228 229 [ST_STATUS] = { 230 .type = UE_BULK, 231 .endpoint = UE_ADDR_ANY, 232 .direction = UE_DIR_IN, 233 .bufsize = sizeof(struct bbb_csw), |
235 .flags = {.ext_buffer = 1,.short_xfer_ok = 1,}, | 234 .flags = {.short_xfer_ok = 1,}, |
236 .callback = &bbb_status_callback, 237 .timeout = 1 * USB_MS_HZ, /* 1 second */ 238 }, 239}; 240 241static void 242bbb_done(struct bbb_transfer *sc, int error) 243{ | 235 .callback = &bbb_status_callback, 236 .timeout = 1 * USB_MS_HZ, /* 1 second */ 237 }, 238}; 239 240static void 241bbb_done(struct bbb_transfer *sc, int error) 242{ |
244 | |
245 sc->error = error; 246 sc->state = ST_COMMAND; 247 sc->status_try = 1; 248 cv_signal(&sc->cv); 249} 250 251static void 252bbb_transfer_start(struct bbb_transfer *sc, uint8_t xfer_index) --- 32 unchanged lines hidden (view full) --- 285 bbb_transfer_start 286 (sc, ((sc->dir == DIR_IN) ? ST_DATA_RD : 287 (sc->dir == DIR_OUT) ? ST_DATA_WR : 288 ST_STATUS)); 289 break; 290 291 case USB_ST_SETUP: 292 sc->status_try = 0; | 243 sc->error = error; 244 sc->state = ST_COMMAND; 245 sc->status_try = 1; 246 cv_signal(&sc->cv); 247} 248 249static void 250bbb_transfer_start(struct bbb_transfer *sc, uint8_t xfer_index) --- 32 unchanged lines hidden (view full) --- 283 bbb_transfer_start 284 (sc, ((sc->dir == DIR_IN) ? ST_DATA_RD : 285 (sc->dir == DIR_OUT) ? ST_DATA_WR : 286 ST_STATUS)); 287 break; 288 289 case USB_ST_SETUP: 290 sc->status_try = 0; |
293 tag = UGETDW(sc->cbw.dCBWTag) + 1; 294 USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE); 295 USETDW(sc->cbw.dCBWTag, tag); 296 USETDW(sc->cbw.dCBWDataTransferLength, (uint32_t)sc->data_len); 297 sc->cbw.bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT); 298 sc->cbw.bCBWLUN = sc->lun; 299 sc->cbw.bCDBLength = sc->cmd_len; 300 if (sc->cbw.bCDBLength > sizeof(sc->cbw.CBWCDB)) { 301 sc->cbw.bCDBLength = sizeof(sc->cbw.CBWCDB); | 291 tag = UGETDW(sc->cbw->dCBWTag) + 1; 292 USETDW(sc->cbw->dCBWSignature, CBWSIGNATURE); 293 USETDW(sc->cbw->dCBWTag, tag); 294 USETDW(sc->cbw->dCBWDataTransferLength, (uint32_t)sc->data_len); 295 sc->cbw->bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT); 296 sc->cbw->bCBWLUN = sc->lun; 297 sc->cbw->bCDBLength = sc->cmd_len; 298 if (sc->cbw->bCDBLength > sizeof(sc->cbw->CBWCDB)) { 299 sc->cbw->bCDBLength = sizeof(sc->cbw->CBWCDB); |
302 DPRINTFN(0, "Truncating long command\n"); 303 } | 300 DPRINTFN(0, "Truncating long command\n"); 301 } |
304 usbd_xfer_set_frame_data(xfer, 0, &sc->cbw, sizeof(sc->cbw)); | |
305 usbd_transfer_submit(xfer); 306 break; 307 308 default: /* Error */ 309 bbb_done(sc, error); 310 break; 311 } 312} --- 112 unchanged lines hidden (view full) --- 425 426 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); 427 428 switch (USB_GET_STATE(xfer)) { 429 case USB_ST_TRANSFERRED: 430 431 /* very simple status check */ 432 | 302 usbd_transfer_submit(xfer); 303 break; 304 305 default: /* Error */ 306 bbb_done(sc, error); 307 break; 308 } 309} --- 112 unchanged lines hidden (view full) --- 422 423 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); 424 425 switch (USB_GET_STATE(xfer)) { 426 case USB_ST_TRANSFERRED: 427 428 /* very simple status check */ 429 |
433 if (actlen < (int)sizeof(sc->csw)) { | 430 if (actlen < (int)sizeof(struct bbb_csw)) { |
434 bbb_done(sc, USB_ERR_SHORT_XFER); | 431 bbb_done(sc, USB_ERR_SHORT_XFER); |
435 } else if (sc->csw.bCSWStatus == CSWSTATUS_GOOD) { | 432 } else if (sc->csw->bCSWStatus == CSWSTATUS_GOOD) { |
436 bbb_done(sc, 0); /* success */ 437 } else { 438 bbb_done(sc, ERR_CSW_FAILED); /* error */ 439 } 440 break; 441 442 case USB_ST_SETUP: | 433 bbb_done(sc, 0); /* success */ 434 } else { 435 bbb_done(sc, ERR_CSW_FAILED); /* error */ 436 } 437 break; 438 439 case USB_ST_SETUP: |
443 usbd_xfer_set_frame_data(xfer, 0, &sc->csw, sizeof(sc->csw)); | |
444 usbd_transfer_submit(xfer); 445 break; 446 447 default: 448 DPRINTF("Failed to read CSW: %s, try %d\n", 449 usbd_errstr(error), sc->status_try); 450 451 if (error == USB_ERR_CANCELLED || sc->status_try) { --- 21 unchanged lines hidden (view full) --- 473 sc->lun = lun; 474 sc->dir = data_len ? dir : DIR_NONE; 475 sc->data_ptr = data_ptr; 476 sc->data_len = data_len; 477 sc->data_rem = data_len; 478 sc->data_timeout = (data_timeout + USB_MS_HZ); 479 sc->actlen = 0; 480 sc->cmd_len = cmd_len; | 440 usbd_transfer_submit(xfer); 441 break; 442 443 default: 444 DPRINTF("Failed to read CSW: %s, try %d\n", 445 usbd_errstr(error), sc->status_try); 446 447 if (error == USB_ERR_CANCELLED || sc->status_try) { --- 21 unchanged lines hidden (view full) --- 469 sc->lun = lun; 470 sc->dir = data_len ? dir : DIR_NONE; 471 sc->data_ptr = data_ptr; 472 sc->data_len = data_len; 473 sc->data_rem = data_len; 474 sc->data_timeout = (data_timeout + USB_MS_HZ); 475 sc->actlen = 0; 476 sc->cmd_len = cmd_len; |
481 memset(&sc->cbw.CBWCDB, 0, sizeof(sc->cbw.CBWCDB)); 482 memcpy(&sc->cbw.CBWCDB, cmd_ptr, cmd_len); 483 DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw.CBWCDB, ":"); | 477 memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB)); 478 memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len); 479 DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw->CBWCDB, ":"); |
484 485 mtx_lock(&sc->mtx); 486 usbd_transfer_start(sc->xfer[sc->state]); 487 488 while (usbd_transfer_pending(sc->xfer[sc->state])) { 489 cv_wait(&sc->cv, &sc->mtx); 490 } 491 mtx_unlock(&sc->mtx); --- 57 unchanged lines hidden (view full) --- 549 cv_init(&sc->cv, "WBBB"); 550 551 err = usbd_transfer_setup(udev, &iface_index, sc->xfer, bbb_config, 552 ST_MAX, sc, &sc->mtx); 553 if (err) { 554 bbb_detach(sc); 555 return (NULL); 556 } | 480 481 mtx_lock(&sc->mtx); 482 usbd_transfer_start(sc->xfer[sc->state]); 483 484 while (usbd_transfer_pending(sc->xfer[sc->state])) { 485 cv_wait(&sc->cv, &sc->mtx); 486 } 487 mtx_unlock(&sc->mtx); --- 57 unchanged lines hidden (view full) --- 545 cv_init(&sc->cv, "WBBB"); 546 547 err = usbd_transfer_setup(udev, &iface_index, sc->xfer, bbb_config, 548 ST_MAX, sc, &sc->mtx); 549 if (err) { 550 bbb_detach(sc); 551 return (NULL); 552 } |
553 /* store pointer to DMA buffers */ 554 sc->buffer = usbd_xfer_get_frame_buffer( 555 sc->xfer[ST_DATA_RD], 0); 556 sc->cbw = usbd_xfer_get_frame_buffer( 557 sc->xfer[ST_COMMAND], 0); 558 sc->csw = usbd_xfer_get_frame_buffer( 559 sc->xfer[ST_STATUS], 0); 560 |
|
557 return (sc); 558} 559 560static void 561bbb_detach(struct bbb_transfer *sc) 562{ 563 usbd_transfer_unsetup(sc->xfer, ST_MAX); 564 mtx_destroy(&sc->mtx); --- 280 unchanged lines hidden --- | 561 return (sc); 562} 563 564static void 565bbb_detach(struct bbb_transfer *sc) 566{ 567 usbd_transfer_unsetup(sc->xfer, ST_MAX); 568 mtx_destroy(&sc->mtx); --- 280 unchanged lines hidden --- |