Date: Wed, 13 Sep 2006 12:59:09 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 106054 for review Message-ID: <200609131259.k8DCx9Rj098491@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=106054 Change 106054 by hselasky@hselasky_mini_itx on 2006/09/13 12:58:58 Make ata-usb more compliant with the BBB standard. Remove the interrupt callback and transfers, hence CBI needs to be handled separately. Fix a small bug where the code is returning from attach instead of "goto detach". Add extra check for softc equal to NULL. Double check that the residue is valid. Affected files ... .. //depot/projects/usb/src/sys/dev/ata/ata-usb.c#5 edit Differences ... ==== //depot/projects/usb/src/sys/dev/ata/ata-usb.c#5 (text) ==== @@ -99,11 +99,14 @@ #define ATAUSB_T_BBB_RESET3 2 #define ATAUSB_T_BBB_COMMAND 3 #define ATAUSB_T_BBB_DATA_READ 4 -#define ATAUSB_T_BBB_DATA_WRITE 5 -#define ATAUSB_T_BBB_STATUS 6 -#define ATAUSB_T_BBB_INTERRUPT 7 -#define ATAUSB_T_BBB_I_CLEAR_STALL 8 -#define ATAUSB_T_MAX 9 +#define ATAUSB_T_BBB_DATA_RD_CS 5 +#define ATAUSB_T_BBB_DATA_WRITE 6 +#define ATAUSB_T_BBB_DATA_WR_CS 7 +#define ATAUSB_T_BBB_STATUS 8 +#define ATAUSB_T_BBB_MAX 9 + +#define ATAUSB_T_MAX ATAUSB_T_BBB_MAX + struct usbd_xfer * xfer[ATAUSB_T_MAX]; caddr_t ata_data; device_t dev; @@ -118,6 +121,7 @@ u_int8_t intr_stalled; u_int8_t maxlun; u_int8_t iface_no; + u_int8_t status_try; }; static const int atausbdebug = 0; @@ -144,22 +148,28 @@ atausb_t_bbb_reset3_callback(struct usbd_xfer *xfer); static void +atausb_t_bbb_data_read_clear_stall_callback(struct usbd_xfer *xfer, + u_int8_t next_xfer); +static void +atausb_t_bbb_data_write_clear_stall_callback(struct usbd_xfer *xfer, + u_int8_t next_xfer); +static void atausb_t_bbb_command_callback(struct usbd_xfer *xfer); static void atausb_t_bbb_data_read_callback(struct usbd_xfer *xfer); static void -atausb_t_bbb_data_write_callback(struct usbd_xfer *xfer); +atausb_t_bbb_data_rd_cs(struct usbd_xfer *xfer); static void -atausb_t_bbb_status_callback(struct usbd_xfer *xfer); +atausb_t_bbb_data_write_callback(struct usbd_xfer *xfer); static void -atausb_t_bbb_interrupt_callback(struct usbd_xfer *xfer); +atausb_t_bbb_data_wr_cs(struct usbd_xfer *xfer); static void -atausb_t_bbb_i_clear_stall_callback(struct usbd_xfer *xfer); +atausb_t_bbb_status_callback(struct usbd_xfer *xfer); static void atausb_tr_error(struct usbd_xfer *xfer); @@ -181,7 +191,7 @@ * USB frontend part */ -struct usbd_config atausb_config[ATAUSB_T_MAX] = { +struct usbd_config atausb_config[ATAUSB_T_BBB_MAX] = { [ATAUSB_T_BBB_RESET1] = { .type = UE_CONTROL, @@ -233,6 +243,16 @@ .timeout = 0, /* overwritten later */ }, + [ATAUSB_T_BBB_DATA_RD_CS] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = -1, + .bufsize = sizeof(usb_device_request_t), + .flags = USBD_USE_DMA, + .callback = &atausb_t_bbb_data_rd_cs, + .timeout = 5000, /* 5 seconds */ + }, + [ATAUSB_T_BBB_DATA_WRITE] = { .type = UE_BULK, .endpoint = -1, /* any */ @@ -243,6 +263,16 @@ .timeout = 0, /* overwritten later */ }, + [ATAUSB_T_BBB_DATA_WR_CS] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = -1, + .bufsize = sizeof(usb_device_request_t), + .flags = USBD_USE_DMA, + .callback = &atausb_t_bbb_data_wr_cs, + .timeout = 5000, /* 5 seconds */ + }, + [ATAUSB_T_BBB_STATUS] = { .type = UE_BULK, .endpoint = -1, /* any */ @@ -252,30 +282,6 @@ .callback = &atausb_t_bbb_status_callback, .timeout = 5000, /* ms */ }, - - /* - * the following endpoints are only - * present on CBI devices: - */ - - [ATAUSB_T_BBB_INTERRUPT] = { - .type = UE_INTERRUPT, - .endpoint = -1, /* any */ - .direction = UE_DIR_IN, - .flags = (USBD_USE_DMA|USBD_SHORT_XFER_OK), - .bufsize = 0, /* use wMaxPacketSize */ - .callback = &atausb_t_bbb_interrupt_callback, - }, - - [ATAUSB_T_BBB_I_CLEAR_STALL] = { - .type = UE_CONTROL, - .endpoint = 0x00, /* Control pipe */ - .direction = -1, - .flags = USBD_USE_DMA, - .bufsize = sizeof(usb_device_request_t), - .callback = &atausb_t_bbb_i_clear_stall_callback, - .timeout = 5000, /* ms */ - }, }; static devclass_t atausb_devclass; @@ -347,6 +353,10 @@ u_int8_t has_intr; int err; + if (sc == NULL) { + return ENOMEM; + } + usbd_set_desc(dev, uaa->device); sc->dev = dev; @@ -400,13 +410,16 @@ device_printf(dev, "using %s over %s\n", subclass, proto); if (strcmp(proto, "Bulk-Only") || (strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI"))) { - return ENXIO; + goto detach; } err = usbd_transfer_setup(uaa->device, uaa->iface_index, sc->xfer, atausb_config, - has_intr ? ATAUSB_T_MAX : (ATAUSB_T_MAX-2), sc, + ATAUSB_T_BBB_MAX, sc, &(sc->locked_mtx), &(sc->mem_wait)); + /* skip reset first time */ + sc->last_xfer_no = ATAUSB_T_BBB_COMMAND; + if (err) { device_printf(sc->dev, "could not setup required " "transfers, %s\n", usbd_errstr(err)); @@ -504,13 +517,10 @@ mtx_assert(&(sc->locked_mtx), MA_OWNED); - if (sc->xfer[ATAUSB_T_BBB_INTERRUPT]) { - /* start the interrupt pipe, in case it stopped */ - usbd_transfer_start(sc->xfer[ATAUSB_T_BBB_INTERRUPT]); - } - +#if 0 __callout_reset(&(sc->watchdog), hz, &atausb_watchdog, sc); +#endif mtx_unlock(&(sc->locked_mtx)); return; @@ -519,9 +529,9 @@ static void atausb_transfer_start(struct atausb_softc *sc, u_int8_t xfer_no) { -#if 0 - device_printf(sc->dev, "BBB transfer %d\n", xfer_no); -#endif + if (atausbdebug) { + device_printf(sc->dev, "BBB transfer %d\n", xfer_no); + } sc->last_xfer_no = xfer_no; usbd_transfer_start(sc->xfer[xfer_no]); return; @@ -550,7 +560,8 @@ req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = 0xff; /* bulk-only reset */ USETW(req.wValue, 0); - USETW(req.wIndex, sc->iface_no); + req.wIndex[0] = sc->iface_no; + req.wIndex[1] = 0; USETW(req.wLength, 0); usbd_copy_in(&(xfer->buf_data), 0, &req, sizeof(req)); @@ -562,6 +573,21 @@ static void atausb_t_bbb_reset2_callback(struct usbd_xfer *xfer) { + atausb_t_bbb_data_read_clear_stall_callback(xfer, ATAUSB_T_BBB_RESET3); + return; +} + +static void +atausb_t_bbb_reset3_callback(struct usbd_xfer *xfer) +{ + atausb_t_bbb_data_write_clear_stall_callback(xfer, ATAUSB_T_BBB_COMMAND); + return; +} + +static void +atausb_t_bbb_data_read_clear_stall_callback(struct usbd_xfer *xfer, + u_int8_t next_xfer) +{ struct atausb_softc *sc = xfer->priv_sc; USBD_CHECK_STATUS(xfer); @@ -571,7 +597,7 @@ return; tr_transferred: - atausb_transfer_start(sc, ATAUSB_T_BBB_RESET3); + atausb_transfer_start(sc, next_xfer); return; tr_setup: @@ -581,7 +607,8 @@ } static void -atausb_t_bbb_reset3_callback(struct usbd_xfer *xfer) +atausb_t_bbb_data_write_clear_stall_callback(struct usbd_xfer *xfer, + u_int8_t next_xfer) { struct atausb_softc *sc = xfer->priv_sc; @@ -592,7 +619,7 @@ return; tr_transferred: - atausb_transfer_start(sc, ATAUSB_T_BBB_COMMAND); + atausb_transfer_start(sc, next_xfer); return; tr_setup: @@ -625,6 +652,7 @@ tr_setup: sc->reset_count = 0; + sc->status_try = 0; if (request) { ch = device_get_softc(request->parent); @@ -658,7 +686,11 @@ USBD_CHECK_STATUS(xfer); tr_error: - atausb_tr_error(xfer); + if (xfer->error == USBD_CANCELLED) { + atausb_tr_error(xfer); + } else { + atausb_transfer_start(sc, ATAUSB_T_BBB_DATA_RD_CS); + } return; tr_transferred: @@ -699,6 +731,13 @@ } static void +atausb_t_bbb_data_rd_cs(struct usbd_xfer *xfer) +{ + atausb_t_bbb_data_read_clear_stall_callback(xfer, ATAUSB_T_BBB_STATUS); + return; +} + +static void atausb_t_bbb_data_write_callback(struct usbd_xfer *xfer) { struct atausb_softc *sc = xfer->priv_sc; @@ -707,7 +746,11 @@ USBD_CHECK_STATUS(xfer); tr_error: - atausb_tr_error(xfer); + if (xfer->error == USBD_CANCELLED) { + atausb_tr_error(xfer); + } else { + atausb_transfer_start(sc, ATAUSB_T_BBB_DATA_WR_CS); + } return; tr_transferred: @@ -743,6 +786,13 @@ } static void +atausb_t_bbb_data_wr_cs(struct usbd_xfer *xfer) +{ + atausb_t_bbb_data_write_clear_stall_callback(xfer, ATAUSB_T_BBB_STATUS); + return; +} + +static void atausb_t_bbb_status_callback(struct usbd_xfer *xfer) { struct atausb_softc *sc = xfer->priv_sc; @@ -752,7 +802,13 @@ USBD_CHECK_STATUS(xfer); tr_error: - atausb_tr_error(xfer); + if ((xfer->error == USBD_CANCELLED) || + (sc->status_try)) { + atausb_tr_error(xfer); + } else { + sc->status_try = 1; + atausb_transfer_start(sc, ATAUSB_T_BBB_DATA_RD_CS); + } return; tr_transferred: @@ -773,6 +829,15 @@ residue = (request->bytecount - request->donecount); } + if (residue > request->bytecount) { + if (atausbdebug) { + device_printf(sc->dev, "truncating residue from %d " + "to %d bytes\n", residue, + request->bytecount); + } + residue = request->bytecount; + } + /* check CSW and handle eventual error */ if (UGETDW(sc->csw.signature) != CSWSIGNATURE) { if (atausbdebug) { @@ -837,68 +902,6 @@ } static void -atausb_t_bbb_interrupt_callback(struct usbd_xfer *xfer) -{ - struct atausb_softc *sc = xfer->priv_sc; - - USBD_CHECK_STATUS(xfer); - - tr_transferred: - if (atausbdebug) { - device_printf(sc->dev, "Interrupt transfer " - "complete, %d bytes\n", xfer->actlen); - } - - tr_setup: - if (sc->intr_stalled) { - usbd_transfer_start(sc->xfer[ATAUSB_T_BBB_I_CLEAR_STALL]); - } else { - usbd_start_hardware(xfer); - } - return; - - tr_error: - if (xfer->error != USBD_CANCELLED) { - /* try to clear stall first */ - sc->intr_stalled = 1; - usbd_transfer_start(sc->xfer[ATAUSB_T_BBB_I_CLEAR_STALL]); - } - return; -} - -static void -atausb_t_bbb_i_clear_stall_callback(struct usbd_xfer *xfer) -{ - struct atausb_softc *sc = xfer->priv_sc; - struct usbd_xfer *other_xfer = sc->xfer[ATAUSB_T_BBB_INTERRUPT]; - - USBD_CHECK_STATUS(xfer); - - tr_setup: - /* start clear stall */ - usbd_clear_stall_tr_setup(xfer, other_xfer); - return; - - tr_transferred: - usbd_clear_stall_tr_transferred(xfer, other_xfer); - - sc->intr_stalled = 0; - usbd_transfer_start(other_xfer); - return; - - tr_error: - /* bomb out (wait for watchdog to start - * interrupt transfer again) - */ - sc->intr_stalled = 0; - - if (xfer->error != USBD_CANCELLED) { - device_printf(sc->dev, "Interrupt transfer stopped!\n"); - } - return; -} - -static void atausb_tr_error(struct usbd_xfer *xfer) { struct atausb_softc *sc = xfer->priv_sc;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609131259.k8DCx9Rj098491>