Date: Thu, 2 Jul 2009 14:56:53 GMT From: Andre Oppermann <andre@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 165544 for review Message-ID: <200907021456.n62Eur6s005909@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=165544 Change 165544 by andre@andre_flirtbox on 2009/07/02 14:56:13 Integrate some more stuff was missing before. There seems to be a problem with integrations after the cvs->svn switchover. Especially when files are moved or overwritten. It seems to be an artefact of the svn->svc->p4 exporter chain (?). Affected files ... .. //depot/projects/tcp_new/modules/Makefile#4 edit .. //depot/projects/tcp_reass/dev/ata/ata-usb.c#3 integrate .. //depot/projects/tcp_reass/dev/sbni/if_sbni.c#2 integrate .. //depot/projects/tcp_reass/dev/sbni/if_sbni_isa.c#2 integrate .. //depot/projects/tcp_reass/dev/sbni/if_sbni_pci.c#2 integrate .. //depot/projects/tcp_reass/dev/sbni/if_sbnireg.h#2 integrate .. //depot/projects/tcp_reass/dev/sbni/if_sbnivar.h#2 integrate .. //depot/projects/tcp_reass/dev/sound/usb/uaudio.c#2 integrate .. //depot/projects/tcp_reass/dev/sound/usb/uaudio.h#2 integrate .. //depot/projects/tcp_reass/dev/sound/usb/uaudio_pcm.c#2 integrate .. //depot/projects/tcp_reass/dev/sound/usb/uaudioreg.h#2 integrate .. //depot/projects/tcp_reass/dev/usb/usb.h#2 integrate .. //depot/projects/tcp_reass/dev/usb/usb_if.m#2 integrate .. //depot/projects/tcp_reass/dev/usb/usbdevs#4 integrate .. //depot/projects/tcp_reass/dev/usb/usbhid.h#2 integrate .. //depot/projects/tcp_reass/kern/vfs_subr.c#7 integrate .. //depot/projects/tcp_reass/modules/sbni/Makefile#2 integrate .. //depot/projects/tcp_reass/modules/usb/Makefile#2 integrate .. //depot/projects/tcp_reass/netgraph/bluetooth/drivers/ubt/ng_ubt.c#3 integrate .. //depot/projects/tcp_reass/netgraph/bluetooth/drivers/ubt/ng_ubt_var.h#3 integrate .. //depot/projects/tcp_reass/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c#3 integrate .. //depot/projects/tcp_reass/netinet/tcp_reass.c#27 edit Differences ... ==== //depot/projects/tcp_new/modules/Makefile#4 (text+ko) ==== @@ -218,7 +218,6 @@ rc \ rc4 \ re \ - reiserfs \ rl \ rp \ rue \ ==== //depot/projects/tcp_reass/dev/ata/ata-usb.c#3 (text) ==== @@ -2,6 +2,9 @@ * Copyright (c) 2006 - 2008 Søren Schmidt <sos@FreeBSD.org> * 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,1099 @@ */ #include <sys/cdefs.h> -__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.20 2009/06/23 02:19:59 thompsa Exp $"); -#include "opt_ata.h" +#include <sys/stdint.h> +#include <sys/stddef.h> #include <sys/param.h> -#include <sys/conf.h> +#include <sys/queue.h> +#include <sys/types.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/bus.h> +#include <sys/linker_set.h> +#include <sys/module.h> +#include <sys/lock.h> #include <sys/mutex.h> +#include <sys/condvar.h> +#include <sys/sysctl.h> +#include <sys/sx.h> +#include <sys/unistd.h> +#include <sys/callout.h> +#include <sys/malloc.h> +#include <sys/priv.h> +#include <machine/bus.h> + +#include "usbdevs.h" +#include <dev/usb/usb.h> +#include <dev/usb/usbdi.h> + #include <sys/ata.h> -#include <sys/bus.h> -#include <sys/endian.h> -#include <sys/malloc.h> -#include <sys/module.h> +#include <sys/bio.h> #include <sys/sema.h> #include <sys/taskqueue.h> #include <vm/uma.h> -#include <machine/resource.h> -#include <machine/bus.h> -#include <sys/rman.h> -#include <dev/usb/usb_port.h> -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> + #include <dev/ata/ata-all.h> #include <ata_if.h> +#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 usb_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 usb_callback_t atausb2_t_bbb_reset1_callback; +static usb_callback_t atausb2_t_bbb_reset2_callback; +static usb_callback_t atausb2_t_bbb_reset3_callback; +static usb_callback_t atausb2_t_bbb_command_callback; +static usb_callback_t atausb2_t_bbb_data_read_callback; +static usb_callback_t atausb2_t_bbb_data_rd_cs_callback; +static usb_callback_t atausb2_t_bbb_data_write_callback; +static usb_callback_t atausb2_t_bbb_data_wr_cs_callback; +static usb_callback_t atausb2_t_bbb_status_callback; +static usb_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 usb_xfer *xfer, + uint8_t next_xfer, uint8_t stall_xfer, usb_error_t error); +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 usb_config atausb2_config[ATAUSB_T_BBB_MAX] = { + + [ATAUSB_T_BBB_RESET1] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(struct usb_device_request), + .flags = {}, + .callback = &atausb2_t_bbb_reset1_callback, + .timeout = 5000, /* 5 seconds */ + .interval = 500, /* 500 milliseconds */ + }, + + [ATAUSB_T_BBB_RESET2] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(struct usb_device_request), + .flags = {}, + .callback = &atausb2_t_bbb_reset2_callback, + .timeout = 5000, /* 5 seconds */ + .interval = 50, /* 50 milliseconds */ + }, + + [ATAUSB_T_BBB_RESET3] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(struct usb_device_request), + .flags = {}, + .callback = &atausb2_t_bbb_reset3_callback, + .timeout = 5000, /* 5 seconds */ + .interval = 50, /* 50 milliseconds */ + }, + + [ATAUSB_T_BBB_COMMAND] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = sizeof(struct bbb_cbw), + .flags = {}, + .callback = &atausb2_t_bbb_command_callback, + .timeout = 5000, /* 5 seconds */ + }, + + [ATAUSB_T_BBB_DATA_READ] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .bufsize = ATAUSB_BULK_SIZE, + .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,}, + .callback = &atausb2_t_bbb_data_read_callback, + .timeout = 0, /* overwritten later */ + }, + + [ATAUSB_T_BBB_DATA_RD_CS] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(struct usb_device_request), + .flags = {}, + .callback = &atausb2_t_bbb_data_rd_cs_callback, + .timeout = 5000, /* 5 seconds */ + }, + + [ATAUSB_T_BBB_DATA_WRITE] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = ATAUSB_BULK_SIZE, + .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,}, + .callback = &atausb2_t_bbb_data_write_callback, + .timeout = 0, /* overwritten later */ + }, + + [ATAUSB_T_BBB_DATA_WR_CS] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(struct usb_device_request), + .flags = {}, + .callback = &atausb2_t_bbb_data_wr_cs_callback, + .timeout = 5000, /* 5 seconds */ + }, + + [ATAUSB_T_BBB_STATUS] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .bufsize = sizeof(struct bbb_csw), + .flags = {.short_xfer_ok = 1,}, + .callback = &atausb2_t_bbb_status_callback, + .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 usb_attach_arg *uaa = device_get_ivars(dev); + struct usb_interface_descriptor *id; + + if (uaa->usb_mode != USB_MODE_HOST) { + return (ENXIO); + } + if (uaa->use_generic == 0) { + /* give other drivers a try first */ + return (ENXIO); + } + id = usbd_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 usb_attach_arg *uaa = device_get_ivars(dev); + struct usb_interface_descriptor *id; + const char *proto, *subclass; + struct usb_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_usb_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 = usbd_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 = usbd_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 = usbd_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", usbd_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 = usbd_do_request(uaa->device, &Giant, &request, &maxlun); + + if (err) { + if (bootverbose) { + device_printf(sc->dev, "get maxlun not supported %s\n", + usbd_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); + usbd_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; + usbd_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 usb_xfer *xfer, usb_error_t error) +{ + struct atausb2_softc *sc = usbd_xfer_softc(xfer); + struct usb_device_request req; + struct usb_page_cache *pc; + + 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); + + pc = usbd_xfer_get_frame(xfer, 0); + usbd_copy_in(pc, 0, &req, sizeof(req)); + + usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); + usbd_xfer_set_frames(xfer, 1); + usbd_transfer_submit(xfer); + return; + + default: /* Error */ + atausb2_tr_error(xfer, error); + return; + } - } +} + +static void +atausb2_t_bbb_reset2_callback(struct usb_xfer *xfer, usb_error_t error) +{ + atausb2_t_bbb_data_clear_stall_callback(xfer, ATAUSB_T_BBB_RESET3, + ATAUSB_T_BBB_DATA_READ, error); +} - /* 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 usb_xfer *xfer, usb_error_t error) +{ + atausb2_t_bbb_data_clear_stall_callback(xfer, ATAUSB_T_BBB_COMMAND, + ATAUSB_T_BBB_DATA_WRITE, error); +} - /* 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 usb_xfer *xfer, + uint8_t next_xfer, uint8_t stall_xfer, usb_error_t error) +{ + struct atausb2_softc *sc = usbd_xfer_softc(xfer); - /* 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 (usbd_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, error); + 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 usb_xfer *xfer, usb_error_t error) { - struct atausb_softc *sc = device_get_softc(dev); - usbd_device_handle udev; - device_t *children; - int nchildren, i; + struct atausb2_softc *sc = usbd_xfer_softc(xfer); + struct ata_request *request = sc->ata_request; + struct ata_channel *ch; + struct usb_page_cache *pc; + 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 */ + pc = usbd_xfer_get_frame(xfer, 0); + usbd_copy_in(pc, 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; + usbd_xfer_set_frame_len(xfer, 0, sizeof(sc->cbw)); + usbd_transfer_submit(xfer); + } + return; - if (sc->state == ATAUSB_S_DETACH) - return USBD_NOT_STARTED; + default: /* Error */ + atausb2_tr_error(xfer, error); + 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 usb_xfer *xfer, usb_error_t error) { - usbd_status err; + struct atausb2_softc *sc = usbd_xfer_softc(xfer); + uint32_t max_bulk = usbd_xfer_max_len(xfer); + struct usb_page_cache *pc; + int actlen, sumlen; + + usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + + pc = usbd_xfer_get_frame(xfer, 0); + usbd_copy_out(pc, 0, sc->ata_data, actlen); + + sc->ata_bytecount -= actlen; + sc->ata_data += actlen; + sc->ata_donecount += actlen; + + if (actlen < 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; + } + usbd_xfer_set_timeout(xfer, sc->timeout); + usbd_xfer_set_frame_len(xfer, 0, max_bulk); + + usbd_transfer_submit(xfer); + return; >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907021456.n62Eur6s005909>