From de29f650e65ee47a3b0430555b28f248cbceb4da Mon Sep 17 00:00:00 2001 From: thompsa Date: Mon, 23 Feb 2009 21:07:20 +0000 Subject: Move two missed usb drivers out to the graveyard location under sys/legacy/dev. --- sys/dev/ata/ata-usb.c | 970 -------------------------------------------------- 1 file changed, 970 deletions(-) delete mode 100644 sys/dev/ata/ata-usb.c (limited to 'sys/dev/ata') 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 - * 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 -__FBSDID("$FreeBSD$"); - -#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 - -/* 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); -- cgit v1.1