summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2009-02-23 21:07:20 +0000
committerthompsa <thompsa@FreeBSD.org>2009-02-23 21:07:20 +0000
commitde29f650e65ee47a3b0430555b28f248cbceb4da (patch)
tree950fd630ee5efc2483a3c62d06f19a6246f5a15c /sys/dev/ata
parent40c2eac6aa3328ce690020e0325867fd0ee36d1c (diff)
downloadFreeBSD-src-de29f650e65ee47a3b0430555b28f248cbceb4da.zip
FreeBSD-src-de29f650e65ee47a3b0430555b28f248cbceb4da.tar.gz
Move two missed usb drivers out to the graveyard location under sys/legacy/dev.
Diffstat (limited to 'sys/dev/ata')
-rw-r--r--sys/dev/ata/ata-usb.c970
1 files changed, 0 insertions, 970 deletions
diff --git a/sys/dev/ata/ata-usb.c b/sys/dev/ata/ata-usb.c
deleted file mode 100644
index 5c868b2..0000000
--- a/sys/dev/ata/ata-usb.c
+++ /dev/null
@@ -1,970 +0,0 @@
-/*-
- * Copyright (c) 2006 - 2008 Søren Schmidt <sos@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer,
- * without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#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/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>
-
-/* Command Block Wrapper */
-struct bbb_cbw {
- u_int8_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
-
- u_int8_t lun;
- u_int8_t length;
-#define CBWCDBLENGTH 16
-
- u_int8_t cdb[CBWCDBLENGTH];
-};
-
-/* Command Status Wrapper */
-struct bbb_csw {
- u_int8_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
-};
-
-/* 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;
-
-#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];
-
- 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
-
- struct mtx locked_mtx;
- struct ata_channel *locked_ch;
- struct ata_channel *restart_ch;
-};
-
-static int atausbdebug = 0;
-
-/* 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);
-
-
-/*
- * USB frontend part
- */
-USB_DECLARE_DRIVER(atausb);
-DRIVER_MODULE(atausb, uhub, atausb_driver, atausb_devclass, 0, 0);
-MODULE_VERSION(atausb, 1);
-
-static int
-atausb_match(device_t dev)
-{
- struct usb_attach_arg *uaa = device_get_ivars(dev);
- usb_interface_descriptor_t *id;
-
- if (uaa->iface == NULL)
- return UMATCH_NONE;
-
- id = usbd_get_interface_descriptor(uaa->iface);
- if (!id || id->bInterfaceClass != UICLASS_MASS)
- return UMATCH_NONE;
-
- 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 UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
- default:
- return UMATCH_IFACECLASS_IFACESUBCLASS;
- }
- break;
- default:
- return UMATCH_IFACECLASS;
- }
-}
-
-static int
-atausb_attach(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;
- device_t child;
- char devinfo[1024], *proto, *subclass;
- u_int8_t maxlun;
- int err, i;
-
- 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);
-
- 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;
-
- 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 (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
- (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
- sc->bulkin = ed->bEndpointAddress;
- }
- if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
- (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
- sc->bulkout = ed->bEndpointAddress;
- }
- 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;
- }
- }
-
- /* 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;
- }
-
- /* 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;
-
- /* 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;
- }
- }
-
- /* driver is ready to process requests here */
- sc->state = ATAUSB_S_IDLE;
-
- /* 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));
- }
-
- /* 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);
- }
- bus_generic_attach(sc->dev);
- return 0;
-}
-
-static int
-atausb_detach(device_t dev)
-{
- struct atausb_softc *sc = device_get_softc(dev);
- usbd_device_handle udev;
- device_t *children;
- int nchildren, i;
-
- /* signal that device is going away */
- sc->state = ATAUSB_S_DETACH;
-
- /* 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);
-
- /* 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);
- }
-
- /* free the transfers */
- for (i = 0; i < ATAUSB_T_MAX; i++)
- if (sc->transfer[i])
- usbd_free_xfer(sc->transfer[i]);
-
- /* 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);
-
- mtx_destroy(&sc->locked_mtx);
- return 0;
-}
-
-
-/*
- * 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;
-
- if (sc->state == ATAUSB_S_DETACH)
- return USBD_NOT_STARTED;
-
- 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)
-{
- usbd_status err;
-
- if (sc->state == ATAUSB_S_DETACH)
- return USBD_NOT_STARTED;
-
- 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)
-{
- 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);
-}
-
-
-/*
- * Bulk-Only transport part
- */
-static void
-atausb_bbb_reset(struct atausb_softc *sc)
-{
- usbd_device_handle udev;
-
- if (atausbdebug)
- device_printf(sc->dev, "Bulk Reset\n");
- sc->timeout = 5000;
- sc->state = ATAUSB_S_BBB_RESET1;
- usbd_interface2device_handle(sc->iface, &udev);
- sc->usb_request.bmRequestType = UT_WRITE_CLASS_INTERFACE;
- sc->usb_request.bRequest = 0xff; /* bulk-only reset */
- USETW(sc->usb_request.wValue, 0);
- USETW(sc->usb_request.wIndex, sc->ifaceno);
- USETW(sc->usb_request.wLength, 0);
- atausb_ctl_start(sc, udev, &sc->usb_request, NULL,
- 0, 0, sc->transfer[ATAUSB_T_BBB_RESET1]);
-}
-
-static int
-atausb_bbb_start(struct ata_request *request)
-{
- struct atausb_softc *sc =
- device_get_softc(device_get_parent(request->parent));
- struct ata_channel *ch = device_get_softc(request->parent);
-
- sc->timeout = (request->timeout * 1000) + 5000;
- USETDW(sc->cbw.signature, CBWSIGNATURE);
- USETDW(sc->cbw.tag, UGETDW(sc->cbw.tag) + 1);
- 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 */
- sc->state = ATAUSB_S_BBB_COMMAND;
- if (atausb_start(sc, sc->bulkout_pipe, &sc->cbw, sizeof(struct bbb_cbw),
- 0, sc->transfer[ATAUSB_T_BBB_CBW])) {
- request->result = EIO;
- if (atausbdebug)
- device_printf(request->dev, "cannot setup USB transfer\n");
- atausb_bbb_reset(sc);
- return ATA_OP_FINISHED;
- }
- return ATA_OP_CONTINUES;
-}
-
-static void
-atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv,
- usbd_status err)
-{
- struct atausb_softc *sc = (struct atausb_softc *)priv;
- struct ata_request *request = sc->ata_request;
- usbd_xfer_handle next_xfer;
-
- //device_printf(sc->dev, "BBB state %d: %s\n", sc->state, usbd_errstr(err));
-
- if (sc->state == ATAUSB_S_DETACH) {
- device_printf(sc->dev, "WARNING - device has been removed\n");
- return;
- }
-
- switch (sc->state) {
- case ATAUSB_S_BBB_COMMAND: /* command transport phase */
- if (err) {
- if (atausbdebug)
- device_printf(sc->dev, "failed to send CBW\n");
- request->result = EIO;
- atausb_bbb_reset(sc);
- return;
- }
-
- /* next is data transport phase, setup transfer */
- sc->state = ATAUSB_S_BBB_DATA;
- if (request->flags & ATA_R_READ) {
- if (atausb_start(sc, sc->bulkin_pipe,
- request->data, request->bytecount,
- USBD_SHORT_XFER_OK,
- sc->transfer[ATAUSB_T_BBB_DATA])) {
- request->result = EIO;
- atausb_bbb_reset(sc);
- }
- return;
- }
- if (request->flags & ATA_R_WRITE) {
- if (atausb_start(sc, sc->bulkout_pipe,
- request->data, request->bytecount,
- 0, sc->transfer[ATAUSB_T_BBB_DATA])) {
- request->result = EIO;
- atausb_bbb_reset(sc);
- }
- return;
- }
- /* FALLTHROUGH */
-
- case ATAUSB_S_BBB_DATA: /* data transport phase */
- if (request->flags & (ATA_R_READ | ATA_R_WRITE)) {
- usbd_get_xfer_status(xfer, NULL, NULL, &request->donecount, NULL);
- if (err) {
- if (atausbdebug)
- device_printf(sc->dev, "data %s count %d failed: %s\n",
- (request->flags & ATA_R_READ?"read":"write"),
- request->bytecount, usbd_errstr(err));
- if (err == USBD_STALLED) {
- atausb_clear_stall(sc,
- (request->flags & ATA_R_READ ?
- sc->bulkin : sc->bulkout),
- (request->flags & ATA_R_READ ?
- sc->bulkin_pipe : sc->bulkout_pipe),
- ATAUSB_S_BBB_DCLEAR,
- sc->transfer[ATAUSB_T_BBB_DCLEAR]);
- }
- else {
- request->result = EIO;
- atausb_bbb_reset(sc);
- }
- return;
- }
- }
- /* FALLTHROUGH */
-
- case ATAUSB_S_BBB_DCLEAR: /* stall clear after data phase */
- case ATAUSB_S_BBB_SCLEAR: /* stall clear after status phase */
- if (err) {
- if (atausbdebug)
- device_printf(sc->dev, "bulk%s stall clear failed %s\n",
- (request->flags & ATA_R_READ ? "in" : "out"),
- usbd_errstr(err));
- request->result = EIO;
- atausb_bbb_reset(sc);
- return;
- }
-
- if (sc->state == ATAUSB_S_BBB_COMMAND ||
- sc->state == ATAUSB_S_BBB_DATA ||
- sc->state == ATAUSB_S_BBB_DCLEAR) {
- /* first attempt on status transport phase setup transfer */
- sc->state = ATAUSB_S_BBB_STATUS1;
- next_xfer = sc->transfer[ATAUSB_T_BBB_CSW1];
- }
- else {
- /* second attempt of fetching status */
- sc->state = ATAUSB_S_BBB_STATUS2;
- next_xfer = sc->transfer[ATAUSB_T_BBB_CSW2];
- }
- if (atausb_start(sc, sc->bulkin_pipe, &sc->csw, sizeof(struct bbb_csw),
- USBD_SHORT_XFER_OK, next_xfer)) {
- request->result = EIO;
- atausb_bbb_reset(sc);
- }
- return;
-
- case ATAUSB_S_BBB_STATUS1: /* status transfer first attempt */
- case ATAUSB_S_BBB_STATUS2: /* status transfer second attempt */
- if (err) {
- if (atausbdebug)
- device_printf(sc->dev, "cannot get CSW, %s%s\n",
- usbd_errstr(err),
- sc->state == ATAUSB_S_BBB_STATUS1 ? ", retry":"");
- if (sc->state == ATAUSB_S_BBB_STATUS1) {
- atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe,
- ATAUSB_S_BBB_SCLEAR,
- sc->transfer[ATAUSB_T_BBB_SCLEAR]);
- }
- else {
- request->result = EIO;
- atausb_bbb_reset(sc);
- }
- return;
- }
-
- int residue = UGETDW(sc->csw.residue);
-
- if (!residue &&
- (request->bytecount - request->donecount))
- residue = request->bytecount - request->donecount;
-
- /* check CSW and handle eventual error */
- if (UGETDW(sc->csw.signature) != CSWSIGNATURE) {
- if (atausbdebug)
- device_printf(sc->dev, "bad CSW signature 0x%08x != 0x%08x\n",
- UGETDW(sc->csw.signature), CSWSIGNATURE);
- request->result = EIO;
- atausb_bbb_reset(sc);
- return;
- }
- else if (UGETDW(sc->csw.tag) != UGETDW(sc->cbw.tag)) {
- if (atausbdebug)
- device_printf(sc->dev, "bad CSW tag %d != %d\n",
- UGETDW(sc->csw.tag), UGETDW(sc->cbw.tag));
- request->result = EIO;
- atausb_bbb_reset(sc);
- return;
- }
- else if (sc->csw.status > CSWSTATUS_PHASE) {
- if (atausbdebug)
- device_printf(sc->dev, "bad CSW status %d > %d\n",
- sc->csw.status, CSWSTATUS_PHASE);
- request->result = EIO;
- atausb_bbb_reset(sc);
- return;
- }
- else if (sc->csw.status == CSWSTATUS_PHASE) {
- if (atausbdebug)
- device_printf(sc->dev, "phase error residue = %d\n", residue);
- request->result = EIO;
- atausb_bbb_reset(sc);
- return;
- }
- else if (request->donecount > request->bytecount) {
- if (atausbdebug)
- device_printf(sc->dev, "buffer overrun %d > %d",
- request->donecount, request->bytecount);
- request->result = EIO;
- atausb_bbb_reset(sc);
- return;
- }
- else if (sc->csw.status == CSWSTATUS_FAILED) {
- if (atausbdebug)
- device_printf(sc->dev, "CSWSTATUS_FAILED\n");
- request->error = ATA_E_ATAPI_SENSE_MASK ;
- sc->state = ATAUSB_S_IDLE;
- ata_interrupt(device_get_softc(request->parent));
- return;
- }
- else {
- sc->state = ATAUSB_S_IDLE;
- ata_interrupt(device_get_softc(request->parent));
- return;
- }
- /* NOT REACHED */
-
- case ATAUSB_S_BBB_RESET1:
- if (err)
- if (atausbdebug)
- device_printf(sc->dev,
- "BBB reset failure: %s\n", usbd_errstr(err));
- atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe,
- ATAUSB_S_BBB_RESET2,
- sc->transfer[ATAUSB_T_BBB_RESET2]);
- return;
-
- case ATAUSB_S_BBB_RESET2:
- if (err)
- if (atausbdebug)
- device_printf(sc->dev, "BBB bulkin clear stall failure: %s\n",
- usbd_errstr(err));
- atausb_clear_stall(sc, sc->bulkout, sc->bulkout_pipe,
- ATAUSB_S_BBB_RESET3,
- sc->transfer[ATAUSB_T_BBB_RESET3]);
- return;
-
- case ATAUSB_S_BBB_RESET3:
- if (err)
- if (atausbdebug)
- device_printf(sc->dev, "BBB bulk-out clear stall failure: %s\n",
- usbd_errstr(err));
- sc->state = ATAUSB_S_IDLE;
- if (request) {
- if (err)
- request->result = ENXIO;
- else
- request->result = EIO;
- ata_interrupt(device_get_softc(request->parent));
- }
- return;
-
- default:
- if (atausbdebug)
- device_printf(sc->dev, "unknown state %d", sc->state);
- }
-}
-
-
-/*
- * ATA backend part
- */
-struct atapi_inquiry {
- u_int8_t device_type;
- u_int8_t device_modifier;
- u_int8_t version;
- u_int8_t response_format;
- u_int8_t length;
- u_int8_t reserved[2];
- u_int8_t flags;
- u_int8_t vendor[8];
- u_int8_t product[16];
- u_int8_t revision[4];
- //u_int8_t crap[60];
-};
-
-int
-ata_usbchannel_begin_transaction(struct ata_request *request)
-{
- struct atausb_softc *sc =
- device_get_softc(device_get_parent(request->parent));
-
- if (atausbdebug > 1)
- device_printf(request->dev, "begin_transaction %s\n",
- ata_cmd2str(request));
-
- /* sanity just in case */
- if (sc->state != ATAUSB_S_IDLE) {
- printf("begin is busy (%d)\n", sc->state);
- request->result = EBUSY;
- return ATA_OP_FINISHED;
- }
-
- /* XXX SOS convert the request into the format used, only BBB for now*/
- sc->ata_request = request;
-
- /* ATA/ATAPI IDENTIFY needs special treatment */
- if (!(request->flags & ATA_R_ATAPI)) {
- if (request->u.ata.command != ATA_ATAPI_IDENTIFY) {
- device_printf(request->dev,"%s unsupported\n",ata_cmd2str(request));
- request->result = EIO;
- return ATA_OP_FINISHED;
- }
- request->flags |= ATA_R_ATAPI;
- bzero(request->u.atapi.ccb, 16);
- request->u.atapi.ccb[0] = ATAPI_INQUIRY;
- request->u.atapi.ccb[4] = 255; //sizeof(struct atapi_inquiry);
- request->data += 256; /* arbitrary offset into ata_param */
- request->bytecount = 255; //sizeof(struct atapi_inquiry);
- }
- return atausb_bbb_start(request);
-}
-
-int
-ata_usbchannel_end_transaction(struct ata_request *request)
-{
- if (atausbdebug > 1)
- device_printf(request->dev, "end_transaction %s\n",
- ata_cmd2str(request));
-
- /* XXX SOS convert the request from the format used, only BBB for now*/
-
- /* ATA/ATAPI IDENTIFY needs special treatment */
- if ((request->flags & ATA_R_ATAPI) &&
- (request->u.atapi.ccb[0] == ATAPI_INQUIRY)) {
- struct ata_device *atadev = device_get_softc(request->dev);
- struct atapi_inquiry *inquiry = (struct atapi_inquiry *)request->data;
- u_int16_t *ptr;
-
- /* convert inquiry data into simple ata_param like format */
- atadev->param.config = ATA_PROTO_ATAPI | ATA_PROTO_ATAPI_12;
- atadev->param.config |= (inquiry->device_type & 0x1f) << 8;
- bzero(atadev->param.model, sizeof(atadev->param.model));
- strncpy(atadev->param.model, inquiry->vendor, 8);
- strcpy(atadev->param.model, " ");
- strncpy(atadev->param.model, inquiry->product, 16);
- ptr = (u_int16_t*)(atadev->param.model + sizeof(atadev->param.model));
- while (--ptr >= (u_int16_t*)atadev->param.model)
- *ptr = ntohs(*ptr);
- strncpy(atadev->param.revision, inquiry->revision, 4);
- ptr=(u_int16_t*)(atadev->param.revision+sizeof(atadev->param.revision));
- while (--ptr >= (u_int16_t*)atadev->param.revision)
- *ptr = ntohs(*ptr);
- request->result = 0;
- }
- return ATA_OP_FINISHED;
-}
-
-static int
-ata_usbchannel_probe(device_t dev)
-{
- char buffer[32];
-
- sprintf(buffer, "USB lun %d", (int)(intptr_t)device_get_ivars(dev));
- device_set_desc_copy(dev, buffer);
-
- return 0;
-}
-
-static int
-ata_usbchannel_attach(device_t dev)
-{
- struct ata_channel *ch = device_get_softc(dev);
-
- if (ch->attached)
- return (0);
- ch->attached = 1;
-
- /* initialize the softc basics */
- ch->dev = dev;
- ch->unit = (intptr_t)device_get_ivars(dev);
- ch->state = ATA_IDLE;
- ch->hw.begin_transaction = ata_usbchannel_begin_transaction;
- ch->hw.end_transaction = ata_usbchannel_end_transaction;
- ch->hw.status = NULL;
- ch->hw.command = NULL;
- bzero(&ch->state_mtx, sizeof(struct mtx));
- mtx_init(&ch->state_mtx, "ATA state lock", NULL, MTX_DEF);
- bzero(&ch->queue_mtx, sizeof(struct mtx));
- mtx_init(&ch->queue_mtx, "ATA queue lock", NULL, MTX_DEF);
- TAILQ_INIT(&ch->ata_queue);
-
- /* XXX SOS reset the controller HW, the channel and device(s) */
- //ATA_RESET(dev);
-
- /* probe and attach device on this channel */
- ch->devices = ATA_ATAPI_MASTER;
- if (!ata_delayed_attach)
- ata_identify(dev);
- return 0;
-}
-
-static int
-ata_usbchannel_detach(device_t dev)
-{
- struct ata_channel *ch = device_get_softc(dev);
- device_t *children;
- int nchildren, i;
-
- if (!ch->attached)
- return (0);
- ch->attached = 0;
-
- /* detach & delete all children */
- if (!device_get_children(dev, &children, &nchildren)) {
- for (i = 0; i < nchildren; i++)
- if (children[i])
- device_delete_child(dev, children[i]);
- free(children, M_TEMP);
- }
- mtx_destroy(&ch->state_mtx);
- mtx_destroy(&ch->queue_mtx);
- return 0;
-}
-
-static void
-ata_usbchannel_setmode(device_t parent, device_t dev)
-{
- struct atausb_softc *sc = device_get_softc(GRANDPARENT(dev));
- struct ata_device *atadev = device_get_softc(dev);
- usbd_device_handle udev;
-
- usbd_interface2device_handle(sc->iface, &udev);
- if (usbd_get_speed(udev) == USB_SPEED_HIGH)
- atadev->mode = ATA_USB2;
- else
- atadev->mode = ATA_USB1;
-}
-
-static int
-ata_usbchannel_locking(device_t dev, int flags)
-{
- struct atausb_softc *sc = device_get_softc(device_get_parent(dev));
- struct ata_channel *ch = device_get_softc(dev);
- int res = -1;
-
-
- mtx_lock(&sc->locked_mtx);
- switch (flags) {
- case ATA_LF_LOCK:
- if (sc->locked_ch == NULL)
- sc->locked_ch = ch;
- if (sc->locked_ch != ch)
- sc->restart_ch = ch;
- break;
-
- case ATA_LF_UNLOCK:
- if (sc->locked_ch == ch) {
- sc->locked_ch = NULL;
- if (sc->restart_ch) {
- ch = sc->restart_ch;
- sc->restart_ch = NULL;
- mtx_unlock(&sc->locked_mtx);
- ata_start(ch->dev);
- return res;
- }
- }
- break;
-
- case ATA_LF_WHICH:
- break;
- }
- if (sc->locked_ch)
- res = sc->locked_ch->unit;
- mtx_unlock(&sc->locked_mtx);
- return res;
-}
-
-static device_method_t ata_usbchannel_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, ata_usbchannel_probe),
- DEVMETHOD(device_attach, ata_usbchannel_attach),
- DEVMETHOD(device_detach, ata_usbchannel_detach),
-
- /* ATA methods */
- DEVMETHOD(ata_setmode, ata_usbchannel_setmode),
- DEVMETHOD(ata_locking, ata_usbchannel_locking),
- //DEVMETHOD(ata_reset, ata_usbchannel_reset),
-
- { 0, 0 }
-};
-
-static driver_t ata_usbchannel_driver = {
- "ata",
- ata_usbchannel_methods,
- sizeof(struct ata_channel),
-};
-
-DRIVER_MODULE(ata, atausb, ata_usbchannel_driver, ata_devclass, 0, 0);
-MODULE_DEPEND(atausb, ata, 1, 1, 1);
OpenPOWER on IntegriCloud