PERFORCE change 162332 for review
John Baldwin
jhb at FreeBSD.org
Tue May 19 18:22:42 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=162332
Change 162332 by jhb at 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 <sos at 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,1071 @@
*/
#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.14 2009/03/02 05:37:05 thompsa Exp $");
+
+#include "usbdevs.h"
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_mfunc.h>
+#include <dev/usb/usb_error.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_util.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_request.h>
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_transfer.h>
-#include "opt_ata.h"
-#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/mutex.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 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) <<<
More information about the p4-projects
mailing list