From owner-p4-projects@FreeBSD.ORG Tue May 19 18:22:42 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 2F3451065676; Tue, 19 May 2009 18:22:42 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DCB0D106566B for ; Tue, 19 May 2009 18:22:41 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id CAA608FC13 for ; Tue, 19 May 2009 18:22:41 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n4JIMfdn087287 for ; Tue, 19 May 2009 18:22:41 GMT (envelope-from jhb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n4JIMfSH087283 for perforce@freebsd.org; Tue, 19 May 2009 18:22:41 GMT (envelope-from jhb@freebsd.org) Date: Tue, 19 May 2009 18:22:41 GMT Message-Id: <200905191822.n4JIMfSH087283@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jhb@freebsd.org using -f From: John Baldwin To: Perforce Change Reviews Cc: Subject: PERFORCE change 162332 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 May 2009 18:22:42 -0000 http://perforce.freebsd.org/chv.cgi?CH=162332 Change 162332 by jhb@jhb_jhbbsd on 2009/05/19 18:22:12 Merge brain-o's. Affected files ... .. //depot/projects/multipass/sys/dev/ata/ata-usb.c#2 integrate .. //depot/projects/multipass/sys/dev/sound/usb/uaudio.c#2 integrate .. //depot/projects/multipass/sys/dev/sound/usb/uaudio.h#2 integrate .. //depot/projects/multipass/sys/dev/sound/usb/uaudio_pcm.c#2 integrate .. //depot/projects/multipass/sys/dev/sound/usb/uaudioreg.h#2 integrate .. //depot/projects/multipass/sys/dev/usb/usb.h#2 integrate .. //depot/projects/multipass/sys/dev/usb/usb_if.m#2 integrate .. //depot/projects/multipass/sys/dev/usb/usbdevs#2 integrate .. //depot/projects/multipass/sys/dev/usb/usbhid.h#2 integrate .. //depot/projects/multipass/sys/modules/usb/Makefile#2 integrate Differences ... ==== //depot/projects/multipass/sys/dev/ata/ata-usb.c#2 (text) ==== @@ -2,6 +2,9 @@ * Copyright (c) 2006 - 2008 Søren Schmidt * All rights reserved. * + * Copyright (c) 2006 Hans Petter Selasky + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,950 +28,1071 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/ata/ata-usb.c,v 1.8 2008/04/10 13:05:05 sos Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/ata/ata-usb.c,v 1.14 2009/03/02 05:37:05 thompsa Exp $"); + +#include "usbdevs.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include -#include "opt_ata.h" -#include -#include -#include -#include -#include #include -#include -#include -#include -#include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include + #include #include +#define ATAUSB_BULK_SIZE (1<<17) + /* Command Block Wrapper */ struct bbb_cbw { - u_int8_t signature[4]; -#define CBWSIGNATURE 0x43425355 + uint8_t signature[4]; +#define CBWSIGNATURE 0x43425355 - u_int8_t tag[4]; - u_int8_t transfer_length[4]; - u_int8_t flags; -#define CBWFLAGS_OUT 0x00 -#define CBWFLAGS_IN 0x80 + uint8_t tag[4]; + uint8_t transfer_length[4]; + uint8_t flags; +#define CBWFLAGS_OUT 0x00 +#define CBWFLAGS_IN 0x80 - u_int8_t lun; - u_int8_t length; -#define CBWCDBLENGTH 16 + uint8_t lun; + uint8_t length; +#define CBWCDBLENGTH 16 - u_int8_t cdb[CBWCDBLENGTH]; -}; + uint8_t cdb[CBWCDBLENGTH]; +} __packed; /* Command Status Wrapper */ struct bbb_csw { - u_int8_t signature[4]; -#define CSWSIGNATURE 0x53425355 + uint8_t signature[4]; +#define CSWSIGNATURE 0x53425355 - u_int8_t tag[4]; - u_int8_t residue[4]; - u_int8_t status; -#define CSWSTATUS_GOOD 0x0 -#define CSWSTATUS_FAILED 0x1 -#define CSWSTATUS_PHASE 0x2 -}; + uint8_t tag[4]; + uint8_t residue[4]; + uint8_t status; +#define CSWSTATUS_GOOD 0x0 +#define CSWSTATUS_FAILED 0x1 +#define CSWSTATUS_PHASE 0x2 +} __packed; /* USB-ATA 'controller' softc */ -struct atausb_softc { - device_t dev; /* base device */ - usbd_interface_handle iface; /* interface */ - int ifaceno; /* interface number */ - u_int8_t bulkin; /* endpoint address's */ - u_int8_t bulkout; - u_int8_t bulkirq; - usbd_pipe_handle bulkin_pipe; /* pipe handle's */ - usbd_pipe_handle bulkout_pipe; - usbd_pipe_handle bulkirq_pipe; - int maxlun; - int timeout; - struct ata_request *ata_request; - usb_device_request_t usb_request; - struct bbb_cbw cbw; - struct bbb_csw csw; +struct atausb2_softc { + struct bbb_cbw cbw; + struct bbb_csw csw; + struct mtx locked_mtx; + + struct ata_channel *locked_ch; + struct ata_channel *restart_ch; + struct ata_request *ata_request; + +#define ATAUSB_T_BBB_RESET1 0 +#define ATAUSB_T_BBB_RESET2 1 +#define ATAUSB_T_BBB_RESET3 2 +#define ATAUSB_T_BBB_COMMAND 3 +#define ATAUSB_T_BBB_DATA_READ 4 +#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 -#define ATAUSB_T_BBB_CBW 0 -#define ATAUSB_T_BBB_DATA 1 -#define ATAUSB_T_BBB_DCLEAR 2 -#define ATAUSB_T_BBB_CSW1 3 -#define ATAUSB_T_BBB_CSW2 4 -#define ATAUSB_T_BBB_SCLEAR 5 -#define ATAUSB_T_BBB_RESET1 6 -#define ATAUSB_T_BBB_RESET2 7 -#define ATAUSB_T_BBB_RESET3 8 -#define ATAUSB_T_MAX 9 - usbd_xfer_handle transfer[ATAUSB_T_MAX]; + struct usb2_xfer *xfer[ATAUSB_T_MAX]; + caddr_t ata_data; + device_t dev; - int state; -#define ATAUSB_S_ATTACH 0 -#define ATAUSB_S_IDLE 1 -#define ATAUSB_S_BBB_COMMAND 2 -#define ATAUSB_S_BBB_DATA 3 -#define ATAUSB_S_BBB_DCLEAR 4 -#define ATAUSB_S_BBB_STATUS1 5 -#define ATAUSB_S_BBB_SCLEAR 6 -#define ATAUSB_S_BBB_STATUS2 7 -#define ATAUSB_S_BBB_RESET1 8 -#define ATAUSB_S_BBB_RESET2 9 -#define ATAUSB_S_BBB_RESET3 10 -#define ATAUSB_S_DETACH 11 + uint32_t timeout; + uint32_t ata_donecount; + uint32_t ata_bytecount; - struct mtx locked_mtx; - struct ata_channel *locked_ch; - struct ata_channel *restart_ch; + uint8_t last_xfer_no; + uint8_t usb2_speed; + uint8_t intr_stalled; + uint8_t maxlun; + uint8_t iface_no; + uint8_t status_try; }; -static int atausbdebug = 0; +static const int atausbdebug = 0; + +/* prototypes */ + +static device_probe_t atausb2_probe; +static device_attach_t atausb2_attach; +static device_detach_t atausb2_detach; + +static usb2_callback_t atausb2_t_bbb_reset1_callback; +static usb2_callback_t atausb2_t_bbb_reset2_callback; +static usb2_callback_t atausb2_t_bbb_reset3_callback; +static usb2_callback_t atausb2_t_bbb_command_callback; +static usb2_callback_t atausb2_t_bbb_data_read_callback; +static usb2_callback_t atausb2_t_bbb_data_rd_cs_callback; +static usb2_callback_t atausb2_t_bbb_data_write_callback; +static usb2_callback_t atausb2_t_bbb_data_wr_cs_callback; +static usb2_callback_t atausb2_t_bbb_status_callback; +static usb2_callback_t atausb2_tr_error; + +static void atausb2_cancel_request(struct atausb2_softc *sc); +static void atausb2_transfer_start(struct atausb2_softc *sc, uint8_t xfer_no); +static void atausb2_t_bbb_data_clear_stall_callback(struct usb2_xfer *xfer, uint8_t next_xfer, uint8_t stall_xfer); +static int ata_usbchannel_begin_transaction(struct ata_request *request); +static int ata_usbchannel_end_transaction(struct ata_request *request); -/* prototypes*/ -static usbd_status atausb_start(struct atausb_softc *sc, usbd_pipe_handle pipe, void *buffer, int buflen, int flags, usbd_xfer_handle xfer); -static usbd_status atausb_ctl_start(struct atausb_softc *sc, usbd_device_handle udev, usb_device_request_t *req, void *buffer, int buflen, int flags, usbd_xfer_handle xfer); -static void atausb_clear_stall(struct atausb_softc *sc, u_int8_t endpt, usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer); -static void atausb_bbb_reset(struct atausb_softc *sc); -static int atausb_bbb_start(struct ata_request *request); -static void atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err); -int ata_usbchannel_begin_transaction(struct ata_request *request); -int ata_usbchannel_end_transaction(struct ata_request *request); +static device_probe_t ata_usbchannel_probe; +static device_attach_t ata_usbchannel_attach; +static device_detach_t ata_usbchannel_detach; +static ata_setmode_t ata_usbchannel_setmode; +static ata_locking_t ata_usbchannel_locking; /* * USB frontend part */ -USB_DECLARE_DRIVER(atausb); -DRIVER_MODULE(atausb, uhub, atausb_driver, atausb_devclass, 0, 0); + +struct usb2_config atausb2_config[ATAUSB_T_BBB_MAX] = { + + [ATAUSB_T_BBB_RESET1] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .mh.bufsize = sizeof(struct usb2_device_request), + .mh.flags = {}, + .mh.callback = &atausb2_t_bbb_reset1_callback, + .mh.timeout = 5000, /* 5 seconds */ + .mh.interval = 500, /* 500 milliseconds */ + }, + + [ATAUSB_T_BBB_RESET2] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .mh.bufsize = sizeof(struct usb2_device_request), + .mh.flags = {}, + .mh.callback = &atausb2_t_bbb_reset2_callback, + .mh.timeout = 5000, /* 5 seconds */ + .mh.interval = 50, /* 50 milliseconds */ + }, + + [ATAUSB_T_BBB_RESET3] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .mh.bufsize = sizeof(struct usb2_device_request), + .mh.flags = {}, + .mh.callback = &atausb2_t_bbb_reset3_callback, + .mh.timeout = 5000, /* 5 seconds */ + .mh.interval = 50, /* 50 milliseconds */ + }, + + [ATAUSB_T_BBB_COMMAND] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .mh.bufsize = sizeof(struct bbb_cbw), + .mh.flags = {}, + .mh.callback = &atausb2_t_bbb_command_callback, + .mh.timeout = 5000, /* 5 seconds */ + }, + + [ATAUSB_T_BBB_DATA_READ] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .mh.bufsize = ATAUSB_BULK_SIZE, + .mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,}, + .mh.callback = &atausb2_t_bbb_data_read_callback, + .mh.timeout = 0, /* overwritten later */ + }, + + [ATAUSB_T_BBB_DATA_RD_CS] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .mh.bufsize = sizeof(struct usb2_device_request), + .mh.flags = {}, + .mh.callback = &atausb2_t_bbb_data_rd_cs_callback, + .mh.timeout = 5000, /* 5 seconds */ + }, + + [ATAUSB_T_BBB_DATA_WRITE] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .mh.bufsize = ATAUSB_BULK_SIZE, + .mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,}, + .mh.callback = &atausb2_t_bbb_data_write_callback, + .mh.timeout = 0, /* overwritten later */ + }, + + [ATAUSB_T_BBB_DATA_WR_CS] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .mh.bufsize = sizeof(struct usb2_device_request), + .mh.flags = {}, + .mh.callback = &atausb2_t_bbb_data_wr_cs_callback, + .mh.timeout = 5000, /* 5 seconds */ + }, + + [ATAUSB_T_BBB_STATUS] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .mh.bufsize = sizeof(struct bbb_csw), + .mh.flags = {.short_xfer_ok = 1,}, + .mh.callback = &atausb2_t_bbb_status_callback, + .mh.timeout = 5000, /* ms */ + }, +}; + +static devclass_t atausb2_devclass; + +static device_method_t atausb2_methods[] = { + DEVMETHOD(device_probe, atausb2_probe), + DEVMETHOD(device_attach, atausb2_attach), + DEVMETHOD(device_detach, atausb2_detach), + {0, 0} +}; + +static driver_t atausb2_driver = { + .name = "atausb", + .methods = atausb2_methods, + .size = sizeof(struct atausb2_softc), +}; + +DRIVER_MODULE(atausb, uhub, atausb2_driver, atausb2_devclass, 0, 0); +MODULE_DEPEND(atausb, usb, 1, 1, 1); MODULE_VERSION(atausb, 1); static int -atausb_match(device_t dev) +atausb2_probe(device_t dev) +{ + struct usb2_attach_arg *uaa = device_get_ivars(dev); + struct usb2_interface_descriptor *id; + + if (uaa->usb2_mode != USB_MODE_HOST) { + return (ENXIO); + } + if (uaa->use_generic == 0) { + /* give other drivers a try first */ + return (ENXIO); + } + id = usb2_get_interface_descriptor(uaa->iface); + if ((!id) || (id->bInterfaceClass != UICLASS_MASS)) { + return (ENXIO); + } + switch (id->bInterfaceSubClass) { + case UISUBCLASS_QIC157: + case UISUBCLASS_RBC: + case UISUBCLASS_SCSI: + case UISUBCLASS_SFF8020I: + case UISUBCLASS_SFF8070I: + case UISUBCLASS_UFI: + switch (id->bInterfaceProtocol) { + case UIPROTO_MASS_CBI: + case UIPROTO_MASS_CBI_I: + case UIPROTO_MASS_BBB: + case UIPROTO_MASS_BBB_OLD: + return (0); + default: + return (0); + } + break; + default: + return (0); + } +} + +static int +atausb2_attach(device_t dev) { - struct usb_attach_arg *uaa = device_get_ivars(dev); - usb_interface_descriptor_t *id; + struct atausb2_softc *sc = device_get_softc(dev); + struct usb2_attach_arg *uaa = device_get_ivars(dev); + struct usb2_interface_descriptor *id; + const char *proto, *subclass; + struct usb2_device_request request; + device_t child; + uint16_t i; + uint8_t maxlun; + uint8_t has_intr; + int err; - if (uaa->iface == NULL) - return UMATCH_NONE; + device_set_usb2_desc(dev); - id = usbd_get_interface_descriptor(uaa->iface); - if (!id || id->bInterfaceClass != UICLASS_MASS) - return UMATCH_NONE; + sc->dev = dev; + sc->maxlun = 0; + sc->locked_ch = NULL; + sc->restart_ch = NULL; + sc->usb2_speed = usb2_get_speed(uaa->device); + mtx_init(&sc->locked_mtx, "ATAUSB lock", NULL, (MTX_DEF | MTX_RECURSE)); - switch (id->bInterfaceSubClass) { - case UISUBCLASS_QIC157: - case UISUBCLASS_RBC: - case UISUBCLASS_SCSI: - case UISUBCLASS_SFF8020I: - case UISUBCLASS_SFF8070I: - case UISUBCLASS_UFI: + id = usb2_get_interface_descriptor(uaa->iface); switch (id->bInterfaceProtocol) { + case UIPROTO_MASS_BBB: + case UIPROTO_MASS_BBB_OLD: + proto = "Bulk-Only"; + break; case UIPROTO_MASS_CBI: + proto = "CBI"; + break; case UIPROTO_MASS_CBI_I: - case UIPROTO_MASS_BBB: - case UIPROTO_MASS_BBB_OLD: - return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; + proto = "CBI with CCI"; + break; + default: + proto = "Unknown"; + } + + switch (id->bInterfaceSubClass) { + case UISUBCLASS_RBC: + subclass = "RBC"; + break; + case UISUBCLASS_QIC157: + case UISUBCLASS_SFF8020I: + case UISUBCLASS_SFF8070I: + subclass = "ATAPI"; + break; + case UISUBCLASS_SCSI: + subclass = "SCSI"; + break; + case UISUBCLASS_UFI: + subclass = "UFI"; + break; default: - return UMATCH_IFACECLASS_IFACESUBCLASS; + subclass = "Unknown"; + } + + has_intr = (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I); + sc->iface_no = id->bInterfaceNumber; + + device_printf(dev, "using %s over %s\n", subclass, proto); + if (strcmp(proto, "Bulk-Only") || + (strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI"))) { + goto detach; + } + err = usb2_transfer_setup(uaa->device, &uaa->info.bIfaceIndex, + sc->xfer, atausb2_config, ATAUSB_T_BBB_MAX, sc, + &sc->locked_mtx); + + /* 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", usb2_errstr(err)); + goto detach; + } + /* get number of devices so we can add matching channels */ + request.bmRequestType = UT_READ_CLASS_INTERFACE; + request.bRequest = 0xfe; /* GET_MAX_LUN; */ + USETW(request.wValue, 0); + USETW(request.wIndex, sc->iface_no); + USETW(request.wLength, sizeof(maxlun)); + err = usb2_do_request(uaa->device, &Giant, &request, &maxlun); + + if (err) { + if (bootverbose) { + device_printf(sc->dev, "get maxlun not supported %s\n", + usb2_errstr(err)); + } + } else { + sc->maxlun = maxlun; + if (bootverbose) { + device_printf(sc->dev, "maxlun=%d\n", sc->maxlun); + } + } + + /* ata channels are children to this USB control device */ + for (i = 0; i <= sc->maxlun; i++) { + if ((child = device_add_child(sc->dev, "ata", + devclass_find_free_unit(ata_devclass, 2))) == NULL) { + device_printf(sc->dev, "failed to add ata child device\n"); + } else + device_set_ivars(child, (void *)(intptr_t)i); } - break; - default: - return UMATCH_IFACECLASS; - } + bus_generic_attach(sc->dev); + + return (0); + +detach: + atausb2_detach(dev); + return (ENXIO); } static int -atausb_attach(device_t dev) +atausb2_detach(device_t dev) { - struct atausb_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_device_handle udev; - usb_device_request_t request; - char devinfo[1024], *proto, *subclass; - u_int8_t maxlun; - int err, i; + struct atausb2_softc *sc = device_get_softc(dev); + device_t *children; + int nchildren, i; + + /* teardown our statemachine */ - sc->dev = dev; - usbd_devinfo(uaa->device, 0, devinfo); - device_set_desc_copy(dev, devinfo); - sc->bulkin = sc->bulkout = sc->bulkirq = -1; - sc->bulkin_pipe = sc->bulkout_pipe= sc->bulkirq_pipe = NULL; - sc->iface = uaa->iface; - sc->ifaceno = uaa->ifaceno; - sc->maxlun = 0; - sc->timeout = 5000; - sc->locked_ch = NULL; - sc->restart_ch = NULL; - mtx_init(&sc->locked_mtx, "ATAUSB lock", NULL, MTX_DEF); + usb2_transfer_unsetup(sc->xfer, ATAUSB_T_MAX); - id = usbd_get_interface_descriptor(sc->iface); - switch (id->bInterfaceProtocol) { - case UIPROTO_MASS_BBB: - case UIPROTO_MASS_BBB_OLD: - proto = "Bulk-Only"; - break; - case UIPROTO_MASS_CBI: - proto = "CBI"; - break; - case UIPROTO_MASS_CBI_I: - proto = "CBI with CCI"; - break; - default: - proto = "Unknown"; - } - switch (id->bInterfaceSubClass) { - case UISUBCLASS_RBC: - subclass = "RBC"; - break; - case UISUBCLASS_QIC157: - case UISUBCLASS_SFF8020I: - case UISUBCLASS_SFF8070I: - subclass = "ATAPI"; - break; - case UISUBCLASS_SCSI: - subclass = "SCSI"; - break; - case UISUBCLASS_UFI: - subclass = "UFI"; - break; - default: - subclass = "Unknown"; - } - device_printf(dev, "using %s over %s\n", subclass, proto); - if (strcmp(proto, "Bulk-Only") || - (strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI"))) - return ENXIO; + /* detach & delete all children, if any */ - for (i = 0 ; i < id->bNumEndpoints ; i++) { - if (!(ed = usbd_interface2endpoint_descriptor(sc->iface, i))) { - device_printf(sc->dev, "could not read endpoint descriptor\n"); - return ENXIO; + if (!device_get_children(dev, &children, &nchildren)) { + for (i = 0; i < nchildren; i++) { + device_delete_child(dev, children[i]); + } + free(children, M_TEMP); } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->bulkin = ed->bEndpointAddress; + mtx_destroy(&sc->locked_mtx); + return (0); +} + +static void +atausb2_transfer_start(struct atausb2_softc *sc, uint8_t xfer_no) +{ + if (atausbdebug) { + device_printf(sc->dev, "BBB transfer %d\n", xfer_no); } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->bulkout = ed->bEndpointAddress; + if (sc->xfer[xfer_no]) { + sc->last_xfer_no = xfer_no; + usb2_transfer_start(sc->xfer[xfer_no]); + } else { + atausb2_cancel_request(sc); } - if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I && - UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { - sc->bulkirq = ed->bEndpointAddress; +} + +static void +atausb2_t_bbb_reset1_callback(struct usb2_xfer *xfer) +{ + struct atausb2_softc *sc = xfer->priv_sc; + struct usb2_device_request req; + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + atausb2_transfer_start(sc, ATAUSB_T_BBB_RESET2); + return; + + case USB_ST_SETUP: + req.bmRequestType = UT_WRITE_CLASS_INTERFACE; + req.bRequest = 0xff; /* bulk-only reset */ + USETW(req.wValue, 0); + req.wIndex[0] = sc->iface_no; + req.wIndex[1] = 0; + USETW(req.wLength, 0); + + usb2_copy_in(xfer->frbuffers, 0, &req, sizeof(req)); + + xfer->frlengths[0] = sizeof(req); + xfer->nframes = 1; + usb2_start_hardware(xfer); + return; + + default: /* Error */ + atausb2_tr_error(xfer); + return; + } - } +} + +static void +atausb2_t_bbb_reset2_callback(struct usb2_xfer *xfer) +{ + atausb2_t_bbb_data_clear_stall_callback(xfer, ATAUSB_T_BBB_RESET3, + ATAUSB_T_BBB_DATA_READ); +} - /* check whether we found at least the endpoints we need */ - if (!sc->bulkin || !sc->bulkout) { - device_printf(sc->dev, "needed endpoints not found (%d,%d)\n", - sc->bulkin, sc->bulkout); - atausb_detach(dev); - return ENXIO; - } +static void +atausb2_t_bbb_reset3_callback(struct usb2_xfer *xfer) +{ + atausb2_t_bbb_data_clear_stall_callback(xfer, ATAUSB_T_BBB_COMMAND, + ATAUSB_T_BBB_DATA_WRITE); +} - /* open the pipes */ - if (usbd_open_pipe(sc->iface, sc->bulkout, - USBD_EXCLUSIVE_USE, &sc->bulkout_pipe)) { - device_printf(sc->dev, "cannot open bulkout pipe (%d)\n", sc->bulkout); - atausb_detach(dev); - return ENXIO; - } - if (usbd_open_pipe(sc->iface, sc->bulkin, - USBD_EXCLUSIVE_USE, &sc->bulkin_pipe)) { - device_printf(sc->dev, "cannot open bulkin pipe (%d)\n", sc->bulkin); - atausb_detach(dev); - return ENXIO; - } - if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I) { - if (usbd_open_pipe(sc->iface, sc->bulkirq, - USBD_EXCLUSIVE_USE, &sc->bulkirq_pipe)) { - device_printf(sc->dev, "cannot open bulkirq pipe (%d)\n", - sc->bulkirq); - atausb_detach(dev); - return ENXIO; - } - } - sc->state = ATAUSB_S_ATTACH; +static void +atausb2_t_bbb_data_clear_stall_callback(struct usb2_xfer *xfer, + uint8_t next_xfer, + uint8_t stall_xfer) +{ + struct atausb2_softc *sc = xfer->priv_sc; - /* alloc needed number of transfer handles */ - for (i = 0; i < ATAUSB_T_MAX; i++) { - sc->transfer[i] = usbd_alloc_xfer(uaa->device); - if (!sc->transfer[i]) { - device_printf(sc->dev, "out of memory\n"); - atausb_detach(dev); - return ENXIO; - } - } + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: +tr_transferred: + atausb2_transfer_start(sc, next_xfer); + return; - /* driver is ready to process requests here */ - sc->state = ATAUSB_S_IDLE; + case USB_ST_SETUP: + if (usb2_clear_stall_callback(xfer, sc->xfer[stall_xfer])) { + goto tr_transferred; + } + return; - /* get number of devices so we can add matching channels */ - usbd_interface2device_handle(sc->iface, &udev); - request.bmRequestType = UT_READ_CLASS_INTERFACE; - request.bRequest = 0xfe; //GET_MAX_LUN; - USETW(request.wValue, 0); - USETW(request.wIndex, sc->ifaceno); - USETW(request.wLength, sizeof(maxlun)); - switch ((err = usbd_do_request(udev, &request, &maxlun))) { - case USBD_NORMAL_COMPLETION: - if (bootverbose) - device_printf(sc->dev, "maxlun=%d\n", maxlun); - sc->maxlun = maxlun; - break; - default: - if (bootverbose) - device_printf(sc->dev, "get maxlun not supported %s\n", - usbd_errstr(err)); - } + default: /* Error */ + atausb2_tr_error(xfer); + return; - /* ata channels are children to this USB control device */ - for (i = 0; i <= sc->maxlun; i++) { - if (!device_add_child(sc->dev, "ata", - devclass_find_free_unit(ata_devclass, 2))) { - device_printf(sc->dev, "failed to attach ata child device\n"); - atausb_detach(dev); - return ENXIO; } - } - bus_generic_attach(sc->dev); - return 0; } -static int -atausb_detach(device_t dev) +static void +atausb2_t_bbb_command_callback(struct usb2_xfer *xfer) { - struct atausb_softc *sc = device_get_softc(dev); - usbd_device_handle udev; - device_t *children; - int nchildren, i; + struct atausb2_softc *sc = xfer->priv_sc; + struct ata_request *request = sc->ata_request; + struct ata_channel *ch; + uint32_t tag; + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + atausb2_transfer_start + (sc, ((request->flags & ATA_R_READ) ? ATAUSB_T_BBB_DATA_READ : + (request->flags & ATA_R_WRITE) ? ATAUSB_T_BBB_DATA_WRITE : + ATAUSB_T_BBB_STATUS)); + return; - /* signal that device is going away */ - sc->state = ATAUSB_S_DETACH; + case USB_ST_SETUP: - /* abort all the pipes in case there are active transfers */ - usbd_interface2device_handle(sc->iface, &udev); - usbd_abort_default_pipe(udev); - if (sc->bulkout_pipe) - usbd_abort_pipe(sc->bulkout_pipe); - if (sc->bulkin_pipe) - usbd_abort_pipe(sc->bulkin_pipe); - if (sc->bulkirq_pipe) - usbd_abort_pipe(sc->bulkirq_pipe); + sc->status_try = 0; - /* detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - device_delete_child(dev, children[i]); - free(children, M_TEMP); - } + if (request) { + ch = device_get_softc(request->parent); - /* free the transfers */ - for (i = 0; i < ATAUSB_T_MAX; i++) - if (sc->transfer[i]) - usbd_free_xfer(sc->transfer[i]); + sc->timeout = (request->timeout * 1000) + 5000; - /* remove all the pipes */ - if (sc->bulkout_pipe) - usbd_close_pipe(sc->bulkout_pipe); - if (sc->bulkin_pipe) - usbd_close_pipe(sc->bulkin_pipe); - if (sc->bulkirq_pipe) - usbd_close_pipe(sc->bulkirq_pipe); + tag = UGETDW(sc->cbw.tag) + 1; - mtx_destroy(&sc->locked_mtx); - return 0; -} + USETDW(sc->cbw.signature, CBWSIGNATURE); + USETDW(sc->cbw.tag, tag); + USETDW(sc->cbw.transfer_length, request->bytecount); + sc->cbw.flags = (request->flags & ATA_R_READ) ? CBWFLAGS_IN : CBWFLAGS_OUT; + sc->cbw.lun = ch->unit; + sc->cbw.length = 16; + bzero(sc->cbw.cdb, 16); + bcopy(request->u.atapi.ccb, sc->cbw.cdb, 12); /* XXX SOS */ + usb2_copy_in(xfer->frbuffers, 0, &sc->cbw, sizeof(sc->cbw)); -/* - * Generic USB transfer routines - */ -static usbd_status -atausb_start(struct atausb_softc *sc, usbd_pipe_handle pipe, - void *buffer, int buflen, int flags, usbd_xfer_handle xfer) -{ - usbd_status err; + xfer->frlengths[0] = sizeof(sc->cbw); + usb2_start_hardware(xfer); + } + return; - if (sc->state == ATAUSB_S_DETACH) - return USBD_NOT_STARTED; + default: /* Error */ + atausb2_tr_error(xfer); + return; - usbd_setup_xfer(xfer, pipe, (void *)sc, buffer, buflen, flags, - sc->timeout, atausb_bbb_finish); - err = usbd_transfer(xfer); - if (err && (err != USBD_IN_PROGRESS)) { - if (atausbdebug) - device_printf(sc->dev, "failed to setup transfer, %s\n", - usbd_errstr(err)); - return err; - } - return USBD_NORMAL_COMPLETION; + } } -static usbd_status -atausb_ctl_start(struct atausb_softc *sc, usbd_device_handle udev, - usb_device_request_t *req, void *buffer, int buflen, int flags, - usbd_xfer_handle xfer) +static void +atausb2_t_bbb_data_read_callback(struct usb2_xfer *xfer) { - usbd_status err; + struct atausb2_softc *sc = xfer->priv_sc; + uint32_t max_bulk = xfer->max_data_length; + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + + usb2_copy_out(xfer->frbuffers, 0, + sc->ata_data, xfer->actlen); + + sc->ata_bytecount -= xfer->actlen; + sc->ata_data += xfer->actlen; + sc->ata_donecount += xfer->actlen; + + if (xfer->actlen < xfer->sumlen) { + /* short transfer */ + sc->ata_bytecount = 0; + } + case USB_ST_SETUP: + + if (atausbdebug > 1) { + device_printf(sc->dev, "%s: max_bulk=%d, ata_bytecount=%d\n", + __FUNCTION__, max_bulk, sc->ata_bytecount); + } + if (sc->ata_bytecount == 0) { + atausb2_transfer_start(sc, ATAUSB_T_BBB_STATUS); + return; + } + if (max_bulk > sc->ata_bytecount) { + max_bulk = sc->ata_bytecount; + } + xfer->timeout = sc->timeout; + xfer->frlengths[0] = max_bulk; + + usb2_start_hardware(xfer); + return; - if (sc->state == ATAUSB_S_DETACH) - return USBD_NOT_STARTED; + default: /* Error */ + if (xfer->error == USB_ERR_CANCELLED) { + atausb2_tr_error(xfer); + } else { + atausb2_transfer_start(sc, ATAUSB_T_BBB_DATA_RD_CS); + } + return; - usbd_setup_default_xfer(xfer, udev, (void *)sc, sc->timeout, req, - buffer, buflen, flags, atausb_bbb_finish); - err = usbd_transfer(xfer); - if (err && (err != USBD_IN_PROGRESS)) { - if (atausbdebug) - device_printf(sc->dev, "failed to setup ctl transfer, %s\n", - usbd_errstr(err)); - return err; - } - return USBD_NORMAL_COMPLETION; + } } static void -atausb_clear_stall(struct atausb_softc *sc, u_int8_t endpt, - usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer) +atausb2_t_bbb_data_rd_cs_callback(struct usb2_xfer *xfer) { - usbd_device_handle udev; - - if (atausbdebug) - device_printf(sc->dev, "clear endpoint 0x%02x stall\n", endpt); - usbd_interface2device_handle(sc->iface, &udev); - sc->state = state; - usbd_clear_endpoint_toggle(pipe); - sc->usb_request.bmRequestType = UT_WRITE_ENDPOINT; - sc->usb_request.bRequest = UR_CLEAR_FEATURE; - USETW(sc->usb_request.wValue, UF_ENDPOINT_HALT); - USETW(sc->usb_request.wIndex, endpt); - USETW(sc->usb_request.wLength, 0); - atausb_ctl_start(sc, udev, &sc->usb_request, NULL, 0, 0, xfer); + atausb2_t_bbb_data_clear_stall_callback(xfer, ATAUSB_T_BBB_STATUS, >>> TRUNCATED FOR MAIL (1000 lines) <<<