summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb2/controller
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb2/controller')
-rw-r--r--sys/dev/usb2/controller/at91dci.c2467
-rw-r--r--sys/dev/usb2/controller/at91dci.h245
-rw-r--r--sys/dev/usb2/controller/at91dci_atmelarm.c347
-rw-r--r--sys/dev/usb2/controller/atmegadci.c2327
-rw-r--r--sys/dev/usb2/controller/atmegadci.h273
-rw-r--r--sys/dev/usb2/controller/atmegadci_atmelarm.c27
-rw-r--r--sys/dev/usb2/controller/ehci2.c3965
-rw-r--r--sys/dev/usb2/controller/ehci2.h532
-rw-r--r--sys/dev/usb2/controller/ehci2_ixp4xx.c349
-rw-r--r--sys/dev/usb2/controller/ehci2_mbus.c365
-rw-r--r--sys/dev/usb2/controller/ehci2_pci.c487
-rw-r--r--sys/dev/usb2/controller/musb2_otg.c2875
-rw-r--r--sys/dev/usb2/controller/musb2_otg.h407
-rw-r--r--sys/dev/usb2/controller/musb2_otg_atmelarm.c240
-rw-r--r--sys/dev/usb2/controller/ohci2.c2862
-rw-r--r--sys/dev/usb2/controller/ohci2.h366
-rw-r--r--sys/dev/usb2/controller/ohci2_atmelarm.c224
-rw-r--r--sys/dev/usb2/controller/ohci2_pci.c388
-rw-r--r--sys/dev/usb2/controller/uhci2.c3381
-rw-r--r--sys/dev/usb2/controller/uhci2.h321
-rw-r--r--sys/dev/usb2/controller/uhci2_pci.c444
-rw-r--r--sys/dev/usb2/controller/usb2_bus.h104
-rw-r--r--sys/dev/usb2/controller/usb2_controller.c623
-rw-r--r--sys/dev/usb2/controller/usb2_controller.h199
-rw-r--r--sys/dev/usb2/controller/usb2_pci.h39
-rw-r--r--sys/dev/usb2/controller/uss820dci.c2489
-rw-r--r--sys/dev/usb2/controller/uss820dci.h377
-rw-r--r--sys/dev/usb2/controller/uss820dci_atmelarm.c239
-rw-r--r--sys/dev/usb2/controller/uss820dci_pccard.c266
29 files changed, 0 insertions, 27228 deletions
diff --git a/sys/dev/usb2/controller/at91dci.c b/sys/dev/usb2/controller/at91dci.c
deleted file mode 100644
index 501d0c0..0000000
--- a/sys/dev/usb2/controller/at91dci.c
+++ /dev/null
@@ -1,2467 +0,0 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*-
- * Copyright (c) 2007-2008 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-/*
- * This file contains the driver for the AT91 series USB Device
- * Controller
- */
-
-/*
- * Thanks to "David Brownell" for helping out regarding the hardware
- * endpoint profiles.
- */
-
-/*
- * NOTE: The "fifo_bank" is not reset in hardware when the endpoint is
- * reset !
- *
- * NOTE: When the chip detects BUS-reset it will also reset the
- * endpoints, Function-address and more.
- */
-
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_defs.h>
-
-#define USB_DEBUG_VAR at91dcidebug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_transfer.h>
-#include <dev/usb2/core/usb2_device.h>
-#include <dev/usb2/core/usb2_hub.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/at91dci.h>
-
-#define AT9100_DCI_BUS2SC(bus) \
- ((struct at91dci_softc *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((struct at91dci_softc *)0)->sc_bus))))
-
-#define AT9100_DCI_PC2SC(pc) \
- AT9100_DCI_BUS2SC((pc)->tag_parent->info->bus)
-
-#if USB_DEBUG
-static int at91dcidebug = 0;
-
-SYSCTL_NODE(_hw_usb2, OID_AUTO, at91dci, CTLFLAG_RW, 0, "USB at91dci");
-SYSCTL_INT(_hw_usb2_at91dci, OID_AUTO, debug, CTLFLAG_RW,
- &at91dcidebug, 0, "at91dci debug level");
-#endif
-
-#define AT9100_DCI_INTR_ENDPT 1
-
-/* prototypes */
-
-struct usb2_bus_methods at91dci_bus_methods;
-struct usb2_pipe_methods at91dci_device_bulk_methods;
-struct usb2_pipe_methods at91dci_device_ctrl_methods;
-struct usb2_pipe_methods at91dci_device_intr_methods;
-struct usb2_pipe_methods at91dci_device_isoc_fs_methods;
-struct usb2_pipe_methods at91dci_root_ctrl_methods;
-struct usb2_pipe_methods at91dci_root_intr_methods;
-
-static at91dci_cmd_t at91dci_setup_rx;
-static at91dci_cmd_t at91dci_data_rx;
-static at91dci_cmd_t at91dci_data_tx;
-static at91dci_cmd_t at91dci_data_tx_sync;
-static void at91dci_device_done(struct usb2_xfer *, usb2_error_t);
-static void at91dci_do_poll(struct usb2_bus *);
-static void at91dci_root_ctrl_poll(struct at91dci_softc *);
-static void at91dci_standard_done(struct usb2_xfer *);
-
-static usb2_sw_transfer_func_t at91dci_root_intr_done;
-static usb2_sw_transfer_func_t at91dci_root_ctrl_done;
-
-/*
- * NOTE: Some of the bits in the CSR register have inverse meaning so
- * we need a helper macro when acknowledging events:
- */
-#define AT91_CSR_ACK(csr, what) do { \
- (csr) &= ~((AT91_UDP_CSR_FORCESTALL| \
- AT91_UDP_CSR_TXPKTRDY| \
- AT91_UDP_CSR_RXBYTECNT) ^ (what));\
- (csr) |= ((AT91_UDP_CSR_RX_DATA_BK0| \
- AT91_UDP_CSR_RX_DATA_BK1| \
- AT91_UDP_CSR_TXCOMP| \
- AT91_UDP_CSR_RXSETUP| \
- AT91_UDP_CSR_STALLSENT) ^ (what)); \
-} while (0)
-
-/*
- * Here is a list of what the chip supports.
- * Probably it supports more than listed here!
- */
-static const struct usb2_hw_ep_profile
- at91dci_ep_profile[AT91_UDP_EP_MAX] = {
-
- [0] = {
- .max_in_frame_size = 8,
- .max_out_frame_size = 8,
- .is_simplex = 1,
- .support_control = 1,
- },
- [1] = {
- .max_in_frame_size = 64,
- .max_out_frame_size = 64,
- .is_simplex = 1,
- .support_multi_buffer = 1,
- .support_bulk = 1,
- .support_interrupt = 1,
- .support_isochronous = 1,
- .support_in = 1,
- .support_out = 1,
- },
- [2] = {
- .max_in_frame_size = 64,
- .max_out_frame_size = 64,
- .is_simplex = 1,
- .support_multi_buffer = 1,
- .support_bulk = 1,
- .support_interrupt = 1,
- .support_isochronous = 1,
- .support_in = 1,
- .support_out = 1,
- },
- [3] = {
- /* can also do BULK */
- .max_in_frame_size = 8,
- .max_out_frame_size = 8,
- .is_simplex = 1,
- .support_interrupt = 1,
- .support_in = 1,
- .support_out = 1,
- },
- [4] = {
- .max_in_frame_size = 256,
- .max_out_frame_size = 256,
- .is_simplex = 1,
- .support_multi_buffer = 1,
- .support_bulk = 1,
- .support_interrupt = 1,
- .support_isochronous = 1,
- .support_in = 1,
- .support_out = 1,
- },
- [5] = {
- .max_in_frame_size = 256,
- .max_out_frame_size = 256,
- .is_simplex = 1,
- .support_multi_buffer = 1,
- .support_bulk = 1,
- .support_interrupt = 1,
- .support_isochronous = 1,
- .support_in = 1,
- .support_out = 1,
- },
-};
-
-static void
-at91dci_get_hw_ep_profile(struct usb2_device *udev,
- const struct usb2_hw_ep_profile **ppf, uint8_t ep_addr)
-{
- if (ep_addr < AT91_UDP_EP_MAX) {
- *ppf = (at91dci_ep_profile + ep_addr);
- } else {
- *ppf = NULL;
- }
-}
-
-static void
-at91dci_clocks_on(struct at91dci_softc *sc)
-{
- if (sc->sc_flags.clocks_off &&
- sc->sc_flags.port_powered) {
-
- DPRINTFN(5, "\n");
-
- if (sc->sc_clocks_on) {
- (sc->sc_clocks_on) (sc->sc_clocks_arg);
- }
- sc->sc_flags.clocks_off = 0;
-
- /* enable Transceiver */
- AT91_UDP_WRITE_4(sc, AT91_UDP_TXVC, 0);
- }
-}
-
-static void
-at91dci_clocks_off(struct at91dci_softc *sc)
-{
- if (!sc->sc_flags.clocks_off) {
-
- DPRINTFN(5, "\n");
-
- /* disable Transceiver */
- AT91_UDP_WRITE_4(sc, AT91_UDP_TXVC, AT91_UDP_TXVC_DIS);
-
- if (sc->sc_clocks_off) {
- (sc->sc_clocks_off) (sc->sc_clocks_arg);
- }
- sc->sc_flags.clocks_off = 1;
- }
-}
-
-static void
-at91dci_pull_up(struct at91dci_softc *sc)
-{
- /* pullup D+, if possible */
-
- if (!sc->sc_flags.d_pulled_up &&
- sc->sc_flags.port_powered) {
- sc->sc_flags.d_pulled_up = 1;
- (sc->sc_pull_up) (sc->sc_pull_arg);
- }
-}
-
-static void
-at91dci_pull_down(struct at91dci_softc *sc)
-{
- /* pulldown D+, if possible */
-
- if (sc->sc_flags.d_pulled_up) {
- sc->sc_flags.d_pulled_up = 0;
- (sc->sc_pull_down) (sc->sc_pull_arg);
- }
-}
-
-static void
-at91dci_wakeup_peer(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
- uint8_t use_polling;
-
- if (!(sc->sc_flags.status_suspend)) {
- return;
- }
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, AT91_UDP_GSTATE_ESR);
-
- /* wait 8 milliseconds */
- if (use_polling) {
- /* polling */
- DELAY(8000);
- } else {
- /* Wait for reset to complete. */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 125);
- }
-
- AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, 0);
-}
-
-static void
-at91dci_set_address(struct at91dci_softc *sc, uint8_t addr)
-{
- DPRINTFN(5, "addr=%d\n", addr);
-
- AT91_UDP_WRITE_4(sc, AT91_UDP_FADDR, addr |
- AT91_UDP_FADDR_EN);
-}
-
-static uint8_t
-at91dci_setup_rx(struct at91dci_td *td)
-{
- struct at91dci_softc *sc;
- struct usb2_device_request req;
- uint32_t csr;
- uint32_t temp;
- uint16_t count;
-
- /* read out FIFO status */
- csr = bus_space_read_4(td->io_tag, td->io_hdl,
- td->status_reg);
-
- DPRINTFN(5, "csr=0x%08x rem=%u\n", csr, td->remainder);
-
- temp = csr;
- temp &= (AT91_UDP_CSR_RX_DATA_BK0 |
- AT91_UDP_CSR_RX_DATA_BK1 |
- AT91_UDP_CSR_STALLSENT |
- AT91_UDP_CSR_RXSETUP |
- AT91_UDP_CSR_TXCOMP);
-
- if (!(csr & AT91_UDP_CSR_RXSETUP)) {
- /* abort any ongoing transfer */
- if (!td->did_stall) {
- DPRINTFN(5, "stalling\n");
- temp |= AT91_UDP_CSR_FORCESTALL;
- td->did_stall = 1;
- }
- goto not_complete;
- }
- /* get the packet byte count */
- count = (csr & AT91_UDP_CSR_RXBYTECNT) >> 16;
-
- /* verify data length */
- if (count != td->remainder) {
- DPRINTFN(0, "Invalid SETUP packet "
- "length, %d bytes\n", count);
- goto not_complete;
- }
- if (count != sizeof(req)) {
- DPRINTFN(0, "Unsupported SETUP packet "
- "length, %d bytes\n", count);
- goto not_complete;
- }
- /* receive data */
- bus_space_read_multi_1(td->io_tag, td->io_hdl,
- td->fifo_reg, (void *)&req, sizeof(req));
-
- /* copy data into real buffer */
- usb2_copy_in(td->pc, 0, &req, sizeof(req));
-
- td->offset = sizeof(req);
- td->remainder = 0;
-
- /* get pointer to softc */
- sc = AT9100_DCI_PC2SC(td->pc);
-
- /* sneak peek the set address */
- if ((req.bmRequestType == UT_WRITE_DEVICE) &&
- (req.bRequest == UR_SET_ADDRESS)) {
- sc->sc_dv_addr = req.wValue[0] & 0x7F;
- } else {
- sc->sc_dv_addr = 0xFF;
- }
-
- /* sneak peek the endpoint direction */
- if (req.bmRequestType & UE_DIR_IN) {
- csr |= AT91_UDP_CSR_DIR;
- } else {
- csr &= ~AT91_UDP_CSR_DIR;
- }
-
- /* write the direction of the control transfer */
- AT91_CSR_ACK(csr, temp);
- bus_space_write_4(td->io_tag, td->io_hdl,
- td->status_reg, csr);
- return (0); /* complete */
-
-not_complete:
- /* clear interrupts, if any */
- if (temp) {
- DPRINTFN(5, "clearing 0x%08x\n", temp);
- AT91_CSR_ACK(csr, temp);
- bus_space_write_4(td->io_tag, td->io_hdl,
- td->status_reg, csr);
- }
- return (1); /* not complete */
-
-}
-
-static uint8_t
-at91dci_data_rx(struct at91dci_td *td)
-{
- struct usb2_page_search buf_res;
- uint32_t csr;
- uint32_t temp;
- uint16_t count;
- uint8_t to;
- uint8_t got_short;
-
- to = 2; /* don't loop forever! */
- got_short = 0;
-
- /* check if any of the FIFO banks have data */
-repeat:
- /* read out FIFO status */
- csr = bus_space_read_4(td->io_tag, td->io_hdl,
- td->status_reg);
-
- DPRINTFN(5, "csr=0x%08x rem=%u\n", csr, td->remainder);
-
- if (csr & AT91_UDP_CSR_RXSETUP) {
- if (td->remainder == 0) {
- /*
- * We are actually complete and have
- * received the next SETUP
- */
- DPRINTFN(5, "faking complete\n");
- return (0); /* complete */
- }
- /*
- * USB Host Aborted the transfer.
- */
- td->error = 1;
- return (0); /* complete */
- }
- /* Make sure that "STALLSENT" gets cleared */
- temp = csr;
- temp &= AT91_UDP_CSR_STALLSENT;
-
- /* check status */
- if (!(csr & (AT91_UDP_CSR_RX_DATA_BK0 |
- AT91_UDP_CSR_RX_DATA_BK1))) {
- if (temp) {
- /* write command */
- AT91_CSR_ACK(csr, temp);
- bus_space_write_4(td->io_tag, td->io_hdl,
- td->status_reg, csr);
- }
- return (1); /* not complete */
- }
- /* get the packet byte count */
- count = (csr & AT91_UDP_CSR_RXBYTECNT) >> 16;
-
- /* verify the packet byte count */
- if (count != td->max_packet_size) {
- if (count < td->max_packet_size) {
- /* we have a short packet */
- td->short_pkt = 1;
- got_short = 1;
- } else {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- }
- /* verify the packet byte count */
- if (count > td->remainder) {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- while (count > 0) {
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* receive data */
- bus_space_read_multi_1(td->io_tag, td->io_hdl,
- td->fifo_reg, buf_res.buffer, buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* clear status bits */
- if (td->support_multi_buffer) {
- if (td->fifo_bank) {
- td->fifo_bank = 0;
- temp |= AT91_UDP_CSR_RX_DATA_BK1;
- } else {
- td->fifo_bank = 1;
- temp |= AT91_UDP_CSR_RX_DATA_BK0;
- }
- } else {
- temp |= (AT91_UDP_CSR_RX_DATA_BK0 |
- AT91_UDP_CSR_RX_DATA_BK1);
- }
-
- /* write command */
- AT91_CSR_ACK(csr, temp);
- bus_space_write_4(td->io_tag, td->io_hdl,
- td->status_reg, csr);
-
- /*
- * NOTE: We may have to delay a little bit before
- * proceeding after clearing the DATA_BK bits.
- */
-
- /* check if we are complete */
- if ((td->remainder == 0) || got_short) {
- if (td->short_pkt) {
- /* we are complete */
- return (0);
- }
- /* else need to receive a zero length packet */
- }
- if (--to) {
- goto repeat;
- }
- return (1); /* not complete */
-}
-
-static uint8_t
-at91dci_data_tx(struct at91dci_td *td)
-{
- struct usb2_page_search buf_res;
- uint32_t csr;
- uint32_t temp;
- uint16_t count;
- uint8_t to;
-
- to = 2; /* don't loop forever! */
-
-repeat:
-
- /* read out FIFO status */
- csr = bus_space_read_4(td->io_tag, td->io_hdl,
- td->status_reg);
-
- DPRINTFN(5, "csr=0x%08x rem=%u\n", csr, td->remainder);
-
- if (csr & AT91_UDP_CSR_RXSETUP) {
- /*
- * The current transfer was aborted
- * by the USB Host
- */
- td->error = 1;
- return (0); /* complete */
- }
- /* Make sure that "STALLSENT" gets cleared */
- temp = csr;
- temp &= AT91_UDP_CSR_STALLSENT;
-
- if (csr & AT91_UDP_CSR_TXPKTRDY) {
- if (temp) {
- /* write command */
- AT91_CSR_ACK(csr, temp);
- bus_space_write_4(td->io_tag, td->io_hdl,
- td->status_reg, csr);
- }
- return (1); /* not complete */
- } else {
- /* clear TXCOMP and set TXPKTRDY */
- temp |= (AT91_UDP_CSR_TXCOMP |
- AT91_UDP_CSR_TXPKTRDY);
- }
-
- count = td->max_packet_size;
- if (td->remainder < count) {
- /* we have a short packet */
- td->short_pkt = 1;
- count = td->remainder;
- }
- while (count > 0) {
-
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* transmit data */
- bus_space_write_multi_1(td->io_tag, td->io_hdl,
- td->fifo_reg, buf_res.buffer, buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* write command */
- AT91_CSR_ACK(csr, temp);
- bus_space_write_4(td->io_tag, td->io_hdl,
- td->status_reg, csr);
-
- /* check remainder */
- if (td->remainder == 0) {
- if (td->short_pkt) {
- return (0); /* complete */
- }
- /* else we need to transmit a short packet */
- }
- if (--to) {
- goto repeat;
- }
- return (1); /* not complete */
-}
-
-static uint8_t
-at91dci_data_tx_sync(struct at91dci_td *td)
-{
- struct at91dci_softc *sc;
- uint32_t csr;
- uint32_t temp;
-
-#if 0
-repeat:
-#endif
-
- /* read out FIFO status */
- csr = bus_space_read_4(td->io_tag, td->io_hdl,
- td->status_reg);
-
- DPRINTFN(5, "csr=0x%08x\n", csr);
-
- if (csr & AT91_UDP_CSR_RXSETUP) {
- DPRINTFN(5, "faking complete\n");
- /* Race condition */
- return (0); /* complete */
- }
- temp = csr;
- temp &= (AT91_UDP_CSR_STALLSENT |
- AT91_UDP_CSR_TXCOMP);
-
- /* check status */
- if (csr & AT91_UDP_CSR_TXPKTRDY) {
- goto not_complete;
- }
- if (!(csr & AT91_UDP_CSR_TXCOMP)) {
- goto not_complete;
- }
- sc = AT9100_DCI_PC2SC(td->pc);
- if (sc->sc_dv_addr != 0xFF) {
- /*
- * The AT91 has a special requirement with regard to
- * setting the address and that is to write the new
- * address before clearing TXCOMP:
- */
- at91dci_set_address(sc, sc->sc_dv_addr);
- }
- /* write command */
- AT91_CSR_ACK(csr, temp);
- bus_space_write_4(td->io_tag, td->io_hdl,
- td->status_reg, csr);
-
- return (0); /* complete */
-
-not_complete:
- if (temp) {
- /* write command */
- AT91_CSR_ACK(csr, temp);
- bus_space_write_4(td->io_tag, td->io_hdl,
- td->status_reg, csr);
- }
- return (1); /* not complete */
-}
-
-static uint8_t
-at91dci_xfer_do_fifo(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc;
- struct at91dci_td *td;
- uint8_t temp;
-
- DPRINTFN(9, "\n");
-
- td = xfer->td_transfer_cache;
- while (1) {
- if ((td->func) (td)) {
- /* operation in progress */
- break;
- }
- if (((void *)td) == xfer->td_transfer_last) {
- goto done;
- }
- if (td->error) {
- goto done;
- } else if (td->remainder > 0) {
- /*
- * We had a short transfer. If there is no alternate
- * next, stop processing !
- */
- if (!td->alt_next) {
- goto done;
- }
- }
- /*
- * Fetch the next transfer descriptor and transfer
- * some flags to the next transfer descriptor
- */
- temp = 0;
- if (td->fifo_bank)
- temp |= 1;
- td = td->obj_next;
- xfer->td_transfer_cache = td;
- if (temp & 1)
- td->fifo_bank = 1;
- }
- return (1); /* not complete */
-
-done:
- sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
- temp = (xfer->endpoint & UE_ADDR);
-
- /* update FIFO bank flag and multi buffer */
- if (td->fifo_bank) {
- sc->sc_ep_flags[temp].fifo_bank = 1;
- } else {
- sc->sc_ep_flags[temp].fifo_bank = 0;
- }
-
- /* compute all actual lengths */
-
- at91dci_standard_done(xfer);
-
- return (0); /* complete */
-}
-
-static void
-at91dci_interrupt_poll(struct at91dci_softc *sc)
-{
- struct usb2_xfer *xfer;
-
-repeat:
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- if (!at91dci_xfer_do_fifo(xfer)) {
- /* queue has been modified */
- goto repeat;
- }
- }
-}
-
-void
-at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on)
-{
- DPRINTFN(5, "vbus = %u\n", is_on);
-
- USB_BUS_LOCK(&sc->sc_bus);
- if (is_on) {
- if (!sc->sc_flags.status_vbus) {
- sc->sc_flags.status_vbus = 1;
-
- /* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &at91dci_root_intr_done);
- }
- } else {
- if (sc->sc_flags.status_vbus) {
- sc->sc_flags.status_vbus = 0;
- sc->sc_flags.status_bus_reset = 0;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- /* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &at91dci_root_intr_done);
- }
- }
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-void
-at91dci_interrupt(struct at91dci_softc *sc)
-{
- uint32_t status;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- status = AT91_UDP_READ_4(sc, AT91_UDP_ISR);
- status &= AT91_UDP_INT_DEFAULT;
-
- if (!status) {
- USB_BUS_UNLOCK(&sc->sc_bus);
- return;
- }
- /* acknowledge interrupts */
-
- AT91_UDP_WRITE_4(sc, AT91_UDP_ICR, status);
-
- /* check for any bus state change interrupts */
-
- if (status & AT91_UDP_INT_BUS) {
-
- DPRINTFN(5, "real bus interrupt 0x%08x\n", status);
-
- if (status & AT91_UDP_INT_END_BR) {
-
- /* set correct state */
- sc->sc_flags.status_bus_reset = 1;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- /* disable resume interrupt */
- AT91_UDP_WRITE_4(sc, AT91_UDP_IDR,
- AT91_UDP_INT_RXRSM);
- /* enable suspend interrupt */
- AT91_UDP_WRITE_4(sc, AT91_UDP_IER,
- AT91_UDP_INT_RXSUSP);
- }
- /*
- * If RXRSM and RXSUSP is set at the same time we interpret
- * that like RESUME. Resume is set when there is at least 3
- * milliseconds of inactivity on the USB BUS.
- */
- if (status & AT91_UDP_INT_RXRSM) {
- if (sc->sc_flags.status_suspend) {
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 1;
-
- /* disable resume interrupt */
- AT91_UDP_WRITE_4(sc, AT91_UDP_IDR,
- AT91_UDP_INT_RXRSM);
- /* enable suspend interrupt */
- AT91_UDP_WRITE_4(sc, AT91_UDP_IER,
- AT91_UDP_INT_RXSUSP);
- }
- } else if (status & AT91_UDP_INT_RXSUSP) {
- if (!sc->sc_flags.status_suspend) {
- sc->sc_flags.status_suspend = 1;
- sc->sc_flags.change_suspend = 1;
-
- /* disable suspend interrupt */
- AT91_UDP_WRITE_4(sc, AT91_UDP_IDR,
- AT91_UDP_INT_RXSUSP);
-
- /* enable resume interrupt */
- AT91_UDP_WRITE_4(sc, AT91_UDP_IER,
- AT91_UDP_INT_RXRSM);
- }
- }
- /* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &at91dci_root_intr_done);
- }
- /* check for any endpoint interrupts */
-
- if (status & AT91_UDP_INT_EPS) {
-
- DPRINTFN(5, "real endpoint interrupt 0x%08x\n", status);
-
- at91dci_interrupt_poll(sc);
- }
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-static void
-at91dci_setup_standard_chain_sub(struct at91dci_std_temp *temp)
-{
- struct at91dci_td *td;
-
- /* get current Transfer Descriptor */
- td = temp->td_next;
- temp->td = td;
-
- /* prepare for next TD */
- temp->td_next = td->obj_next;
-
- /* fill out the Transfer Descriptor */
- td->func = temp->func;
- td->pc = temp->pc;
- td->offset = temp->offset;
- td->remainder = temp->len;
- td->fifo_bank = 0;
- td->error = 0;
- td->did_stall = 0;
- td->short_pkt = temp->short_pkt;
- td->alt_next = temp->setup_alt_next;
-}
-
-static void
-at91dci_setup_standard_chain(struct usb2_xfer *xfer)
-{
- struct at91dci_std_temp temp;
- struct at91dci_softc *sc;
- struct at91dci_td *td;
- uint32_t x;
- uint8_t ep_no;
- uint8_t need_sync;
-
- DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
- xfer->address, UE_GET_ADDR(xfer->endpoint),
- xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
-
- temp.max_frame_size = xfer->max_frame_size;
-
- td = xfer->td_start[0];
- xfer->td_transfer_first = td;
- xfer->td_transfer_cache = td;
-
- /* setup temp */
-
- temp.td = NULL;
- temp.td_next = xfer->td_start[0];
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.offset = 0;
-
- sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
- ep_no = (xfer->endpoint & UE_ADDR);
-
- /* check if we should prepend a setup message */
-
- if (xfer->flags_int.control_xfr) {
- if (xfer->flags_int.control_hdr) {
-
- temp.func = &at91dci_setup_rx;
- temp.len = xfer->frlengths[0];
- temp.pc = xfer->frbuffers + 0;
- temp.short_pkt = temp.len ? 1 : 0;
-
- at91dci_setup_standard_chain_sub(&temp);
- }
- x = 1;
- } else {
- x = 0;
- }
-
- if (x != xfer->nframes) {
- if (xfer->endpoint & UE_DIR_IN) {
- temp.func = &at91dci_data_tx;
- need_sync = 1;
- } else {
- temp.func = &at91dci_data_rx;
- need_sync = 0;
- }
-
- /* setup "pc" pointer */
- temp.pc = xfer->frbuffers + x;
- } else {
- need_sync = 0;
- }
- while (x != xfer->nframes) {
-
- /* DATA0 / DATA1 message */
-
- temp.len = xfer->frlengths[x];
-
- x++;
-
- if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
- }
- if (temp.len == 0) {
-
- /* make sure that we send an USB packet */
-
- temp.short_pkt = 0;
-
- } else {
-
- /* regular data transfer */
-
- temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1;
- }
-
- at91dci_setup_standard_chain_sub(&temp);
-
- if (xfer->flags_int.isochronous_xfr) {
- temp.offset += temp.len;
- } else {
- /* get next Page Cache pointer */
- temp.pc = xfer->frbuffers + x;
- }
- }
-
- /* always setup a valid "pc" pointer for status and sync */
- temp.pc = xfer->frbuffers + 0;
-
- /* check if we need to sync */
- if (need_sync && xfer->flags_int.control_xfr) {
-
- /* we need a SYNC point after TX */
- temp.func = &at91dci_data_tx_sync;
- temp.len = 0;
- temp.short_pkt = 0;
-
- at91dci_setup_standard_chain_sub(&temp);
- }
- /* check if we should append a status stage */
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- /*
- * Send a DATA1 message and invert the current
- * endpoint direction.
- */
- if (xfer->endpoint & UE_DIR_IN) {
- temp.func = &at91dci_data_rx;
- need_sync = 0;
- } else {
- temp.func = &at91dci_data_tx;
- need_sync = 1;
- }
- temp.len = 0;
- temp.short_pkt = 0;
-
- at91dci_setup_standard_chain_sub(&temp);
- if (need_sync) {
- /* we need a SYNC point after TX */
- temp.func = &at91dci_data_tx_sync;
- temp.len = 0;
- temp.short_pkt = 0;
-
- at91dci_setup_standard_chain_sub(&temp);
- }
- }
- /* must have at least one frame! */
- td = temp.td;
- xfer->td_transfer_last = td;
-
- /* setup the correct fifo bank */
- if (sc->sc_ep_flags[ep_no].fifo_bank) {
- td = xfer->td_transfer_first;
- td->fifo_bank = 1;
- }
-}
-
-static void
-at91dci_timeout(void *arg)
-{
- struct usb2_xfer *xfer = arg;
-
- DPRINTF("xfer=%p\n", xfer);
-
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- /* transfer is transferred */
- at91dci_device_done(xfer, USB_ERR_TIMEOUT);
-}
-
-static void
-at91dci_start_standard_chain(struct usb2_xfer *xfer)
-{
- DPRINTFN(9, "\n");
-
- /* poll one time */
- if (at91dci_xfer_do_fifo(xfer)) {
-
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
- uint8_t ep_no = xfer->endpoint & UE_ADDR;
-
- /*
- * Only enable the endpoint interrupt when we are actually
- * waiting for data, hence we are dealing with level
- * triggered interrupts !
- */
- AT91_UDP_WRITE_4(sc, AT91_UDP_IER, AT91_UDP_INT_EP(ep_no));
-
- DPRINTFN(15, "enable interrupts on endpoint %d\n", ep_no);
-
- /* put transfer on interrupt queue */
- usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
-
- /* start timeout, if any */
- if (xfer->timeout != 0) {
- usb2_transfer_timeout_ms(xfer,
- &at91dci_timeout, xfer->timeout);
- }
- }
-}
-
-static void
-at91dci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
- DPRINTFN(9, "\n");
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- at91dci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
- /* set port bit */
- sc->sc_hub_idata[0] = 0x02; /* we only have one port */
-
-done:
- return;
-}
-
-static usb2_error_t
-at91dci_standard_done_sub(struct usb2_xfer *xfer)
-{
- struct at91dci_td *td;
- uint32_t len;
- uint8_t error;
-
- DPRINTFN(9, "\n");
-
- td = xfer->td_transfer_cache;
-
- do {
- len = td->remainder;
-
- if (xfer->aframes != xfer->nframes) {
- /*
- * Verify the length and subtract
- * the remainder from "frlengths[]":
- */
- if (len > xfer->frlengths[xfer->aframes]) {
- td->error = 1;
- } else {
- xfer->frlengths[xfer->aframes] -= len;
- }
- }
- /* Check for transfer error */
- if (td->error) {
- /* the transfer is finished */
- error = 1;
- td = NULL;
- break;
- }
- /* Check for short transfer */
- if (len > 0) {
- if (xfer->flags_int.short_frames_ok) {
- /* follow alt next */
- if (td->alt_next) {
- td = td->obj_next;
- } else {
- td = NULL;
- }
- } else {
- /* the transfer is finished */
- td = NULL;
- }
- error = 0;
- break;
- }
- td = td->obj_next;
-
- /* this USB frame is complete */
- error = 0;
- break;
-
- } while (0);
-
- /* update transfer cache */
-
- xfer->td_transfer_cache = td;
-
- return (error ?
- USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION);
-}
-
-static void
-at91dci_standard_done(struct usb2_xfer *xfer)
-{
- usb2_error_t err = 0;
-
- DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
- /* reset scanner */
-
- xfer->td_transfer_cache = xfer->td_transfer_first;
-
- if (xfer->flags_int.control_xfr) {
-
- if (xfer->flags_int.control_hdr) {
-
- err = at91dci_standard_done_sub(xfer);
- }
- xfer->aframes = 1;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
- while (xfer->aframes != xfer->nframes) {
-
- err = at91dci_standard_done_sub(xfer);
- xfer->aframes++;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- err = at91dci_standard_done_sub(xfer);
- }
-done:
- at91dci_device_done(xfer, err);
-}
-
-/*------------------------------------------------------------------------*
- * at91dci_device_done
- *
- * NOTE: this function can be called more than one time on the
- * same USB transfer!
- *------------------------------------------------------------------------*/
-static void
-at91dci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
- uint8_t ep_no;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
- xfer, xfer->pipe, error);
-
- if (xfer->flags_int.usb2_mode == USB_MODE_DEVICE) {
- ep_no = (xfer->endpoint & UE_ADDR);
-
- /* disable endpoint interrupt */
- AT91_UDP_WRITE_4(sc, AT91_UDP_IDR, AT91_UDP_INT_EP(ep_no));
-
- DPRINTFN(15, "disable interrupts on endpoint %d\n", ep_no);
- }
- /* dequeue transfer and start next transfer */
- usb2_transfer_done(xfer, error);
-}
-
-static void
-at91dci_set_stall(struct usb2_device *udev, struct usb2_xfer *xfer,
- struct usb2_pipe *pipe)
-{
- struct at91dci_softc *sc;
- uint32_t csr_val;
- uint8_t csr_reg;
-
- USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
-
- DPRINTFN(5, "pipe=%p\n", pipe);
-
- if (xfer) {
- /* cancel any ongoing transfers */
- at91dci_device_done(xfer, USB_ERR_STALLED);
- }
- /* set FORCESTALL */
- sc = AT9100_DCI_BUS2SC(udev->bus);
- csr_reg = (pipe->edesc->bEndpointAddress & UE_ADDR);
- csr_reg = AT91_UDP_CSR(csr_reg);
- csr_val = AT91_UDP_READ_4(sc, csr_reg);
- AT91_CSR_ACK(csr_val, AT91_UDP_CSR_FORCESTALL);
- AT91_UDP_WRITE_4(sc, csr_reg, csr_val);
-}
-
-static void
-at91dci_clear_stall_sub(struct at91dci_softc *sc, uint8_t ep_no,
- uint8_t ep_type, uint8_t ep_dir)
-{
- const struct usb2_hw_ep_profile *pf;
- uint32_t csr_val;
- uint32_t temp;
- uint8_t csr_reg;
- uint8_t to;
-
- if (ep_type == UE_CONTROL) {
- /* clearing stall is not needed */
- return;
- }
- /* compute CSR register offset */
- csr_reg = AT91_UDP_CSR(ep_no);
-
- /* compute default CSR value */
- csr_val = 0;
- AT91_CSR_ACK(csr_val, 0);
-
- /* disable endpoint */
- AT91_UDP_WRITE_4(sc, csr_reg, csr_val);
-
- /* get endpoint profile */
- at91dci_get_hw_ep_profile(NULL, &pf, ep_no);
-
- /* reset FIFO */
- AT91_UDP_WRITE_4(sc, AT91_UDP_RST, AT91_UDP_RST_EP(ep_no));
- AT91_UDP_WRITE_4(sc, AT91_UDP_RST, 0);
-
- /*
- * NOTE: One would assume that a FIFO reset would release the
- * FIFO banks aswell, but it doesn't! We have to do this
- * manually!
- */
-
- /* release FIFO banks, if any */
- for (to = 0; to != 2; to++) {
-
- /* get csr value */
- csr_val = AT91_UDP_READ_4(sc, csr_reg);
-
- if (csr_val & (AT91_UDP_CSR_RX_DATA_BK0 |
- AT91_UDP_CSR_RX_DATA_BK1)) {
- /* clear status bits */
- if (pf->support_multi_buffer) {
- if (sc->sc_ep_flags[ep_no].fifo_bank) {
- sc->sc_ep_flags[ep_no].fifo_bank = 0;
- temp = AT91_UDP_CSR_RX_DATA_BK1;
- } else {
- sc->sc_ep_flags[ep_no].fifo_bank = 1;
- temp = AT91_UDP_CSR_RX_DATA_BK0;
- }
- } else {
- temp = (AT91_UDP_CSR_RX_DATA_BK0 |
- AT91_UDP_CSR_RX_DATA_BK1);
- }
- } else {
- temp = 0;
- }
-
- /* clear FORCESTALL */
- temp |= AT91_UDP_CSR_STALLSENT;
-
- AT91_CSR_ACK(csr_val, temp);
- AT91_UDP_WRITE_4(sc, csr_reg, csr_val);
- }
-
- /* compute default CSR value */
- csr_val = 0;
- AT91_CSR_ACK(csr_val, 0);
-
- /* enable endpoint */
- csr_val &= ~AT91_UDP_CSR_ET_MASK;
- csr_val |= AT91_UDP_CSR_EPEDS;
-
- if (ep_type == UE_CONTROL) {
- csr_val |= AT91_UDP_CSR_ET_CTRL;
- } else {
- if (ep_type == UE_BULK) {
- csr_val |= AT91_UDP_CSR_ET_BULK;
- } else if (ep_type == UE_INTERRUPT) {
- csr_val |= AT91_UDP_CSR_ET_INT;
- } else {
- csr_val |= AT91_UDP_CSR_ET_ISO;
- }
- if (ep_dir & UE_DIR_IN) {
- csr_val |= AT91_UDP_CSR_ET_DIR_IN;
- }
- }
-
- /* enable endpoint */
- AT91_UDP_WRITE_4(sc, AT91_UDP_CSR(ep_no), csr_val);
-}
-
-static void
-at91dci_clear_stall(struct usb2_device *udev, struct usb2_pipe *pipe)
-{
- struct at91dci_softc *sc;
- struct usb2_endpoint_descriptor *ed;
-
- DPRINTFN(5, "pipe=%p\n", pipe);
-
- USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
-
- /* check mode */
- if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
- /* get softc */
- sc = AT9100_DCI_BUS2SC(udev->bus);
-
- /* get endpoint descriptor */
- ed = pipe->edesc;
-
- /* reset endpoint */
- at91dci_clear_stall_sub(sc,
- (ed->bEndpointAddress & UE_ADDR),
- (ed->bmAttributes & UE_XFERTYPE),
- (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT)));
-}
-
-usb2_error_t
-at91dci_init(struct at91dci_softc *sc)
-{
- uint32_t csr_val;
- uint8_t n;
-
- DPRINTF("start\n");
-
- /* set up the bus structure */
- sc->sc_bus.usbrev = USB_REV_1_1;
- sc->sc_bus.methods = &at91dci_bus_methods;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* turn on clocks */
-
- if (sc->sc_clocks_on) {
- (sc->sc_clocks_on) (sc->sc_clocks_arg);
- }
- /* wait a little for things to stabilise */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
-
- /* disable and clear all interrupts */
-
- AT91_UDP_WRITE_4(sc, AT91_UDP_IDR, 0xFFFFFFFF);
- AT91_UDP_WRITE_4(sc, AT91_UDP_ICR, 0xFFFFFFFF);
-
- /* compute default CSR value */
-
- csr_val = 0;
- AT91_CSR_ACK(csr_val, 0);
-
- /* disable all endpoints */
-
- for (n = 0; n != AT91_UDP_EP_MAX; n++) {
-
- /* disable endpoint */
- AT91_UDP_WRITE_4(sc, AT91_UDP_CSR(n), csr_val);
- }
-
- /* enable the control endpoint */
-
- AT91_CSR_ACK(csr_val, AT91_UDP_CSR_ET_CTRL |
- AT91_UDP_CSR_EPEDS);
-
- /* write to FIFO control register */
-
- AT91_UDP_WRITE_4(sc, AT91_UDP_CSR(0), csr_val);
-
- /* enable the interrupts we want */
-
- AT91_UDP_WRITE_4(sc, AT91_UDP_IER, AT91_UDP_INT_BUS);
-
- /* turn off clocks */
-
- at91dci_clocks_off(sc);
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- /* catch any lost interrupts */
-
- at91dci_do_poll(&sc->sc_bus);
-
- return (0); /* success */
-}
-
-void
-at91dci_uninit(struct at91dci_softc *sc)
-{
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* disable and clear all interrupts */
- AT91_UDP_WRITE_4(sc, AT91_UDP_IDR, 0xFFFFFFFF);
- AT91_UDP_WRITE_4(sc, AT91_UDP_ICR, 0xFFFFFFFF);
-
- sc->sc_flags.port_powered = 0;
- sc->sc_flags.status_vbus = 0;
- sc->sc_flags.status_bus_reset = 0;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- at91dci_pull_down(sc);
- at91dci_clocks_off(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-void
-at91dci_suspend(struct at91dci_softc *sc)
-{
- return;
-}
-
-void
-at91dci_resume(struct at91dci_softc *sc)
-{
- return;
-}
-
-static void
-at91dci_do_poll(struct usb2_bus *bus)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(bus);
-
- USB_BUS_LOCK(&sc->sc_bus);
- at91dci_interrupt_poll(sc);
- at91dci_root_ctrl_poll(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-/*------------------------------------------------------------------------*
- * at91dci bulk support
- *------------------------------------------------------------------------*/
-static void
-at91dci_device_bulk_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_device_bulk_close(struct usb2_xfer *xfer)
-{
- at91dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-at91dci_device_bulk_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_device_bulk_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- at91dci_setup_standard_chain(xfer);
- at91dci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods at91dci_device_bulk_methods =
-{
- .open = at91dci_device_bulk_open,
- .close = at91dci_device_bulk_close,
- .enter = at91dci_device_bulk_enter,
- .start = at91dci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci control support
- *------------------------------------------------------------------------*/
-static void
-at91dci_device_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_device_ctrl_close(struct usb2_xfer *xfer)
-{
- at91dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-at91dci_device_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_device_ctrl_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- at91dci_setup_standard_chain(xfer);
- at91dci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods at91dci_device_ctrl_methods =
-{
- .open = at91dci_device_ctrl_open,
- .close = at91dci_device_ctrl_close,
- .enter = at91dci_device_ctrl_enter,
- .start = at91dci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci interrupt support
- *------------------------------------------------------------------------*/
-static void
-at91dci_device_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_device_intr_close(struct usb2_xfer *xfer)
-{
- at91dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-at91dci_device_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_device_intr_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- at91dci_setup_standard_chain(xfer);
- at91dci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods at91dci_device_intr_methods =
-{
- .open = at91dci_device_intr_open,
- .close = at91dci_device_intr_close,
- .enter = at91dci_device_intr_enter,
- .start = at91dci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci full speed isochronous support
- *------------------------------------------------------------------------*/
-static void
-at91dci_device_isoc_fs_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_device_isoc_fs_close(struct usb2_xfer *xfer)
-{
- at91dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-at91dci_device_isoc_fs_enter(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
- uint32_t temp;
- uint32_t nframes;
-
- DPRINTFN(6, "xfer=%p next=%d nframes=%d\n",
- xfer, xfer->pipe->isoc_next, xfer->nframes);
-
- /* get the current frame index */
-
- nframes = AT91_UDP_READ_4(sc, AT91_UDP_FRM);
-
- /*
- * check if the frame index is within the window where the frames
- * will be inserted
- */
- temp = (nframes - xfer->pipe->isoc_next) & AT91_UDP_FRM_MASK;
-
- if ((xfer->pipe->is_synced == 0) ||
- (temp < xfer->nframes)) {
- /*
- * If there is data underflow or the pipe queue is
- * empty we schedule the transfer a few frames ahead
- * of the current frame position. Else two isochronous
- * transfers might overlap.
- */
- xfer->pipe->isoc_next = (nframes + 3) & AT91_UDP_FRM_MASK;
- xfer->pipe->is_synced = 1;
- DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next);
- }
- /*
- * compute how many milliseconds the insertion is ahead of the
- * current frame position:
- */
- temp = (xfer->pipe->isoc_next - nframes) & AT91_UDP_FRM_MASK;
-
- /*
- * pre-compute when the isochronous transfer will be finished:
- */
- xfer->isoc_time_complete =
- usb2_isoc_time_expand(&sc->sc_bus, nframes) + temp +
- xfer->nframes;
-
- /* compute frame number for next insertion */
- xfer->pipe->isoc_next += xfer->nframes;
-
- /* setup TDs */
- at91dci_setup_standard_chain(xfer);
-}
-
-static void
-at91dci_device_isoc_fs_start(struct usb2_xfer *xfer)
-{
- /* start TD chain */
- at91dci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods at91dci_device_isoc_fs_methods =
-{
- .open = at91dci_device_isoc_fs_open,
- .close = at91dci_device_isoc_fs_close,
- .enter = at91dci_device_isoc_fs_enter,
- .start = at91dci_device_isoc_fs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci root control support
- *------------------------------------------------------------------------*
- * simulate a hardware HUB by handling
- * all the necessary requests
- *------------------------------------------------------------------------*/
-
-static void
-at91dci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- at91dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/*
- * USB descriptors for the virtual Root HUB:
- */
-
-static const struct usb2_device_descriptor at91dci_devd = {
- .bLength = sizeof(struct usb2_device_descriptor),
- .bDescriptorType = UDESC_DEVICE,
- .bcdUSB = {0x00, 0x02},
- .bDeviceClass = UDCLASS_HUB,
- .bDeviceSubClass = UDSUBCLASS_HUB,
- .bDeviceProtocol = UDPROTO_HSHUBSTT,
- .bMaxPacketSize = 64,
- .bcdDevice = {0x00, 0x01},
- .iManufacturer = 1,
- .iProduct = 2,
- .bNumConfigurations = 1,
-};
-
-static const struct usb2_device_qualifier at91dci_odevd = {
- .bLength = sizeof(struct usb2_device_qualifier),
- .bDescriptorType = UDESC_DEVICE_QUALIFIER,
- .bcdUSB = {0x00, 0x02},
- .bDeviceClass = UDCLASS_HUB,
- .bDeviceSubClass = UDSUBCLASS_HUB,
- .bDeviceProtocol = UDPROTO_FSHUB,
- .bMaxPacketSize0 = 0,
- .bNumConfigurations = 0,
-};
-
-static const struct at91dci_config_desc at91dci_confd = {
- .confd = {
- .bLength = sizeof(struct usb2_config_descriptor),
- .bDescriptorType = UDESC_CONFIG,
- .wTotalLength[0] = sizeof(at91dci_confd),
- .bNumInterface = 1,
- .bConfigurationValue = 1,
- .iConfiguration = 0,
- .bmAttributes = UC_SELF_POWERED,
- .bMaxPower = 0,
- },
- .ifcd = {
- .bLength = sizeof(struct usb2_interface_descriptor),
- .bDescriptorType = UDESC_INTERFACE,
- .bNumEndpoints = 1,
- .bInterfaceClass = UICLASS_HUB,
- .bInterfaceSubClass = UISUBCLASS_HUB,
- .bInterfaceProtocol = UIPROTO_HSHUBSTT,
- },
-
- .endpd = {
- .bLength = sizeof(struct usb2_endpoint_descriptor),
- .bDescriptorType = UDESC_ENDPOINT,
- .bEndpointAddress = (UE_DIR_IN | AT9100_DCI_INTR_ENDPT),
- .bmAttributes = UE_INTERRUPT,
- .wMaxPacketSize[0] = 8,
- .bInterval = 255,
- },
-};
-
-static const struct usb2_hub_descriptor_min at91dci_hubd = {
- .bDescLength = sizeof(at91dci_hubd),
- .bDescriptorType = UDESC_HUB,
- .bNbrPorts = 1,
- .wHubCharacteristics[0] =
- (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) & 0xFF,
- .wHubCharacteristics[1] =
- (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 8,
- .bPwrOn2PwrGood = 50,
- .bHubContrCurrent = 0,
- .DeviceRemovable = {0}, /* port is removable */
-};
-
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
-#define STRING_VENDOR \
- 'A', 0, 'T', 0, 'M', 0, 'E', 0, 'L', 0
-
-#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
-
-USB_MAKE_STRING_DESC(STRING_LANG, at91dci_langtab);
-USB_MAKE_STRING_DESC(STRING_VENDOR, at91dci_vendor);
-USB_MAKE_STRING_DESC(STRING_PRODUCT, at91dci_product);
-
-static void
-at91dci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-at91dci_root_ctrl_task(struct usb2_bus *bus)
-{
- at91dci_root_ctrl_poll(AT9100_DCI_BUS2SC(bus));
-}
-
-static void
-at91dci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
- uint16_t value;
- uint16_t index;
- uint8_t use_polling;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- at91dci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* buffer reset */
- std->ptr = USB_ADD_BYTES(&sc->sc_hub_temp, 0);
- std->len = 0;
-
- value = UGETW(std->req.wValue);
- index = UGETW(std->req.wIndex);
-
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- /* demultiplex the control request */
-
- switch (std->req.bmRequestType) {
- case UT_READ_DEVICE:
- switch (std->req.bRequest) {
- case UR_GET_DESCRIPTOR:
- goto tr_handle_get_descriptor;
- case UR_GET_CONFIG:
- goto tr_handle_get_config;
- case UR_GET_STATUS:
- goto tr_handle_get_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_DEVICE:
- switch (std->req.bRequest) {
- case UR_SET_ADDRESS:
- goto tr_handle_set_address;
- case UR_SET_CONFIG:
- goto tr_handle_set_config;
- case UR_CLEAR_FEATURE:
- goto tr_valid; /* nop */
- case UR_SET_DESCRIPTOR:
- goto tr_valid; /* nop */
- case UR_SET_FEATURE:
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_ENDPOINT:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- switch (UGETW(std->req.wValue)) {
- case UF_ENDPOINT_HALT:
- goto tr_handle_clear_halt;
- case UF_DEVICE_REMOTE_WAKEUP:
- goto tr_handle_clear_wakeup;
- default:
- goto tr_stalled;
- }
- break;
- case UR_SET_FEATURE:
- switch (UGETW(std->req.wValue)) {
- case UF_ENDPOINT_HALT:
- goto tr_handle_set_halt;
- case UF_DEVICE_REMOTE_WAKEUP:
- goto tr_handle_set_wakeup;
- default:
- goto tr_stalled;
- }
- break;
- case UR_SYNCH_FRAME:
- goto tr_valid; /* nop */
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_ENDPOINT:
- switch (std->req.bRequest) {
- case UR_GET_STATUS:
- goto tr_handle_get_ep_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_INTERFACE:
- switch (std->req.bRequest) {
- case UR_SET_INTERFACE:
- goto tr_handle_set_interface;
- case UR_CLEAR_FEATURE:
- goto tr_valid; /* nop */
- case UR_SET_FEATURE:
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_INTERFACE:
- switch (std->req.bRequest) {
- case UR_GET_INTERFACE:
- goto tr_handle_get_interface;
- case UR_GET_STATUS:
- goto tr_handle_get_iface_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_CLASS_INTERFACE:
- case UT_WRITE_VENDOR_INTERFACE:
- /* XXX forward */
- break;
-
- case UT_READ_CLASS_INTERFACE:
- case UT_READ_VENDOR_INTERFACE:
- /* XXX forward */
- break;
-
- case UT_WRITE_CLASS_DEVICE:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- goto tr_valid;
- case UR_SET_DESCRIPTOR:
- case UR_SET_FEATURE:
- break;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_CLASS_OTHER:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- goto tr_handle_clear_port_feature;
- case UR_SET_FEATURE:
- goto tr_handle_set_port_feature;
- case UR_CLEAR_TT_BUFFER:
- case UR_RESET_TT:
- case UR_STOP_TT:
- goto tr_valid;
-
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_CLASS_OTHER:
- switch (std->req.bRequest) {
- case UR_GET_TT_STATE:
- goto tr_handle_get_tt_state;
- case UR_GET_STATUS:
- goto tr_handle_get_port_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_CLASS_DEVICE:
- switch (std->req.bRequest) {
- case UR_GET_DESCRIPTOR:
- goto tr_handle_get_class_descriptor;
- case UR_GET_STATUS:
- goto tr_handle_get_class_status;
-
- default:
- goto tr_stalled;
- }
- break;
- default:
- goto tr_stalled;
- }
- goto tr_valid;
-
-tr_handle_get_descriptor:
- switch (value >> 8) {
- case UDESC_DEVICE:
- if (value & 0xff) {
- goto tr_stalled;
- }
- std->len = sizeof(at91dci_devd);
- std->ptr = USB_ADD_BYTES(&at91dci_devd, 0);
- goto tr_valid;
- case UDESC_CONFIG:
- if (value & 0xff) {
- goto tr_stalled;
- }
- std->len = sizeof(at91dci_confd);
- std->ptr = USB_ADD_BYTES(&at91dci_confd, 0);
- goto tr_valid;
- case UDESC_STRING:
- switch (value & 0xff) {
- case 0: /* Language table */
- std->len = sizeof(at91dci_langtab);
- std->ptr = USB_ADD_BYTES(&at91dci_langtab, 0);
- goto tr_valid;
-
- case 1: /* Vendor */
- std->len = sizeof(at91dci_vendor);
- std->ptr = USB_ADD_BYTES(&at91dci_vendor, 0);
- goto tr_valid;
-
- case 2: /* Product */
- std->len = sizeof(at91dci_product);
- std->ptr = USB_ADD_BYTES(&at91dci_product, 0);
- goto tr_valid;
- default:
- break;
- }
- break;
- default:
- goto tr_stalled;
- }
- goto tr_stalled;
-
-tr_handle_get_config:
- std->len = 1;
- sc->sc_hub_temp.wValue[0] = sc->sc_conf;
- goto tr_valid;
-
-tr_handle_get_status:
- std->len = 2;
- USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED);
- goto tr_valid;
-
-tr_handle_set_address:
- if (value & 0xFF00) {
- goto tr_stalled;
- }
- sc->sc_rt_addr = value;
- goto tr_valid;
-
-tr_handle_set_config:
- if (value >= 2) {
- goto tr_stalled;
- }
- sc->sc_conf = value;
- goto tr_valid;
-
-tr_handle_get_interface:
- std->len = 1;
- sc->sc_hub_temp.wValue[0] = 0;
- goto tr_valid;
-
-tr_handle_get_tt_state:
-tr_handle_get_class_status:
-tr_handle_get_iface_status:
-tr_handle_get_ep_status:
- std->len = 2;
- USETW(sc->sc_hub_temp.wValue, 0);
- goto tr_valid;
-
-tr_handle_set_halt:
-tr_handle_set_interface:
-tr_handle_set_wakeup:
-tr_handle_clear_wakeup:
-tr_handle_clear_halt:
- goto tr_valid;
-
-tr_handle_clear_port_feature:
- if (index != 1) {
- goto tr_stalled;
- }
- DPRINTFN(9, "UR_CLEAR_PORT_FEATURE on port %d\n", index);
-
- switch (value) {
- case UHF_PORT_SUSPEND:
- at91dci_wakeup_peer(xfer);
- break;
-
- case UHF_PORT_ENABLE:
- sc->sc_flags.port_enabled = 0;
- break;
-
- case UHF_PORT_TEST:
- case UHF_PORT_INDICATOR:
- case UHF_C_PORT_ENABLE:
- case UHF_C_PORT_OVER_CURRENT:
- case UHF_C_PORT_RESET:
- /* nops */
- break;
- case UHF_PORT_POWER:
- sc->sc_flags.port_powered = 0;
- at91dci_pull_down(sc);
- at91dci_clocks_off(sc);
- break;
- case UHF_C_PORT_CONNECTION:
- sc->sc_flags.change_connect = 0;
- break;
- case UHF_C_PORT_SUSPEND:
- sc->sc_flags.change_suspend = 0;
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- goto tr_valid;
-
-tr_handle_set_port_feature:
- if (index != 1) {
- goto tr_stalled;
- }
- DPRINTFN(9, "UR_SET_PORT_FEATURE\n");
-
- switch (value) {
- case UHF_PORT_ENABLE:
- sc->sc_flags.port_enabled = 1;
- break;
- case UHF_PORT_SUSPEND:
- case UHF_PORT_RESET:
- case UHF_PORT_TEST:
- case UHF_PORT_INDICATOR:
- /* nops */
- break;
- case UHF_PORT_POWER:
- sc->sc_flags.port_powered = 1;
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- goto tr_valid;
-
-tr_handle_get_port_status:
-
- DPRINTFN(9, "UR_GET_PORT_STATUS\n");
-
- if (index != 1) {
- goto tr_stalled;
- }
- if (sc->sc_flags.status_vbus) {
- at91dci_clocks_on(sc);
- at91dci_pull_up(sc);
- } else {
- at91dci_pull_down(sc);
- at91dci_clocks_off(sc);
- }
-
- /* Select FULL-speed and Device Side Mode */
-
- value = UPS_PORT_MODE_DEVICE;
-
- if (sc->sc_flags.port_powered) {
- value |= UPS_PORT_POWER;
- }
- if (sc->sc_flags.port_enabled) {
- value |= UPS_PORT_ENABLED;
- }
- if (sc->sc_flags.status_vbus &&
- sc->sc_flags.status_bus_reset) {
- value |= UPS_CURRENT_CONNECT_STATUS;
- }
- if (sc->sc_flags.status_suspend) {
- value |= UPS_SUSPEND;
- }
- USETW(sc->sc_hub_temp.ps.wPortStatus, value);
-
- value = 0;
-
- if (sc->sc_flags.change_connect) {
- value |= UPS_C_CONNECT_STATUS;
-
- if (sc->sc_flags.status_vbus &&
- sc->sc_flags.status_bus_reset) {
- /* reset endpoint flags */
- bzero(sc->sc_ep_flags, sizeof(sc->sc_ep_flags));
- }
- }
- if (sc->sc_flags.change_suspend) {
- value |= UPS_C_SUSPEND;
- }
- USETW(sc->sc_hub_temp.ps.wPortChange, value);
- std->len = sizeof(sc->sc_hub_temp.ps);
- goto tr_valid;
-
-tr_handle_get_class_descriptor:
- if (value & 0xFF) {
- goto tr_stalled;
- }
- std->ptr = USB_ADD_BYTES(&at91dci_hubd, 0);
- std->len = sizeof(at91dci_hubd);
- goto tr_valid;
-
-tr_stalled:
- std->err = USB_ERR_STALLED;
-tr_valid:
-done:
- return;
-}
-
-static void
-at91dci_root_ctrl_poll(struct at91dci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &at91dci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods at91dci_root_ctrl_methods =
-{
- .open = at91dci_root_ctrl_open,
- .close = at91dci_root_ctrl_close,
- .enter = at91dci_root_ctrl_enter,
- .start = at91dci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-at91dci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_root_intr_close(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- at91dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-at91dci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_root_intr_start(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods at91dci_root_intr_methods =
-{
- .open = at91dci_root_intr_open,
- .close = at91dci_root_intr_close,
- .enter = at91dci_root_intr_enter,
- .start = at91dci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
-at91dci_xfer_setup(struct usb2_setup_params *parm)
-{
- const struct usb2_hw_ep_profile *pf;
- struct at91dci_softc *sc;
- struct usb2_xfer *xfer;
- void *last_obj;
- uint32_t ntd;
- uint32_t n;
- uint8_t ep_no;
-
- sc = AT9100_DCI_BUS2SC(parm->udev->bus);
- xfer = parm->curr_xfer;
-
- /*
- * NOTE: This driver does not use any of the parameters that
- * are computed from the following values. Just set some
- * reasonable dummies:
- */
- parm->hc_max_packet_size = 0x500;
- parm->hc_max_packet_count = 1;
- parm->hc_max_frame_size = 0x500;
-
- usb2_transfer_setup_sub(parm);
-
- /*
- * compute maximum number of TDs
- */
- if (parm->methods == &at91dci_device_ctrl_methods) {
-
- ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC 1 */
- + 1 /* SYNC 2 */ ;
-
- } else if (parm->methods == &at91dci_device_bulk_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &at91dci_device_intr_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &at91dci_device_isoc_fs_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else {
-
- ntd = 0;
- }
-
- /*
- * check if "usb2_transfer_setup_sub" set an error
- */
- if (parm->err) {
- return;
- }
- /*
- * allocate transfer descriptors
- */
- last_obj = NULL;
-
- /*
- * get profile stuff
- */
- if (ntd) {
-
- ep_no = xfer->endpoint & UE_ADDR;
- at91dci_get_hw_ep_profile(parm->udev, &pf, ep_no);
-
- if (pf == NULL) {
- /* should not happen */
- parm->err = USB_ERR_INVAL;
- return;
- }
- } else {
- ep_no = 0;
- pf = NULL;
- }
-
- /* align data */
- parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
-
- for (n = 0; n != ntd; n++) {
-
- struct at91dci_td *td;
-
- if (parm->buf) {
-
- td = USB_ADD_BYTES(parm->buf, parm->size[0]);
-
- /* init TD */
- td->io_tag = sc->sc_io_tag;
- td->io_hdl = sc->sc_io_hdl;
- td->max_packet_size = xfer->max_packet_size;
- td->status_reg = AT91_UDP_CSR(ep_no);
- td->fifo_reg = AT91_UDP_FDR(ep_no);
- if (pf->support_multi_buffer) {
- td->support_multi_buffer = 1;
- }
- td->obj_next = last_obj;
-
- last_obj = td;
- }
- parm->size[0] += sizeof(*td);
- }
-
- xfer->td_start[0] = last_obj;
-}
-
-static void
-at91dci_xfer_unsetup(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
- struct usb2_pipe *pipe)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(udev->bus);
-
- DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
- pipe, udev->address,
- edesc->bEndpointAddress, udev->flags.usb2_mode,
- sc->sc_rt_addr);
-
- if (udev->device_index == sc->sc_rt_addr) {
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &at91dci_root_ctrl_methods;
- break;
- case UE_DIR_IN | AT9100_DCI_INTR_ENDPT:
- pipe->methods = &at91dci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
-
- if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
- if (udev->speed != USB_SPEED_FULL) {
- /* not supported */
- return;
- }
- switch (edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- pipe->methods = &at91dci_device_ctrl_methods;
- break;
- case UE_INTERRUPT:
- pipe->methods = &at91dci_device_intr_methods;
- break;
- case UE_ISOCHRONOUS:
- pipe->methods = &at91dci_device_isoc_fs_methods;
- break;
- case UE_BULK:
- pipe->methods = &at91dci_device_bulk_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- }
-}
-
-struct usb2_bus_methods at91dci_bus_methods =
-{
- .pipe_init = &at91dci_pipe_init,
- .xfer_setup = &at91dci_xfer_setup,
- .xfer_unsetup = &at91dci_xfer_unsetup,
- .do_poll = &at91dci_do_poll,
- .get_hw_ep_profile = &at91dci_get_hw_ep_profile,
- .set_stall = &at91dci_set_stall,
- .clear_stall = &at91dci_clear_stall,
- .roothub_exec = &at91dci_root_ctrl_task,
-};
diff --git a/sys/dev/usb2/controller/at91dci.h b/sys/dev/usb2/controller/at91dci.h
deleted file mode 100644
index d386307..0000000
--- a/sys/dev/usb2/controller/at91dci.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2006 ATMEL
- * Copyright (c) 2007 Hans Petter Selasky <hselasky@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.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-/*
- * USB Device Port (UDP) register definition, based on
- * "AT91RM9200.h" provided by ATMEL.
- */
-
-#ifndef _AT9100_DCI_H_
-#define _AT9100_DCI_H_
-
-#define AT91_MAX_DEVICES (USB_MIN_DEVICES + 1)
-
-#define AT91_UDP_FRM 0x00 /* Frame number register */
-#define AT91_UDP_FRM_MASK (0x7FF << 0) /* Frame Number as Defined in
- * the Packet Field Formats */
-#define AT91_UDP_FRM_ERR (0x1 << 16) /* Frame Error */
-#define AT91_UDP_FRM_OK (0x1 << 17) /* Frame OK */
-
-#define AT91_UDP_GSTATE 0x04 /* Global state register */
-#define AT91_UDP_GSTATE_ADDR (0x1 << 0) /* Addressed state */
-#define AT91_UDP_GSTATE_CONFG (0x1 << 1) /* Configured */
-#define AT91_UDP_GSTATE_ESR (0x1 << 2) /* Enable Send Resume */
-#define AT91_UDP_GSTATE_RSM (0x1 << 3) /* A Resume Has Been Sent to
- * the Host */
-#define AT91_UDP_GSTATE_RMW (0x1 << 4) /* Remote Wake Up Enable */
-
-#define AT91_UDP_FADDR 0x08 /* Function Address Register */
-#define AT91_UDP_FADDR_MASK (0x7F << 0)/* Function Address Mask */
-#define AT91_UDP_FADDR_EN (0x1 << 8)/* Function Enable */
-
-#define AT91_UDP_RES0 0x0C /* Reserved 0 */
-
-#define AT91_UDP_IER 0x10 /* Interrupt Enable Register */
-#define AT91_UDP_IDR 0x14 /* Interrupt Disable Register */
-#define AT91_UDP_IMR 0x18 /* Interrupt Mask Register */
-#define AT91_UDP_ISR 0x1C /* Interrupt Status Register */
-#define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */
-#define AT91_UDP_INT_EP(n) (0x1 <<(n))/* Endpoint "n" Interrupt */
-#define AT91_UDP_INT_RXSUSP (0x1 << 8)/* USB Suspend Interrupt */
-#define AT91_UDP_INT_RXRSM (0x1 << 9)/* USB Resume Interrupt */
-#define AT91_UDP_INT_EXTRSM (0x1 << 10)/* USB External Resume Interrupt */
-#define AT91_UDP_INT_SOFINT (0x1 << 11)/* USB Start Of frame Interrupt */
-#define AT91_UDP_INT_END_BR (0x1 << 12)/* USB End Of Bus Reset Interrupt */
-#define AT91_UDP_INT_WAKEUP (0x1 << 13)/* USB Resume Interrupt */
-
-#define AT91_UDP_INT_BUS \
- (AT91_UDP_INT_RXSUSP|AT91_UDP_INT_RXRSM| \
- AT91_UDP_INT_END_BR)
-
-#define AT91_UDP_INT_EPS \
- (AT91_UDP_INT_EP(0)|AT91_UDP_INT_EP(1)| \
- AT91_UDP_INT_EP(2)|AT91_UDP_INT_EP(3)| \
- AT91_UDP_INT_EP(4)|AT91_UDP_INT_EP(5))
-
-#define AT91_UDP_INT_DEFAULT \
- (AT91_UDP_INT_EPS|AT91_UDP_INT_BUS)
-
-#define AT91_UDP_RES1 0x24 /* Reserved 1 */
-#define AT91_UDP_RST 0x28 /* Reset Endpoint Register */
-#define AT91_UDP_RST_EP(n) (0x1 << (n))/* Reset Endpoint "n" */
-
-#define AT91_UDP_RES2 0x2C /* Reserved 2 */
-
-#define AT91_UDP_CSR(n) (0x30 + (4*(n)))/* Endpoint Control and Status
- * Register */
-#define AT91_UDP_CSR_TXCOMP (0x1 << 0) /* Generates an IN packet with data
- * previously written in the DPR */
-#define AT91_UDP_CSR_RX_DATA_BK0 (0x1 << 1) /* Receive Data Bank 0 */
-#define AT91_UDP_CSR_RXSETUP (0x1 << 2) /* Sends STALL to the Host
- * (Control endpoints) */
-#define AT91_UDP_CSR_ISOERROR (0x1 << 3) /* Isochronous error
- * (Isochronous endpoints) */
-#define AT91_UDP_CSR_STALLSENT (0x1 << 3) /* Stall sent (Control, bulk,
- * interrupt endpoints) */
-#define AT91_UDP_CSR_TXPKTRDY (0x1 << 4) /* Transmit Packet Ready */
-#define AT91_UDP_CSR_FORCESTALL (0x1 << 5) /* Force Stall (used by
- * Control, Bulk and
- * Isochronous endpoints). */
-#define AT91_UDP_CSR_RX_DATA_BK1 (0x1 << 6) /* Receive Data Bank 1 (only
- * used by endpoints with
- * ping-pong attributes). */
-#define AT91_UDP_CSR_DIR (0x1 << 7) /* Transfer Direction */
-#define AT91_UDP_CSR_ET_MASK (0x7 << 8) /* Endpoint transfer type mask */
-#define AT91_UDP_CSR_ET_CTRL (0x0 << 8) /* Control IN+OUT */
-#define AT91_UDP_CSR_ET_ISO (0x1 << 8) /* Isochronous */
-#define AT91_UDP_CSR_ET_BULK (0x2 << 8) /* Bulk */
-#define AT91_UDP_CSR_ET_INT (0x3 << 8) /* Interrupt */
-#define AT91_UDP_CSR_ET_DIR_OUT (0x0 << 8) /* OUT tokens */
-#define AT91_UDP_CSR_ET_DIR_IN (0x4 << 8) /* IN tokens */
-#define AT91_UDP_CSR_DTGLE (0x1 << 11) /* Data Toggle */
-#define AT91_UDP_CSR_EPEDS (0x1 << 15) /* Endpoint Enable Disable */
-#define AT91_UDP_CSR_RXBYTECNT (0x7FF << 16) /* Number Of Bytes Available
- * in the FIFO */
-
-#define AT91_UDP_FDR(n) (0x50 + (4*(n)))/* Endpoint FIFO Data Register */
-#define AT91_UDP_RES3 0x70 /* Reserved 3 */
-#define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */
-#define AT91_UDP_TXVC_DIS (0x1 << 8)
-
-#define AT91_UDP_EP_MAX 6 /* maximum number of endpoints
- * supported */
-
-#define AT91_UDP_READ_4(sc, reg) \
- bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
-
-#define AT91_UDP_WRITE_4(sc, reg, data) \
- bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
-
-struct at91dci_td;
-
-typedef uint8_t (at91dci_cmd_t)(struct at91dci_td *td);
-
-struct at91dci_td {
- bus_space_tag_t io_tag;
- bus_space_handle_t io_hdl;
- struct at91dci_td *obj_next;
- at91dci_cmd_t *func;
- struct usb2_page_cache *pc;
- uint32_t offset;
- uint32_t remainder;
- uint16_t max_packet_size;
- uint8_t status_reg;
- uint8_t fifo_reg;
- uint8_t fifo_bank:1;
- uint8_t error:1;
- uint8_t alt_next:1;
- uint8_t short_pkt:1;
- uint8_t support_multi_buffer:1;
- uint8_t did_stall:1;
-};
-
-struct at91dci_std_temp {
- at91dci_cmd_t *func;
- struct usb2_page_cache *pc;
- struct at91dci_td *td;
- struct at91dci_td *td_next;
- uint32_t len;
- uint32_t offset;
- uint16_t max_frame_size;
- uint8_t short_pkt;
- /*
- * short_pkt = 0: transfer should be short terminated
- * short_pkt = 1: transfer should not be short terminated
- */
- uint8_t setup_alt_next;
-};
-
-struct at91dci_config_desc {
- struct usb2_config_descriptor confd;
- struct usb2_interface_descriptor ifcd;
- struct usb2_endpoint_descriptor endpd;
-} __packed;
-
-union at91dci_hub_temp {
- uWord wValue;
- struct usb2_port_status ps;
-};
-
-struct at91dci_ep_flags {
- uint8_t fifo_bank:1; /* hardware specific */
-};
-
-struct at91dci_flags {
- uint8_t change_connect:1;
- uint8_t change_suspend:1;
- uint8_t status_suspend:1; /* set if suspended */
- uint8_t status_vbus:1; /* set if present */
- uint8_t status_bus_reset:1; /* set if reset complete */
- uint8_t remote_wakeup:1;
- uint8_t self_powered:1;
- uint8_t clocks_off:1;
- uint8_t port_powered:1;
- uint8_t port_enabled:1;
- uint8_t d_pulled_up:1;
-};
-
-struct at91dci_softc {
- struct usb2_bus sc_bus;
- union at91dci_hub_temp sc_hub_temp;
- LIST_HEAD(, usb2_xfer) sc_interrupt_list_head;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
-
- struct usb2_device *sc_devices[AT91_MAX_DEVICES];
- struct resource *sc_io_res;
- struct resource *sc_irq_res;
- void *sc_intr_hdl;
- bus_size_t sc_io_size;
- bus_space_tag_t sc_io_tag;
- bus_space_handle_t sc_io_hdl;
-
- void (*sc_clocks_on) (void *arg);
- void (*sc_clocks_off) (void *arg);
- void *sc_clocks_arg;
-
- void (*sc_pull_up) (void *arg);
- void (*sc_pull_down) (void *arg);
- void *sc_pull_arg;
-
- uint8_t sc_rt_addr; /* root HUB address */
- uint8_t sc_dv_addr; /* device address */
- uint8_t sc_conf; /* root HUB config */
-
- uint8_t sc_hub_idata[1];
-
- struct at91dci_flags sc_flags;
- struct at91dci_ep_flags sc_ep_flags[AT91_UDP_EP_MAX];
-};
-
-/* prototypes */
-
-usb2_error_t at91dci_init(struct at91dci_softc *sc);
-void at91dci_uninit(struct at91dci_softc *sc);
-void at91dci_suspend(struct at91dci_softc *sc);
-void at91dci_resume(struct at91dci_softc *sc);
-void at91dci_interrupt(struct at91dci_softc *sc);
-void at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on);
-
-#endif /* _AT9100_DCI_H_ */
diff --git a/sys/dev/usb2/controller/at91dci_atmelarm.c b/sys/dev/usb2/controller/at91dci_atmelarm.c
deleted file mode 100644
index 39d3782..0000000
--- a/sys/dev/usb2/controller/at91dci_atmelarm.c
+++ /dev/null
@@ -1,347 +0,0 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*-
- * Copyright (c) 2007-2008 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/at91dci.h>
-
-#include <sys/rman.h>
-
-#include <arm/at91/at91_pmcvar.h>
-#include <arm/at91/at91rm92reg.h>
-#include <arm/at91/at91_pio_rm9200.h>
-#include <arm/at91/at91_piovar.h>
-
-#define MEM_RID 0
-
-/* Pin Definitions - do they belong here or somewhere else ? */
-
-#define VBUS_MASK AT91C_PIO_PB24
-#define VBUS_BASE AT91RM92_PIOB_BASE
-
-#define PULLUP_MASK AT91C_PIO_PB22
-#define PULLUP_BASE AT91RM92_PIOB_BASE
-
-static device_probe_t at91_udp_probe;
-static device_attach_t at91_udp_attach;
-static device_detach_t at91_udp_detach;
-static device_shutdown_t at91_udp_shutdown;
-
-struct at91_udp_softc {
- struct at91dci_softc sc_dci; /* must be first */
- struct at91_pmc_clock *sc_iclk;
- struct at91_pmc_clock *sc_fclk;
- struct resource *sc_vbus_irq_res;
- void *sc_vbus_intr_hdl;
-};
-
-static void
-at91_vbus_poll(struct at91_udp_softc *sc)
-{
- uint32_t temp;
- uint8_t vbus_val;
-
- /* XXX temporary clear interrupts here */
-
- temp = at91_pio_gpio_clear_interrupt(VBUS_BASE);
-
- /* just forward it */
-
- vbus_val = at91_pio_gpio_get(VBUS_BASE, VBUS_MASK);
- at91dci_vbus_interrupt(&sc->sc_dci, vbus_val);
-}
-
-static void
-at91_udp_clocks_on(void *arg)
-{
- struct at91_udp_softc *sc = arg;
-
- at91_pmc_clock_enable(sc->sc_iclk);
- at91_pmc_clock_enable(sc->sc_fclk);
-}
-
-static void
-at91_udp_clocks_off(void *arg)
-{
- struct at91_udp_softc *sc = arg;
-
- at91_pmc_clock_disable(sc->sc_fclk);
- at91_pmc_clock_disable(sc->sc_iclk);
-}
-
-static void
-at91_udp_pull_up(void *arg)
-{
- at91_pio_gpio_set(PULLUP_BASE, PULLUP_MASK);
-}
-
-static void
-at91_udp_pull_down(void *arg)
-{
- at91_pio_gpio_clear(PULLUP_BASE, PULLUP_MASK);
-}
-
-static int
-at91_udp_probe(device_t dev)
-{
- device_set_desc(dev, "AT91 integrated AT91_UDP controller");
- return (0);
-}
-
-static int
-at91_udp_attach(device_t dev)
-{
- struct at91_udp_softc *sc = device_get_softc(dev);
- int err;
- int rid;
-
- /* setup AT9100 USB device controller interface softc */
-
- sc->sc_dci.sc_clocks_on = &at91_udp_clocks_on;
- sc->sc_dci.sc_clocks_off = &at91_udp_clocks_off;
- sc->sc_dci.sc_clocks_arg = sc;
- sc->sc_dci.sc_pull_up = &at91_udp_pull_up;
- sc->sc_dci.sc_pull_down = &at91_udp_pull_down;
- sc->sc_dci.sc_pull_arg = sc;
-
- /* initialise some bus fields */
- sc->sc_dci.sc_bus.parent = dev;
- sc->sc_dci.sc_bus.devices = sc->sc_dci.sc_devices;
- sc->sc_dci.sc_bus.devices_max = AT91_MAX_DEVICES;
-
- /* get all DMA memory */
- if (usb2_bus_mem_alloc_all(&sc->sc_dci.sc_bus,
- USB_GET_DMA_TAG(dev), NULL)) {
- return (ENOMEM);
- }
- /*
- * configure VBUS input pin, enable deglitch and enable
- * interrupt :
- */
- at91_pio_use_gpio(VBUS_BASE, VBUS_MASK);
- at91_pio_gpio_input(VBUS_BASE, VBUS_MASK);
- at91_pio_gpio_set_deglitch(VBUS_BASE, VBUS_MASK, 1);
- at91_pio_gpio_set_interrupt(VBUS_BASE, VBUS_MASK, 1);
-
- /*
- * configure PULLUP output pin :
- */
- at91_pio_use_gpio(PULLUP_BASE, PULLUP_MASK);
- at91_pio_gpio_output(PULLUP_BASE, PULLUP_MASK, 0);
-
- at91_udp_pull_down(sc);
-
- /* wait 10ms for pulldown to stabilise */
- usb2_pause_mtx(NULL, hz / 100);
-
- sc->sc_iclk = at91_pmc_clock_ref("udc_clk");
- sc->sc_fclk = at91_pmc_clock_ref("udpck");
-
- rid = MEM_RID;
- sc->sc_dci.sc_io_res =
- bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
-
- if (!(sc->sc_dci.sc_io_res)) {
- err = ENOMEM;
- goto error;
- }
- sc->sc_dci.sc_io_tag = rman_get_bustag(sc->sc_dci.sc_io_res);
- sc->sc_dci.sc_io_hdl = rman_get_bushandle(sc->sc_dci.sc_io_res);
- sc->sc_dci.sc_io_size = rman_get_size(sc->sc_dci.sc_io_res);
-
- rid = 0;
- sc->sc_dci.sc_irq_res =
- bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
- if (!(sc->sc_dci.sc_irq_res)) {
- goto error;
- }
- rid = 1;
- sc->sc_vbus_irq_res =
- bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
- if (!(sc->sc_vbus_irq_res)) {
- goto error;
- }
- sc->sc_dci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
- if (!(sc->sc_dci.sc_bus.bdev)) {
- goto error;
- }
- device_set_ivars(sc->sc_dci.sc_bus.bdev, &sc->sc_dci.sc_bus);
-
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl);
-#else
- err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl);
-#endif
- if (err) {
- sc->sc_dci.sc_intr_hdl = NULL;
- goto error;
- }
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(dev, sc->sc_vbus_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl);
-#else
- err = bus_setup_intr(dev, sc->sc_vbus_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl);
-#endif
- if (err) {
- sc->sc_vbus_intr_hdl = NULL;
- goto error;
- }
- err = at91dci_init(&sc->sc_dci);
- if (!err) {
- err = device_probe_and_attach(sc->sc_dci.sc_bus.bdev);
- }
- if (err) {
- goto error;
- } else {
- /* poll VBUS one time */
- at91_vbus_poll(sc);
- }
- return (0);
-
-error:
- at91_udp_detach(dev);
- return (ENXIO);
-}
-
-static int
-at91_udp_detach(device_t dev)
-{
- struct at91_udp_softc *sc = device_get_softc(dev);
- device_t bdev;
- int err;
-
- if (sc->sc_dci.sc_bus.bdev) {
- bdev = sc->sc_dci.sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(dev);
-
- /* disable Transceiver */
- AT91_UDP_WRITE_4(&sc->sc_dci, AT91_UDP_TXVC, AT91_UDP_TXVC_DIS);
-
- /* disable and clear all interrupts */
- AT91_UDP_WRITE_4(&sc->sc_dci, AT91_UDP_IDR, 0xFFFFFFFF);
- AT91_UDP_WRITE_4(&sc->sc_dci, AT91_UDP_ICR, 0xFFFFFFFF);
-
- /* disable VBUS interrupt */
- at91_pio_gpio_set_interrupt(VBUS_BASE, VBUS_MASK, 0);
-
- if (sc->sc_vbus_irq_res && sc->sc_vbus_intr_hdl) {
- err = bus_teardown_intr(dev, sc->sc_vbus_irq_res,
- sc->sc_vbus_intr_hdl);
- sc->sc_vbus_intr_hdl = NULL;
- }
- if (sc->sc_vbus_irq_res) {
- bus_release_resource(dev, SYS_RES_IRQ, 1,
- sc->sc_vbus_irq_res);
- sc->sc_vbus_irq_res = NULL;
- }
- if (sc->sc_dci.sc_irq_res && sc->sc_dci.sc_intr_hdl) {
- /*
- * only call at91_udp_uninit() after at91_udp_init()
- */
- at91dci_uninit(&sc->sc_dci);
-
- err = bus_teardown_intr(dev, sc->sc_dci.sc_irq_res,
- sc->sc_dci.sc_intr_hdl);
- sc->sc_dci.sc_intr_hdl = NULL;
- }
- if (sc->sc_dci.sc_irq_res) {
- bus_release_resource(dev, SYS_RES_IRQ, 0,
- sc->sc_dci.sc_irq_res);
- sc->sc_dci.sc_irq_res = NULL;
- }
- if (sc->sc_dci.sc_io_res) {
- bus_release_resource(dev, SYS_RES_MEMORY, MEM_RID,
- sc->sc_dci.sc_io_res);
- sc->sc_dci.sc_io_res = NULL;
- }
- usb2_bus_mem_free_all(&sc->sc_dci.sc_bus, NULL);
-
- /* disable clocks */
- at91_pmc_clock_disable(sc->sc_iclk);
- at91_pmc_clock_disable(sc->sc_fclk);
- at91_pmc_clock_deref(sc->sc_fclk);
- at91_pmc_clock_deref(sc->sc_iclk);
-
- return (0);
-}
-
-static int
-at91_udp_shutdown(device_t dev)
-{
- struct at91_udp_softc *sc = device_get_softc(dev);
- int err;
-
- err = bus_generic_shutdown(dev);
- if (err)
- return (err);
-
- at91dci_uninit(&sc->sc_dci);
-
- return (0);
-}
-
-static device_method_t at91_udp_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, at91_udp_probe),
- DEVMETHOD(device_attach, at91_udp_attach),
- DEVMETHOD(device_detach, at91_udp_detach),
- DEVMETHOD(device_shutdown, at91_udp_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
-};
-
-static driver_t at91_udp_driver = {
- "at91_udp",
- at91_udp_methods,
- sizeof(struct at91_udp_softc),
-};
-
-static devclass_t at91_udp_devclass;
-
-DRIVER_MODULE(at91_udp, atmelarm, at91_udp_driver, at91_udp_devclass, 0, 0);
diff --git a/sys/dev/usb2/controller/atmegadci.c b/sys/dev/usb2/controller/atmegadci.c
deleted file mode 100644
index bea8835d..0000000
--- a/sys/dev/usb2/controller/atmegadci.c
+++ /dev/null
@@ -1,2327 +0,0 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*-
- * Copyright (c) 2009 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-/*
- * This file contains the driver for the ATMEGA series USB Device
- * Controller
- */
-
-/*
- * NOTE: When the chip detects BUS-reset it will also reset the
- * endpoints, Function-address and more.
- */
-
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_defs.h>
-
-#define USB_DEBUG_VAR atmegadci_debug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_transfer.h>
-#include <dev/usb2/core/usb2_device.h>
-#include <dev/usb2/core/usb2_hub.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/atmegadci.h>
-
-#define ATMEGA_BUS2SC(bus) \
- ((struct atmegadci_softc *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((struct atmegadci_softc *)0)->sc_bus))))
-
-#define ATMEGA_PC2SC(pc) \
- ATMEGA_BUS2SC((pc)->tag_parent->info->bus)
-
-#if USB_DEBUG
-static int atmegadci_debug = 0;
-
-SYSCTL_NODE(_hw_usb2, OID_AUTO, atmegadci, CTLFLAG_RW, 0, "USB ATMEGA DCI");
-SYSCTL_INT(_hw_usb2_atmegadci, OID_AUTO, debug, CTLFLAG_RW,
- &atmegadci_debug, 0, "ATMEGA DCI debug level");
-#endif
-
-#define ATMEGA_INTR_ENDPT 1
-
-/* prototypes */
-
-struct usb2_bus_methods atmegadci_bus_methods;
-struct usb2_pipe_methods atmegadci_device_bulk_methods;
-struct usb2_pipe_methods atmegadci_device_ctrl_methods;
-struct usb2_pipe_methods atmegadci_device_intr_methods;
-struct usb2_pipe_methods atmegadci_device_isoc_fs_methods;
-struct usb2_pipe_methods atmegadci_root_ctrl_methods;
-struct usb2_pipe_methods atmegadci_root_intr_methods;
-
-static atmegadci_cmd_t atmegadci_setup_rx;
-static atmegadci_cmd_t atmegadci_data_rx;
-static atmegadci_cmd_t atmegadci_data_tx;
-static atmegadci_cmd_t atmegadci_data_tx_sync;
-static void atmegadci_device_done(struct usb2_xfer *, usb2_error_t);
-static void atmegadci_do_poll(struct usb2_bus *);
-static void atmegadci_root_ctrl_poll(struct atmegadci_softc *);
-static void atmegadci_standard_done(struct usb2_xfer *);
-
-static usb2_sw_transfer_func_t atmegadci_root_intr_done;
-static usb2_sw_transfer_func_t atmegadci_root_ctrl_done;
-
-/*
- * Here is a list of what the chip supports:
- */
-static const struct usb2_hw_ep_profile
- atmegadci_ep_profile[2] = {
-
- [0] = {
- .max_in_frame_size = 64,
- .max_out_frame_size = 64,
- .is_simplex = 1,
- .support_control = 1,
- },
- [1] = {
- .max_in_frame_size = 64,
- .max_out_frame_size = 64,
- .is_simplex = 1,
- .support_multi_buffer = 1,
- .support_bulk = 1,
- .support_interrupt = 1,
- .support_isochronous = 1,
- .support_in = 1,
- .support_out = 1,
- },
-};
-
-static void
-atmegadci_get_hw_ep_profile(struct usb2_device *udev,
- const struct usb2_hw_ep_profile **ppf, uint8_t ep_addr)
-{
- if (ep_addr == 0)
- *ppf = atmegadci_ep_profile;
- else if (ep_addr < ATMEGA_EP_MAX)
- *ppf = atmegadci_ep_profile + 1;
- else
- *ppf = NULL;
-}
-
-static void
-atmegadci_clocks_on(struct atmegadci_softc *sc)
-{
- if (sc->sc_flags.clocks_off &&
- sc->sc_flags.port_powered) {
-
- DPRINTFN(5, "\n");
-
- /* turn on clocks */
- (sc->sc_clocks_on) (&sc->sc_bus);
-
- ATMEGA_WRITE_1(sc, ATMEGA_USBCON,
- ATMEGA_USBCON_USBE |
- ATMEGA_USBCON_OTGPADE |
- ATMEGA_USBCON_VBUSTE);
-
- sc->sc_flags.clocks_off = 0;
-
- /* enable transceiver ? */
- }
-}
-
-static void
-atmegadci_clocks_off(struct atmegadci_softc *sc)
-{
- if (!sc->sc_flags.clocks_off) {
-
- DPRINTFN(5, "\n");
-
- /* disable Transceiver ? */
-
- ATMEGA_WRITE_1(sc, ATMEGA_USBCON,
- ATMEGA_USBCON_USBE |
- ATMEGA_USBCON_OTGPADE |
- ATMEGA_USBCON_FRZCLK |
- ATMEGA_USBCON_VBUSTE);
-
- /* turn clocks off */
- (sc->sc_clocks_off) (&sc->sc_bus);
-
- sc->sc_flags.clocks_off = 1;
- }
-}
-
-static void
-atmegadci_pull_up(struct atmegadci_softc *sc)
-{
- /* pullup D+, if possible */
-
- if (!sc->sc_flags.d_pulled_up &&
- sc->sc_flags.port_powered) {
- sc->sc_flags.d_pulled_up = 1;
- ATMEGA_WRITE_1(sc, ATMEGA_UDCON, 0);
- }
-}
-
-static void
-atmegadci_pull_down(struct atmegadci_softc *sc)
-{
- /* pulldown D+, if possible */
-
- if (sc->sc_flags.d_pulled_up) {
- sc->sc_flags.d_pulled_up = 0;
- ATMEGA_WRITE_1(sc, ATMEGA_UDCON, ATMEGA_UDCON_DETACH);
- }
-}
-
-static void
-atmegadci_wakeup_peer(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
- uint8_t use_polling;
- uint8_t temp;
-
- if (!sc->sc_flags.status_suspend) {
- return;
- }
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- temp = ATMEGA_READ_1(sc, ATMEGA_UDCON);
- ATMEGA_WRITE_1(sc, ATMEGA_UDCON, temp | ATMEGA_UDCON_RMWKUP);
-
- /* wait 8 milliseconds */
- if (use_polling) {
- /* polling */
- DELAY(8000);
- } else {
- /* Wait for reset to complete. */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 125);
- }
-
- /* hardware should have cleared RMWKUP bit */
-}
-
-static void
-atmegadci_set_address(struct atmegadci_softc *sc, uint8_t addr)
-{
- DPRINTFN(5, "addr=%d\n", addr);
-
- ATMEGA_WRITE_1(sc, ATMEGA_UDADDR, addr);
-
- addr |= ATMEGA_UDADDR_ADDEN;
-
- ATMEGA_WRITE_1(sc, ATMEGA_UDADDR, addr);
-}
-
-static uint8_t
-atmegadci_setup_rx(struct atmegadci_td *td)
-{
- struct atmegadci_softc *sc;
- struct usb2_device_request req;
- uint16_t count;
- uint8_t temp;
-
- /* get pointer to softc */
- sc = ATMEGA_PC2SC(td->pc);
-
- /* select endpoint number */
- ATMEGA_WRITE_1(sc, ATMEGA_UENUM, td->ep_no);
-
- /* check endpoint status */
- temp = ATMEGA_READ_1(sc, ATMEGA_UEINTX);
-
- DPRINTFN(5, "UEINTX=0x%02x\n", temp);
-
- if (!(temp & ATMEGA_UEINTX_RXSTPI)) {
- /* abort any ongoing transfer */
- if (!td->did_stall) {
- DPRINTFN(5, "stalling\n");
- ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
- ATMEGA_UECONX_EPEN |
- ATMEGA_UECONX_STALLRQ);
- td->did_stall = 1;
- }
- goto not_complete;
- }
- /* get the packet byte count */
- count =
- (ATMEGA_READ_1(sc, ATMEGA_UEBCHX) << 8) |
- (ATMEGA_READ_1(sc, ATMEGA_UEBCLX));
-
- /* mask away undefined bits */
- count &= 0x7FF;
-
- /* verify data length */
- if (count != td->remainder) {
- DPRINTFN(0, "Invalid SETUP packet "
- "length, %d bytes\n", count);
- goto not_complete;
- }
- if (count != sizeof(req)) {
- DPRINTFN(0, "Unsupported SETUP packet "
- "length, %d bytes\n", count);
- goto not_complete;
- }
- /* receive data */
- ATMEGA_READ_MULTI_1(sc, ATMEGA_UEDATX,
- (void *)&req, sizeof(req));
-
- /* copy data into real buffer */
- usb2_copy_in(td->pc, 0, &req, sizeof(req));
-
- td->offset = sizeof(req);
- td->remainder = 0;
-
- /* sneak peek the set address */
- if ((req.bmRequestType == UT_WRITE_DEVICE) &&
- (req.bRequest == UR_SET_ADDRESS)) {
- sc->sc_dv_addr = req.wValue[0] & 0x7F;
- } else {
- sc->sc_dv_addr = 0xFF;
- }
-
- /* clear SETUP packet interrupt */
- ATMEGA_WRITE_1(sc, ATMEGA_UEINTX, ~ATMEGA_UEINTX_RXSTPI);
- return (0); /* complete */
-
-not_complete:
- /* we only want to know if there is a SETUP packet */
- ATMEGA_WRITE_1(sc, ATMEGA_UEIENX, ATMEGA_UEIENX_RXSTPE);
- return (1); /* not complete */
-}
-
-static uint8_t
-atmegadci_data_rx(struct atmegadci_td *td)
-{
- struct atmegadci_softc *sc;
- struct usb2_page_search buf_res;
- uint16_t count;
- uint8_t temp;
- uint8_t to;
- uint8_t got_short;
-
- to = 3; /* don't loop forever! */
- got_short = 0;
-
- /* get pointer to softc */
- sc = ATMEGA_PC2SC(td->pc);
-
- /* select endpoint number */
- ATMEGA_WRITE_1(sc, ATMEGA_UENUM, td->ep_no);
-
-repeat:
- /* check if any of the FIFO banks have data */
- /* check endpoint status */
- temp = ATMEGA_READ_1(sc, ATMEGA_UEINTX);
-
- DPRINTFN(5, "temp=0x%02x rem=%u\n", temp, td->remainder);
-
- if (temp & ATMEGA_UEINTX_RXSTPI) {
- if (td->remainder == 0) {
- /*
- * We are actually complete and have
- * received the next SETUP
- */
- DPRINTFN(5, "faking complete\n");
- return (0); /* complete */
- }
- /*
- * USB Host Aborted the transfer.
- */
- td->error = 1;
- return (0); /* complete */
- }
- /* check status */
- if (!(temp & (ATMEGA_UEINTX_FIFOCON |
- ATMEGA_UEINTX_RXOUTI))) {
- /* no data */
- goto not_complete;
- }
- /* get the packet byte count */
- count =
- (ATMEGA_READ_1(sc, ATMEGA_UEBCHX) << 8) |
- (ATMEGA_READ_1(sc, ATMEGA_UEBCLX));
-
- /* mask away undefined bits */
- count &= 0x7FF;
-
- /* verify the packet byte count */
- if (count != td->max_packet_size) {
- if (count < td->max_packet_size) {
- /* we have a short packet */
- td->short_pkt = 1;
- got_short = 1;
- } else {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- }
- /* verify the packet byte count */
- if (count > td->remainder) {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- while (count > 0) {
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* receive data */
- ATMEGA_READ_MULTI_1(sc, ATMEGA_UEDATX,
- buf_res.buffer, buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* clear OUT packet interrupt */
- ATMEGA_WRITE_1(sc, ATMEGA_UEINTX, ATMEGA_UEINTX_RXOUTI ^ 0xFF);
-
- /* release FIFO bank */
- ATMEGA_WRITE_1(sc, ATMEGA_UEINTX, ATMEGA_UEINTX_FIFOCON ^ 0xFF);
-
- /* check if we are complete */
- if ((td->remainder == 0) || got_short) {
- if (td->short_pkt) {
- /* we are complete */
- return (0);
- }
- /* else need to receive a zero length packet */
- }
- if (--to) {
- goto repeat;
- }
-not_complete:
- /* we only want to know if there is a SETUP packet or OUT packet */
- ATMEGA_WRITE_1(sc, ATMEGA_UEIENX,
- ATMEGA_UEIENX_RXSTPE | ATMEGA_UEIENX_RXOUTE);
- return (1); /* not complete */
-}
-
-static uint8_t
-atmegadci_data_tx(struct atmegadci_td *td)
-{
- struct atmegadci_softc *sc;
- struct usb2_page_search buf_res;
- uint16_t count;
- uint8_t to;
- uint8_t temp;
-
- to = 3; /* don't loop forever! */
-
- /* get pointer to softc */
- sc = ATMEGA_PC2SC(td->pc);
-
- /* select endpoint number */
- ATMEGA_WRITE_1(sc, ATMEGA_UENUM, td->ep_no);
-
-repeat:
-
- /* check endpoint status */
- temp = ATMEGA_READ_1(sc, ATMEGA_UEINTX);
-
- DPRINTFN(5, "temp=0x%02x rem=%u\n", temp, td->remainder);
-
- if (temp & ATMEGA_UEINTX_RXSTPI) {
- /*
- * The current transfer was aborted
- * by the USB Host
- */
- td->error = 1;
- return (0); /* complete */
- }
- if (!(temp & (ATMEGA_UEINTX_FIFOCON |
- ATMEGA_UEINTX_TXINI))) {
- /* cannot write any data */
- goto not_complete;
- }
- count = td->max_packet_size;
- if (td->remainder < count) {
- /* we have a short packet */
- td->short_pkt = 1;
- count = td->remainder;
- }
- while (count > 0) {
-
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* transmit data */
- ATMEGA_WRITE_MULTI_1(sc, ATMEGA_UEDATX,
- buf_res.buffer, buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* clear IN packet interrupt */
- ATMEGA_WRITE_1(sc, ATMEGA_UEINTX, 0xFF ^ ATMEGA_UEINTX_TXINI);
-
- /* allocate FIFO bank */
- ATMEGA_WRITE_1(sc, ATMEGA_UEINTX, 0xFF ^ ATMEGA_UEINTX_FIFOCON);
-
- /* check remainder */
- if (td->remainder == 0) {
- if (td->short_pkt) {
- return (0); /* complete */
- }
- /* else we need to transmit a short packet */
- }
- if (--to) {
- goto repeat;
- }
-not_complete:
- /* we only want to know if there is a SETUP packet or free IN packet */
- ATMEGA_WRITE_1(sc, ATMEGA_UEIENX,
- ATMEGA_UEIENX_RXSTPE | ATMEGA_UEIENX_TXINE);
- return (1); /* not complete */
-}
-
-static uint8_t
-atmegadci_data_tx_sync(struct atmegadci_td *td)
-{
- struct atmegadci_softc *sc;
- uint8_t temp;
-
- /* get pointer to softc */
- sc = ATMEGA_PC2SC(td->pc);
-
- /* select endpoint number */
- ATMEGA_WRITE_1(sc, ATMEGA_UENUM, td->ep_no);
-
- /* check endpoint status */
- temp = ATMEGA_READ_1(sc, ATMEGA_UEINTX);
-
- DPRINTFN(5, "temp=0x%02x\n", temp);
-
- if (temp & ATMEGA_UEINTX_RXSTPI) {
- DPRINTFN(5, "faking complete\n");
- /* Race condition */
- return (0); /* complete */
- }
- /*
- * The control endpoint has only got one bank, so if that bank
- * is free the packet has been transferred!
- */
- if (!(temp & (ATMEGA_UEINTX_FIFOCON |
- ATMEGA_UEINTX_TXINI))) {
- /* cannot write any data */
- goto not_complete;
- }
- if (sc->sc_dv_addr != 0xFF) {
- /* set new address */
- atmegadci_set_address(sc, sc->sc_dv_addr);
- }
- return (0); /* complete */
-
-not_complete:
- /* we only want to know if there is a SETUP packet or free IN packet */
- ATMEGA_WRITE_1(sc, ATMEGA_UEIENX,
- ATMEGA_UEIENX_RXSTPE | ATMEGA_UEIENX_TXINE);
- return (1); /* not complete */
-}
-
-static uint8_t
-atmegadci_xfer_do_fifo(struct usb2_xfer *xfer)
-{
- struct atmegadci_td *td;
-
- DPRINTFN(9, "\n");
-
- td = xfer->td_transfer_cache;
- while (1) {
- if ((td->func) (td)) {
- /* operation in progress */
- break;
- }
- if (((void *)td) == xfer->td_transfer_last) {
- goto done;
- }
- if (td->error) {
- goto done;
- } else if (td->remainder > 0) {
- /*
- * We had a short transfer. If there is no alternate
- * next, stop processing !
- */
- if (!td->alt_next) {
- goto done;
- }
- }
- /*
- * Fetch the next transfer descriptor and transfer
- * some flags to the next transfer descriptor
- */
- td = td->obj_next;
- xfer->td_transfer_cache = td;
- }
- return (1); /* not complete */
-
-done:
- /* compute all actual lengths */
-
- atmegadci_standard_done(xfer);
- return (0); /* complete */
-}
-
-static void
-atmegadci_interrupt_poll(struct atmegadci_softc *sc)
-{
- struct usb2_xfer *xfer;
-
-repeat:
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- if (!atmegadci_xfer_do_fifo(xfer)) {
- /* queue has been modified */
- goto repeat;
- }
- }
-}
-
-static void
-atmegadci_vbus_interrupt(struct atmegadci_softc *sc, uint8_t is_on)
-{
- DPRINTFN(5, "vbus = %u\n", is_on);
-
- if (is_on) {
- if (!sc->sc_flags.status_vbus) {
- sc->sc_flags.status_vbus = 1;
-
- /* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
- }
- } else {
- if (sc->sc_flags.status_vbus) {
- sc->sc_flags.status_vbus = 0;
- sc->sc_flags.status_bus_reset = 0;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- /* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
- }
- }
-}
-
-void
-atmegadci_interrupt(struct atmegadci_softc *sc)
-{
- uint8_t status;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* read interrupt status */
- status = ATMEGA_READ_1(sc, ATMEGA_UDINT);
-
- /* clear all set interrupts */
- ATMEGA_WRITE_1(sc, ATMEGA_UDINT, ~status);
-
- /* check for any bus state change interrupts */
- if (status & ATMEGA_UDINT_EORSTI) {
-
- DPRINTFN(5, "end of reset\n");
-
- /* set correct state */
- sc->sc_flags.status_bus_reset = 1;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- /* disable resume interrupt */
- ATMEGA_WRITE_1(sc, ATMEGA_UDIEN,
- ATMEGA_UDINT_SUSPE |
- ATMEGA_UDINT_EORSTE);
-
- /* complete root HUB interrupt endpoint */
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
- }
- /*
- * If resume and suspend is set at the same time we interpret
- * that like RESUME. Resume is set when there is at least 3
- * milliseconds of inactivity on the USB BUS.
- */
- if (status & ATMEGA_UDINT_EORSMI) {
-
- DPRINTFN(5, "resume interrupt\n");
-
- if (sc->sc_flags.status_suspend) {
- /* update status bits */
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 1;
-
- /* disable resume interrupt */
- ATMEGA_WRITE_1(sc, ATMEGA_UDIEN,
- ATMEGA_UDINT_SUSPE |
- ATMEGA_UDINT_EORSTE);
-
- /* complete root HUB interrupt endpoint */
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
- }
- } else if (status & ATMEGA_UDINT_SUSPI) {
-
- DPRINTFN(5, "suspend interrupt\n");
-
- if (!sc->sc_flags.status_suspend) {
- /* update status bits */
- sc->sc_flags.status_suspend = 1;
- sc->sc_flags.change_suspend = 1;
-
- /* disable suspend interrupt */
- ATMEGA_WRITE_1(sc, ATMEGA_UDIEN,
- ATMEGA_UDINT_EORSMI |
- ATMEGA_UDINT_EORSTE);
-
- /* complete root HUB interrupt endpoint */
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
- }
- }
- /* check VBUS */
- status = ATMEGA_READ_1(sc, ATMEGA_USBINT);
-
- /* clear all set interrupts */
- ATMEGA_WRITE_1(sc, ATMEGA_USBINT, ~status);
-
- if (status & ATMEGA_USBINT_VBUSTI) {
- uint8_t temp;
-
- temp = ATMEGA_READ_1(sc, ATMEGA_USBSTA);
- atmegadci_vbus_interrupt(sc, temp & ATMEGA_USBSTA_VBUS);
- }
- /* check for any endpoint interrupts */
- status = ATMEGA_READ_1(sc, ATMEGA_UEINT);
-
- /* clear all set interrupts */
- ATMEGA_WRITE_1(sc, ATMEGA_UEINT, ~status);
-
- if (status) {
-
- DPRINTFN(5, "real endpoint interrupt 0x%02x\n", status);
-
- atmegadci_interrupt_poll(sc);
- }
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-static void
-atmegadci_setup_standard_chain_sub(struct atmegadci_std_temp *temp)
-{
- struct atmegadci_td *td;
-
- /* get current Transfer Descriptor */
- td = temp->td_next;
- temp->td = td;
-
- /* prepare for next TD */
- temp->td_next = td->obj_next;
-
- /* fill out the Transfer Descriptor */
- td->func = temp->func;
- td->pc = temp->pc;
- td->offset = temp->offset;
- td->remainder = temp->len;
- td->error = 0;
- td->did_stall = 0;
- td->short_pkt = temp->short_pkt;
- td->alt_next = temp->setup_alt_next;
-}
-
-static void
-atmegadci_setup_standard_chain(struct usb2_xfer *xfer)
-{
- struct atmegadci_std_temp temp;
- struct atmegadci_softc *sc;
- struct atmegadci_td *td;
- uint32_t x;
- uint8_t ep_no;
- uint8_t need_sync;
-
- DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
- xfer->address, UE_GET_ADDR(xfer->endpoint),
- xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
-
- temp.max_frame_size = xfer->max_frame_size;
-
- td = xfer->td_start[0];
- xfer->td_transfer_first = td;
- xfer->td_transfer_cache = td;
-
- /* setup temp */
-
- temp.td = NULL;
- temp.td_next = xfer->td_start[0];
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.offset = 0;
-
- sc = ATMEGA_BUS2SC(xfer->xroot->bus);
- ep_no = (xfer->endpoint & UE_ADDR);
-
- /* check if we should prepend a setup message */
-
- if (xfer->flags_int.control_xfr) {
- if (xfer->flags_int.control_hdr) {
-
- temp.func = &atmegadci_setup_rx;
- temp.len = xfer->frlengths[0];
- temp.pc = xfer->frbuffers + 0;
- temp.short_pkt = temp.len ? 1 : 0;
-
- atmegadci_setup_standard_chain_sub(&temp);
- }
- x = 1;
- } else {
- x = 0;
- }
-
- if (x != xfer->nframes) {
- if (xfer->endpoint & UE_DIR_IN) {
- temp.func = &atmegadci_data_tx;
- need_sync = 1;
- } else {
- temp.func = &atmegadci_data_rx;
- need_sync = 0;
- }
-
- /* setup "pc" pointer */
- temp.pc = xfer->frbuffers + x;
- } else {
- need_sync = 0;
- }
- while (x != xfer->nframes) {
-
- /* DATA0 / DATA1 message */
-
- temp.len = xfer->frlengths[x];
-
- x++;
-
- if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
- }
- if (temp.len == 0) {
-
- /* make sure that we send an USB packet */
-
- temp.short_pkt = 0;
-
- } else {
-
- /* regular data transfer */
-
- temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1;
- }
-
- atmegadci_setup_standard_chain_sub(&temp);
-
- if (xfer->flags_int.isochronous_xfr) {
- temp.offset += temp.len;
- } else {
- /* get next Page Cache pointer */
- temp.pc = xfer->frbuffers + x;
- }
- }
-
- /* always setup a valid "pc" pointer for status and sync */
- temp.pc = xfer->frbuffers + 0;
-
- /* check if we need to sync */
- if (need_sync && xfer->flags_int.control_xfr) {
-
- /* we need a SYNC point after TX */
- temp.func = &atmegadci_data_tx_sync;
- temp.len = 0;
- temp.short_pkt = 0;
-
- atmegadci_setup_standard_chain_sub(&temp);
- }
- /* check if we should append a status stage */
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- /*
- * Send a DATA1 message and invert the current
- * endpoint direction.
- */
- if (xfer->endpoint & UE_DIR_IN) {
- temp.func = &atmegadci_data_rx;
- need_sync = 0;
- } else {
- temp.func = &atmegadci_data_tx;
- need_sync = 1;
- }
- temp.len = 0;
- temp.short_pkt = 0;
-
- atmegadci_setup_standard_chain_sub(&temp);
- if (need_sync) {
- /* we need a SYNC point after TX */
- temp.func = &atmegadci_data_tx_sync;
- temp.len = 0;
- temp.short_pkt = 0;
-
- atmegadci_setup_standard_chain_sub(&temp);
- }
- }
- /* must have at least one frame! */
- td = temp.td;
- xfer->td_transfer_last = td;
-}
-
-static void
-atmegadci_timeout(void *arg)
-{
- struct usb2_xfer *xfer = arg;
-
- DPRINTF("xfer=%p\n", xfer);
-
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- /* transfer is transferred */
- atmegadci_device_done(xfer, USB_ERR_TIMEOUT);
-}
-
-static void
-atmegadci_start_standard_chain(struct usb2_xfer *xfer)
-{
- DPRINTFN(9, "\n");
-
- /* poll one time - will turn on interrupts */
- if (atmegadci_xfer_do_fifo(xfer)) {
-
- /* put transfer on interrupt queue */
- usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
-
- /* start timeout, if any */
- if (xfer->timeout != 0) {
- usb2_transfer_timeout_ms(xfer,
- &atmegadci_timeout, xfer->timeout);
- }
- }
-}
-
-static void
-atmegadci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
- DPRINTFN(9, "\n");
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- atmegadci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
- /* set port bit */
- sc->sc_hub_idata[0] = 0x02; /* we only have one port */
-
-done:
- return;
-}
-
-static usb2_error_t
-atmegadci_standard_done_sub(struct usb2_xfer *xfer)
-{
- struct atmegadci_td *td;
- uint32_t len;
- uint8_t error;
-
- DPRINTFN(9, "\n");
-
- td = xfer->td_transfer_cache;
-
- do {
- len = td->remainder;
-
- if (xfer->aframes != xfer->nframes) {
- /*
- * Verify the length and subtract
- * the remainder from "frlengths[]":
- */
- if (len > xfer->frlengths[xfer->aframes]) {
- td->error = 1;
- } else {
- xfer->frlengths[xfer->aframes] -= len;
- }
- }
- /* Check for transfer error */
- if (td->error) {
- /* the transfer is finished */
- error = 1;
- td = NULL;
- break;
- }
- /* Check for short transfer */
- if (len > 0) {
- if (xfer->flags_int.short_frames_ok) {
- /* follow alt next */
- if (td->alt_next) {
- td = td->obj_next;
- } else {
- td = NULL;
- }
- } else {
- /* the transfer is finished */
- td = NULL;
- }
- error = 0;
- break;
- }
- td = td->obj_next;
-
- /* this USB frame is complete */
- error = 0;
- break;
-
- } while (0);
-
- /* update transfer cache */
-
- xfer->td_transfer_cache = td;
-
- return (error ?
- USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION);
-}
-
-static void
-atmegadci_standard_done(struct usb2_xfer *xfer)
-{
- usb2_error_t err = 0;
-
- DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
- /* reset scanner */
-
- xfer->td_transfer_cache = xfer->td_transfer_first;
-
- if (xfer->flags_int.control_xfr) {
-
- if (xfer->flags_int.control_hdr) {
-
- err = atmegadci_standard_done_sub(xfer);
- }
- xfer->aframes = 1;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
- while (xfer->aframes != xfer->nframes) {
-
- err = atmegadci_standard_done_sub(xfer);
- xfer->aframes++;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- err = atmegadci_standard_done_sub(xfer);
- }
-done:
- atmegadci_device_done(xfer, err);
-}
-
-/*------------------------------------------------------------------------*
- * atmegadci_device_done
- *
- * NOTE: this function can be called more than one time on the
- * same USB transfer!
- *------------------------------------------------------------------------*/
-static void
-atmegadci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
- uint8_t ep_no;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
- xfer, xfer->pipe, error);
-
- if (xfer->flags_int.usb2_mode == USB_MODE_DEVICE) {
- ep_no = (xfer->endpoint & UE_ADDR);
-
- /* select endpoint number */
- ATMEGA_WRITE_1(sc, ATMEGA_UENUM, ep_no);
-
- /* disable endpoint interrupt */
- ATMEGA_WRITE_1(sc, ATMEGA_UEIENX, 0);
-
- DPRINTFN(15, "disabled interrupts!\n");
- }
- /* dequeue transfer and start next transfer */
- usb2_transfer_done(xfer, error);
-}
-
-static void
-atmegadci_set_stall(struct usb2_device *udev, struct usb2_xfer *xfer,
- struct usb2_pipe *pipe)
-{
- struct atmegadci_softc *sc;
- uint8_t ep_no;
-
- USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
-
- DPRINTFN(5, "pipe=%p\n", pipe);
-
- if (xfer) {
- /* cancel any ongoing transfers */
- atmegadci_device_done(xfer, USB_ERR_STALLED);
- }
- sc = ATMEGA_BUS2SC(udev->bus);
- /* get endpoint number */
- ep_no = (pipe->edesc->bEndpointAddress & UE_ADDR);
- /* select endpoint number */
- ATMEGA_WRITE_1(sc, ATMEGA_UENUM, ep_no);
- /* set stall */
- ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
- ATMEGA_UECONX_EPEN |
- ATMEGA_UECONX_STALLRQ);
-}
-
-static void
-atmegadci_clear_stall_sub(struct atmegadci_softc *sc, uint8_t ep_no,
- uint8_t ep_type, uint8_t ep_dir)
-{
- uint8_t temp;
-
- if (ep_type == UE_CONTROL) {
- /* clearing stall is not needed */
- return;
- }
- /* select endpoint number */
- ATMEGA_WRITE_1(sc, ATMEGA_UENUM, ep_no);
-
- /* set endpoint reset */
- ATMEGA_WRITE_1(sc, ATMEGA_UERST, ATMEGA_UERST_MASK(ep_no));
-
- /* clear endpoint reset */
- ATMEGA_WRITE_1(sc, ATMEGA_UERST, 0);
-
- /* set stall */
- ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
- ATMEGA_UECONX_EPEN |
- ATMEGA_UECONX_STALLRQ);
-
- /* reset data toggle */
- ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
- ATMEGA_UECONX_EPEN |
- ATMEGA_UECONX_RSTDT);
-
- /* clear stall */
- ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
- ATMEGA_UECONX_EPEN |
- ATMEGA_UECONX_STALLRQC);
-
- if (ep_type == UE_CONTROL) {
- /* one bank, 64-bytes wMaxPacket */
- ATMEGA_WRITE_1(sc, ATMEGA_UECFG0X,
- ATMEGA_UECFG0X_EPTYPE0);
- ATMEGA_WRITE_1(sc, ATMEGA_UECFG1X,
- ATMEGA_UECFG1X_ALLOC |
- ATMEGA_UECFG1X_EPBK0 |
- ATMEGA_UECFG1X_EPSIZE(7));
- } else {
- temp = 0;
- if (ep_type == UE_BULK) {
- temp |= ATMEGA_UECFG0X_EPTYPE2;
- } else if (ep_type == UE_INTERRUPT) {
- temp |= ATMEGA_UECFG0X_EPTYPE3;
- } else {
- temp |= ATMEGA_UECFG0X_EPTYPE1;
- }
- if (ep_dir & UE_DIR_IN) {
- temp |= ATMEGA_UECFG0X_EPDIR;
- }
- /* two banks, 64-bytes wMaxPacket */
- ATMEGA_WRITE_1(sc, ATMEGA_UECFG0X, temp);
- ATMEGA_WRITE_1(sc, ATMEGA_UECFG1X,
- ATMEGA_UECFG1X_ALLOC |
- ATMEGA_UECFG1X_EPBK1 |
- ATMEGA_UECFG1X_EPSIZE(7));
-
- temp = ATMEGA_READ_1(sc, ATMEGA_UESTA0X);
- if (!(temp & ATMEGA_UESTA0X_CFGOK)) {
- DPRINTFN(0, "Chip rejected configuration\n");
- }
- }
-}
-
-static void
-atmegadci_clear_stall(struct usb2_device *udev, struct usb2_pipe *pipe)
-{
- struct atmegadci_softc *sc;
- struct usb2_endpoint_descriptor *ed;
-
- DPRINTFN(5, "pipe=%p\n", pipe);
-
- USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
-
- /* check mode */
- if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
- /* get softc */
- sc = ATMEGA_BUS2SC(udev->bus);
-
- /* get endpoint descriptor */
- ed = pipe->edesc;
-
- /* reset endpoint */
- atmegadci_clear_stall_sub(sc,
- (ed->bEndpointAddress & UE_ADDR),
- (ed->bmAttributes & UE_XFERTYPE),
- (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT)));
-}
-
-usb2_error_t
-atmegadci_init(struct atmegadci_softc *sc)
-{
- uint8_t n;
-
- DPRINTF("start\n");
-
- /* set up the bus structure */
- sc->sc_bus.usbrev = USB_REV_1_1;
- sc->sc_bus.methods = &atmegadci_bus_methods;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* enable USB PAD regulator */
- ATMEGA_WRITE_1(sc, ATMEGA_UHWCON,
- ATMEGA_UHWCON_UVREGE);
-
- /* turn on clocks */
- (sc->sc_clocks_on) (&sc->sc_bus);
-
- /* wait a little for things to stabilise */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
-
- /* enable interrupts */
- ATMEGA_WRITE_1(sc, ATMEGA_UDIEN,
- ATMEGA_UDINT_SUSPE |
- ATMEGA_UDINT_EORSTE);
-
- /* reset all endpoints */
- ATMEGA_WRITE_1(sc, ATMEGA_UERST,
- (1 << ATMEGA_EP_MAX) - 1);
-
- /* disable reset */
- ATMEGA_WRITE_1(sc, ATMEGA_UERST, 0);
-
- /* disable all endpoints */
- for (n = 1; n != ATMEGA_EP_MAX; n++) {
-
- /* select endpoint */
- ATMEGA_WRITE_1(sc, ATMEGA_UENUM, n);
-
- /* disable endpoint interrupt */
- ATMEGA_WRITE_1(sc, ATMEGA_UEIENX, 0);
-
- /* disable endpoint */
- ATMEGA_WRITE_1(sc, ATMEGA_UECONX, 0);
- }
-
- /* turn off clocks */
-
- atmegadci_clocks_off(sc);
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- /* catch any lost interrupts */
-
- atmegadci_do_poll(&sc->sc_bus);
-
- return (0); /* success */
-}
-
-void
-atmegadci_uninit(struct atmegadci_softc *sc)
-{
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* turn on clocks */
- (sc->sc_clocks_on) (&sc->sc_bus);
-
- /* disable interrupts */
- ATMEGA_WRITE_1(sc, ATMEGA_UDIEN, 0);
-
- /* reset all endpoints */
- ATMEGA_WRITE_1(sc, ATMEGA_UERST,
- (1 << ATMEGA_EP_MAX) - 1);
-
- /* disable reset */
- ATMEGA_WRITE_1(sc, ATMEGA_UERST, 0);
-
- sc->sc_flags.port_powered = 0;
- sc->sc_flags.status_vbus = 0;
- sc->sc_flags.status_bus_reset = 0;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- atmegadci_pull_down(sc);
- atmegadci_clocks_off(sc);
-
- /* disable USB PAD regulator */
- ATMEGA_WRITE_1(sc, ATMEGA_UHWCON, 0);
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-void
-atmegadci_suspend(struct atmegadci_softc *sc)
-{
- return;
-}
-
-void
-atmegadci_resume(struct atmegadci_softc *sc)
-{
- return;
-}
-
-static void
-atmegadci_do_poll(struct usb2_bus *bus)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(bus);
-
- USB_BUS_LOCK(&sc->sc_bus);
- atmegadci_interrupt_poll(sc);
- atmegadci_root_ctrl_poll(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-/*------------------------------------------------------------------------*
- * at91dci bulk support
- *------------------------------------------------------------------------*/
-static void
-atmegadci_device_bulk_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_bulk_close(struct usb2_xfer *xfer)
-{
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-atmegadci_device_bulk_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_bulk_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- atmegadci_setup_standard_chain(xfer);
- atmegadci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods atmegadci_device_bulk_methods =
-{
- .open = atmegadci_device_bulk_open,
- .close = atmegadci_device_bulk_close,
- .enter = atmegadci_device_bulk_enter,
- .start = atmegadci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci control support
- *------------------------------------------------------------------------*/
-static void
-atmegadci_device_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_ctrl_close(struct usb2_xfer *xfer)
-{
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-atmegadci_device_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_ctrl_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- atmegadci_setup_standard_chain(xfer);
- atmegadci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods atmegadci_device_ctrl_methods =
-{
- .open = atmegadci_device_ctrl_open,
- .close = atmegadci_device_ctrl_close,
- .enter = atmegadci_device_ctrl_enter,
- .start = atmegadci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci interrupt support
- *------------------------------------------------------------------------*/
-static void
-atmegadci_device_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_intr_close(struct usb2_xfer *xfer)
-{
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-atmegadci_device_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_intr_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- atmegadci_setup_standard_chain(xfer);
- atmegadci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods atmegadci_device_intr_methods =
-{
- .open = atmegadci_device_intr_open,
- .close = atmegadci_device_intr_close,
- .enter = atmegadci_device_intr_enter,
- .start = atmegadci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci full speed isochronous support
- *------------------------------------------------------------------------*/
-static void
-atmegadci_device_isoc_fs_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_isoc_fs_close(struct usb2_xfer *xfer)
-{
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-atmegadci_device_isoc_fs_enter(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
- uint32_t temp;
- uint32_t nframes;
-
- DPRINTFN(6, "xfer=%p next=%d nframes=%d\n",
- xfer, xfer->pipe->isoc_next, xfer->nframes);
-
- /* get the current frame index */
-
- nframes =
- (ATMEGA_READ_1(sc, ATMEGA_UDFNUMH) << 8) |
- (ATMEGA_READ_1(sc, ATMEGA_UDFNUML));
-
- nframes &= ATMEGA_FRAME_MASK;
-
- /*
- * check if the frame index is within the window where the frames
- * will be inserted
- */
- temp = (nframes - xfer->pipe->isoc_next) & ATMEGA_FRAME_MASK;
-
- if ((xfer->pipe->is_synced == 0) ||
- (temp < xfer->nframes)) {
- /*
- * If there is data underflow or the pipe queue is
- * empty we schedule the transfer a few frames ahead
- * of the current frame position. Else two isochronous
- * transfers might overlap.
- */
- xfer->pipe->isoc_next = (nframes + 3) & ATMEGA_FRAME_MASK;
- xfer->pipe->is_synced = 1;
- DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next);
- }
- /*
- * compute how many milliseconds the insertion is ahead of the
- * current frame position:
- */
- temp = (xfer->pipe->isoc_next - nframes) & ATMEGA_FRAME_MASK;
-
- /*
- * pre-compute when the isochronous transfer will be finished:
- */
- xfer->isoc_time_complete =
- usb2_isoc_time_expand(&sc->sc_bus, nframes) + temp +
- xfer->nframes;
-
- /* compute frame number for next insertion */
- xfer->pipe->isoc_next += xfer->nframes;
-
- /* setup TDs */
- atmegadci_setup_standard_chain(xfer);
-}
-
-static void
-atmegadci_device_isoc_fs_start(struct usb2_xfer *xfer)
-{
- /* start TD chain */
- atmegadci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods atmegadci_device_isoc_fs_methods =
-{
- .open = atmegadci_device_isoc_fs_open,
- .close = atmegadci_device_isoc_fs_close,
- .enter = atmegadci_device_isoc_fs_enter,
- .start = atmegadci_device_isoc_fs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci root control support
- *------------------------------------------------------------------------*
- * simulate a hardware HUB by handling
- * all the necessary requests
- *------------------------------------------------------------------------*/
-
-static void
-atmegadci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/*
- * USB descriptors for the virtual Root HUB:
- */
-
-static const struct usb2_device_descriptor atmegadci_devd = {
- .bLength = sizeof(struct usb2_device_descriptor),
- .bDescriptorType = UDESC_DEVICE,
- .bcdUSB = {0x00, 0x02},
- .bDeviceClass = UDCLASS_HUB,
- .bDeviceSubClass = UDSUBCLASS_HUB,
- .bDeviceProtocol = UDPROTO_HSHUBSTT,
- .bMaxPacketSize = 64,
- .bcdDevice = {0x00, 0x01},
- .iManufacturer = 1,
- .iProduct = 2,
- .bNumConfigurations = 1,
-};
-
-static const struct usb2_device_qualifier atmegadci_odevd = {
- .bLength = sizeof(struct usb2_device_qualifier),
- .bDescriptorType = UDESC_DEVICE_QUALIFIER,
- .bcdUSB = {0x00, 0x02},
- .bDeviceClass = UDCLASS_HUB,
- .bDeviceSubClass = UDSUBCLASS_HUB,
- .bDeviceProtocol = UDPROTO_FSHUB,
- .bMaxPacketSize0 = 0,
- .bNumConfigurations = 0,
-};
-
-static const struct atmegadci_config_desc atmegadci_confd = {
- .confd = {
- .bLength = sizeof(struct usb2_config_descriptor),
- .bDescriptorType = UDESC_CONFIG,
- .wTotalLength[0] = sizeof(atmegadci_confd),
- .bNumInterface = 1,
- .bConfigurationValue = 1,
- .iConfiguration = 0,
- .bmAttributes = UC_SELF_POWERED,
- .bMaxPower = 0,
- },
- .ifcd = {
- .bLength = sizeof(struct usb2_interface_descriptor),
- .bDescriptorType = UDESC_INTERFACE,
- .bNumEndpoints = 1,
- .bInterfaceClass = UICLASS_HUB,
- .bInterfaceSubClass = UISUBCLASS_HUB,
- .bInterfaceProtocol = UIPROTO_HSHUBSTT,
- },
-
- .endpd = {
- .bLength = sizeof(struct usb2_endpoint_descriptor),
- .bDescriptorType = UDESC_ENDPOINT,
- .bEndpointAddress = (UE_DIR_IN | ATMEGA_INTR_ENDPT),
- .bmAttributes = UE_INTERRUPT,
- .wMaxPacketSize[0] = 8,
- .bInterval = 255,
- },
-};
-
-static const struct usb2_hub_descriptor_min atmegadci_hubd = {
- .bDescLength = sizeof(atmegadci_hubd),
- .bDescriptorType = UDESC_HUB,
- .bNbrPorts = 1,
- .wHubCharacteristics[0] =
- (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) & 0xFF,
- .wHubCharacteristics[1] =
- (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 8,
- .bPwrOn2PwrGood = 50,
- .bHubContrCurrent = 0,
- .DeviceRemovable = {0}, /* port is removable */
-};
-
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
-#define STRING_VENDOR \
- 'A', 0, 'T', 0, 'M', 0, 'E', 0, 'G', 0, 'A', 0
-
-#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
-
-USB_MAKE_STRING_DESC(STRING_LANG, atmegadci_langtab);
-USB_MAKE_STRING_DESC(STRING_VENDOR, atmegadci_vendor);
-USB_MAKE_STRING_DESC(STRING_PRODUCT, atmegadci_product);
-
-static void
-atmegadci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-atmegadci_root_ctrl_task(struct usb2_bus *bus)
-{
- atmegadci_root_ctrl_poll(ATMEGA_BUS2SC(bus));
-}
-
-static void
-atmegadci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
- uint16_t value;
- uint16_t index;
- uint8_t use_polling;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- atmegadci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* buffer reset */
- std->ptr = USB_ADD_BYTES(&sc->sc_hub_temp, 0);
- std->len = 0;
-
- value = UGETW(std->req.wValue);
- index = UGETW(std->req.wIndex);
-
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- /* demultiplex the control request */
-
- switch (std->req.bmRequestType) {
- case UT_READ_DEVICE:
- switch (std->req.bRequest) {
- case UR_GET_DESCRIPTOR:
- goto tr_handle_get_descriptor;
- case UR_GET_CONFIG:
- goto tr_handle_get_config;
- case UR_GET_STATUS:
- goto tr_handle_get_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_DEVICE:
- switch (std->req.bRequest) {
- case UR_SET_ADDRESS:
- goto tr_handle_set_address;
- case UR_SET_CONFIG:
- goto tr_handle_set_config;
- case UR_CLEAR_FEATURE:
- goto tr_valid; /* nop */
- case UR_SET_DESCRIPTOR:
- goto tr_valid; /* nop */
- case UR_SET_FEATURE:
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_ENDPOINT:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- switch (UGETW(std->req.wValue)) {
- case UF_ENDPOINT_HALT:
- goto tr_handle_clear_halt;
- case UF_DEVICE_REMOTE_WAKEUP:
- goto tr_handle_clear_wakeup;
- default:
- goto tr_stalled;
- }
- break;
- case UR_SET_FEATURE:
- switch (UGETW(std->req.wValue)) {
- case UF_ENDPOINT_HALT:
- goto tr_handle_set_halt;
- case UF_DEVICE_REMOTE_WAKEUP:
- goto tr_handle_set_wakeup;
- default:
- goto tr_stalled;
- }
- break;
- case UR_SYNCH_FRAME:
- goto tr_valid; /* nop */
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_ENDPOINT:
- switch (std->req.bRequest) {
- case UR_GET_STATUS:
- goto tr_handle_get_ep_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_INTERFACE:
- switch (std->req.bRequest) {
- case UR_SET_INTERFACE:
- goto tr_handle_set_interface;
- case UR_CLEAR_FEATURE:
- goto tr_valid; /* nop */
- case UR_SET_FEATURE:
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_INTERFACE:
- switch (std->req.bRequest) {
- case UR_GET_INTERFACE:
- goto tr_handle_get_interface;
- case UR_GET_STATUS:
- goto tr_handle_get_iface_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_CLASS_INTERFACE:
- case UT_WRITE_VENDOR_INTERFACE:
- /* XXX forward */
- break;
-
- case UT_READ_CLASS_INTERFACE:
- case UT_READ_VENDOR_INTERFACE:
- /* XXX forward */
- break;
-
- case UT_WRITE_CLASS_DEVICE:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- goto tr_valid;
- case UR_SET_DESCRIPTOR:
- case UR_SET_FEATURE:
- break;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_CLASS_OTHER:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- goto tr_handle_clear_port_feature;
- case UR_SET_FEATURE:
- goto tr_handle_set_port_feature;
- case UR_CLEAR_TT_BUFFER:
- case UR_RESET_TT:
- case UR_STOP_TT:
- goto tr_valid;
-
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_CLASS_OTHER:
- switch (std->req.bRequest) {
- case UR_GET_TT_STATE:
- goto tr_handle_get_tt_state;
- case UR_GET_STATUS:
- goto tr_handle_get_port_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_CLASS_DEVICE:
- switch (std->req.bRequest) {
- case UR_GET_DESCRIPTOR:
- goto tr_handle_get_class_descriptor;
- case UR_GET_STATUS:
- goto tr_handle_get_class_status;
-
- default:
- goto tr_stalled;
- }
- break;
- default:
- goto tr_stalled;
- }
- goto tr_valid;
-
-tr_handle_get_descriptor:
- switch (value >> 8) {
- case UDESC_DEVICE:
- if (value & 0xff) {
- goto tr_stalled;
- }
- std->len = sizeof(atmegadci_devd);
- std->ptr = USB_ADD_BYTES(&atmegadci_devd, 0);
- goto tr_valid;
- case UDESC_CONFIG:
- if (value & 0xff) {
- goto tr_stalled;
- }
- std->len = sizeof(atmegadci_confd);
- std->ptr = USB_ADD_BYTES(&atmegadci_confd, 0);
- goto tr_valid;
- case UDESC_STRING:
- switch (value & 0xff) {
- case 0: /* Language table */
- std->len = sizeof(atmegadci_langtab);
- std->ptr = USB_ADD_BYTES(&atmegadci_langtab, 0);
- goto tr_valid;
-
- case 1: /* Vendor */
- std->len = sizeof(atmegadci_vendor);
- std->ptr = USB_ADD_BYTES(&atmegadci_vendor, 0);
- goto tr_valid;
-
- case 2: /* Product */
- std->len = sizeof(atmegadci_product);
- std->ptr = USB_ADD_BYTES(&atmegadci_product, 0);
- goto tr_valid;
- default:
- break;
- }
- break;
- default:
- goto tr_stalled;
- }
- goto tr_stalled;
-
-tr_handle_get_config:
- std->len = 1;
- sc->sc_hub_temp.wValue[0] = sc->sc_conf;
- goto tr_valid;
-
-tr_handle_get_status:
- std->len = 2;
- USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED);
- goto tr_valid;
-
-tr_handle_set_address:
- if (value & 0xFF00) {
- goto tr_stalled;
- }
- sc->sc_rt_addr = value;
- goto tr_valid;
-
-tr_handle_set_config:
- if (value >= 2) {
- goto tr_stalled;
- }
- sc->sc_conf = value;
- goto tr_valid;
-
-tr_handle_get_interface:
- std->len = 1;
- sc->sc_hub_temp.wValue[0] = 0;
- goto tr_valid;
-
-tr_handle_get_tt_state:
-tr_handle_get_class_status:
-tr_handle_get_iface_status:
-tr_handle_get_ep_status:
- std->len = 2;
- USETW(sc->sc_hub_temp.wValue, 0);
- goto tr_valid;
-
-tr_handle_set_halt:
-tr_handle_set_interface:
-tr_handle_set_wakeup:
-tr_handle_clear_wakeup:
-tr_handle_clear_halt:
- goto tr_valid;
-
-tr_handle_clear_port_feature:
- if (index != 1) {
- goto tr_stalled;
- }
- DPRINTFN(9, "UR_CLEAR_PORT_FEATURE on port %d\n", index);
-
- switch (value) {
- case UHF_PORT_SUSPEND:
- atmegadci_wakeup_peer(xfer);
- break;
-
- case UHF_PORT_ENABLE:
- sc->sc_flags.port_enabled = 0;
- break;
-
- case UHF_PORT_TEST:
- case UHF_PORT_INDICATOR:
- case UHF_C_PORT_ENABLE:
- case UHF_C_PORT_OVER_CURRENT:
- case UHF_C_PORT_RESET:
- /* nops */
- break;
- case UHF_PORT_POWER:
- sc->sc_flags.port_powered = 0;
- atmegadci_pull_down(sc);
- atmegadci_clocks_off(sc);
- break;
- case UHF_C_PORT_CONNECTION:
- sc->sc_flags.change_connect = 0;
- break;
- case UHF_C_PORT_SUSPEND:
- sc->sc_flags.change_suspend = 0;
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- goto tr_valid;
-
-tr_handle_set_port_feature:
- if (index != 1) {
- goto tr_stalled;
- }
- DPRINTFN(9, "UR_SET_PORT_FEATURE\n");
-
- switch (value) {
- case UHF_PORT_ENABLE:
- sc->sc_flags.port_enabled = 1;
- break;
- case UHF_PORT_SUSPEND:
- case UHF_PORT_RESET:
- case UHF_PORT_TEST:
- case UHF_PORT_INDICATOR:
- /* nops */
- break;
- case UHF_PORT_POWER:
- sc->sc_flags.port_powered = 1;
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- goto tr_valid;
-
-tr_handle_get_port_status:
-
- DPRINTFN(9, "UR_GET_PORT_STATUS\n");
-
- if (index != 1) {
- goto tr_stalled;
- }
- if (sc->sc_flags.status_vbus) {
- atmegadci_clocks_on(sc);
- atmegadci_pull_up(sc);
- } else {
- atmegadci_pull_down(sc);
- atmegadci_clocks_off(sc);
- }
-
- /* Select FULL-speed and Device Side Mode */
-
- value = UPS_PORT_MODE_DEVICE;
-
- if (sc->sc_flags.port_powered) {
- value |= UPS_PORT_POWER;
- }
- if (sc->sc_flags.port_enabled) {
- value |= UPS_PORT_ENABLED;
- }
- if (sc->sc_flags.status_vbus &&
- sc->sc_flags.status_bus_reset) {
- value |= UPS_CURRENT_CONNECT_STATUS;
- }
- if (sc->sc_flags.status_suspend) {
- value |= UPS_SUSPEND;
- }
- USETW(sc->sc_hub_temp.ps.wPortStatus, value);
-
- value = 0;
-
- if (sc->sc_flags.change_connect) {
- value |= UPS_C_CONNECT_STATUS;
- }
- if (sc->sc_flags.change_suspend) {
- value |= UPS_C_SUSPEND;
- }
- USETW(sc->sc_hub_temp.ps.wPortChange, value);
- std->len = sizeof(sc->sc_hub_temp.ps);
- goto tr_valid;
-
-tr_handle_get_class_descriptor:
- if (value & 0xFF) {
- goto tr_stalled;
- }
- std->ptr = USB_ADD_BYTES(&atmegadci_hubd, 0);
- std->len = sizeof(atmegadci_hubd);
- goto tr_valid;
-
-tr_stalled:
- std->err = USB_ERR_STALLED;
-tr_valid:
-done:
- return;
-}
-
-static void
-atmegadci_root_ctrl_poll(struct atmegadci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &atmegadci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods atmegadci_root_ctrl_methods =
-{
- .open = atmegadci_root_ctrl_open,
- .close = atmegadci_root_ctrl_close,
- .enter = atmegadci_root_ctrl_enter,
- .start = atmegadci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-atmegadci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_root_intr_close(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-atmegadci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_root_intr_start(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods atmegadci_root_intr_methods =
-{
- .open = atmegadci_root_intr_open,
- .close = atmegadci_root_intr_close,
- .enter = atmegadci_root_intr_enter,
- .start = atmegadci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
-atmegadci_xfer_setup(struct usb2_setup_params *parm)
-{
- const struct usb2_hw_ep_profile *pf;
- struct atmegadci_softc *sc;
- struct usb2_xfer *xfer;
- void *last_obj;
- uint32_t ntd;
- uint32_t n;
- uint8_t ep_no;
-
- sc = ATMEGA_BUS2SC(parm->udev->bus);
- xfer = parm->curr_xfer;
-
- /*
- * NOTE: This driver does not use any of the parameters that
- * are computed from the following values. Just set some
- * reasonable dummies:
- */
- parm->hc_max_packet_size = 0x500;
- parm->hc_max_packet_count = 1;
- parm->hc_max_frame_size = 0x500;
-
- usb2_transfer_setup_sub(parm);
-
- /*
- * compute maximum number of TDs
- */
- if (parm->methods == &atmegadci_device_ctrl_methods) {
-
- ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC 1 */
- + 1 /* SYNC 2 */ ;
-
- } else if (parm->methods == &atmegadci_device_bulk_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &atmegadci_device_intr_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &atmegadci_device_isoc_fs_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else {
-
- ntd = 0;
- }
-
- /*
- * check if "usb2_transfer_setup_sub" set an error
- */
- if (parm->err) {
- return;
- }
- /*
- * allocate transfer descriptors
- */
- last_obj = NULL;
-
- /*
- * get profile stuff
- */
- if (ntd) {
-
- ep_no = xfer->endpoint & UE_ADDR;
- atmegadci_get_hw_ep_profile(parm->udev, &pf, ep_no);
-
- if (pf == NULL) {
- /* should not happen */
- parm->err = USB_ERR_INVAL;
- return;
- }
- } else {
- ep_no = 0;
- pf = NULL;
- }
-
- /* align data */
- parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
-
- for (n = 0; n != ntd; n++) {
-
- struct atmegadci_td *td;
-
- if (parm->buf) {
-
- td = USB_ADD_BYTES(parm->buf, parm->size[0]);
-
- /* init TD */
- td->max_packet_size = xfer->max_packet_size;
- td->ep_no = ep_no;
- if (pf->support_multi_buffer) {
- td->support_multi_buffer = 1;
- }
- td->obj_next = last_obj;
-
- last_obj = td;
- }
- parm->size[0] += sizeof(*td);
- }
-
- xfer->td_start[0] = last_obj;
-}
-
-static void
-atmegadci_xfer_unsetup(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
- struct usb2_pipe *pipe)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(udev->bus);
-
- DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
- pipe, udev->address,
- edesc->bEndpointAddress, udev->flags.usb2_mode,
- sc->sc_rt_addr);
-
- if (udev->device_index == sc->sc_rt_addr) {
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &atmegadci_root_ctrl_methods;
- break;
- case UE_DIR_IN | ATMEGA_INTR_ENDPT:
- pipe->methods = &atmegadci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
-
- if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
- if (udev->speed != USB_SPEED_FULL) {
- /* not supported */
- return;
- }
- switch (edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- pipe->methods = &atmegadci_device_ctrl_methods;
- break;
- case UE_INTERRUPT:
- pipe->methods = &atmegadci_device_intr_methods;
- break;
- case UE_ISOCHRONOUS:
- pipe->methods = &atmegadci_device_isoc_fs_methods;
- break;
- case UE_BULK:
- pipe->methods = &atmegadci_device_bulk_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- }
-}
-
-struct usb2_bus_methods atmegadci_bus_methods =
-{
- .pipe_init = &atmegadci_pipe_init,
- .xfer_setup = &atmegadci_xfer_setup,
- .xfer_unsetup = &atmegadci_xfer_unsetup,
- .do_poll = &atmegadci_do_poll,
- .get_hw_ep_profile = &atmegadci_get_hw_ep_profile,
- .set_stall = &atmegadci_set_stall,
- .clear_stall = &atmegadci_clear_stall,
- .roothub_exec = &atmegadci_root_ctrl_task,
-};
diff --git a/sys/dev/usb2/controller/atmegadci.h b/sys/dev/usb2/controller/atmegadci.h
deleted file mode 100644
index 90b3334..0000000
--- a/sys/dev/usb2/controller/atmegadci.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2009 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-/*
- * USB Device Port register definitions, copied from ATMEGA
- * documentation provided by ATMEL.
- */
-
-#ifndef _ATMEGADCI_H_
-#define _ATMEGADCI_H_
-
-#define ATMEGA_MAX_DEVICES (USB_MIN_DEVICES + 1)
-
-#ifndef ATMEGA_HAVE_BUS_SPACE
-#define ATMEGA_HAVE_BUS_SPACE 1
-#endif
-
-#define ATMEGA_UEINT 0xF4
-#define ATMEGA_UEINT_MASK(n) (1 << (n)) /* endpoint interrupt mask */
-
-#define ATMEGA_UEBCHX 0xF3 /* FIFO byte count high */
-#define ATMEGA_UEBCLX 0xF2 /* FIFO byte count low */
-#define ATMEGA_UEDATX 0xF1 /* FIFO data */
-
-#define ATMEGA_UEIENX 0xF0 /* interrupt enable register */
-#define ATMEGA_UEIENX_TXINE (1 << 0)
-#define ATMEGA_UEIENX_STALLEDE (1 << 1)
-#define ATMEGA_UEIENX_RXOUTE (1 << 2)
-#define ATMEGA_UEIENX_RXSTPE (1 << 3) /* received SETUP packet */
-#define ATMEGA_UEIENX_NAKOUTE (1 << 4)
-#define ATMEGA_UEIENX_NAKINE (1 << 6)
-#define ATMEGA_UEIENX_FLERRE (1 << 7)
-
-#define ATMEGA_UESTA1X 0xEF
-#define ATMEGA_UESTA1X_CURRBK (3 << 0) /* current bank */
-#define ATMEGA_UESTA1X_CTRLDIR (1 << 2) /* control endpoint direction */
-
-#define ATMEGA_UESTA0X 0xEE
-#define ATMEGA_UESTA0X_NBUSYBK (3 << 0)
-#define ATMEGA_UESTA0X_DTSEQ (3 << 2)
-#define ATMEGA_UESTA0X_UNDERFI (1 << 5) /* underflow */
-#define ATMEGA_UESTA0X_OVERFI (1 << 6) /* overflow */
-#define ATMEGA_UESTA0X_CFGOK (1 << 7)
-
-#define ATMEGA_UECFG1X 0xED /* endpoint config register */
-#define ATMEGA_UECFG1X_ALLOC (1 << 1)
-#define ATMEGA_UECFG1X_EPBK0 (0 << 2)
-#define ATMEGA_UECFG1X_EPBK1 (1 << 2)
-#define ATMEGA_UECFG1X_EPBK2 (2 << 2)
-#define ATMEGA_UECFG1X_EPBK3 (3 << 2)
-#define ATMEGA_UECFG1X_EPSIZE(n) ((n) << 4)
-
-#define ATMEGA_UECFG0X 0xEC
-#define ATMEGA_UECFG0X_EPDIR (1 << 0) /* endpoint direction */
-#define ATMEGA_UECFG0X_EPTYPE0 (0 << 6)
-#define ATMEGA_UECFG0X_EPTYPE1 (1 << 6)
-#define ATMEGA_UECFG0X_EPTYPE2 (2 << 6)
-#define ATMEGA_UECFG0X_EPTYPE3 (3 << 6)
-
-#define ATMEGA_UECONX 0xEB
-#define ATMEGA_UECONX_EPEN (1 << 0)
-#define ATMEGA_UECONX_RSTDT (1 << 3)
-#define ATMEGA_UECONX_STALLRQC (1 << 4) /* stall request clear */
-#define ATMEGA_UECONX_STALLRQ (1 << 5) /* stall request set */
-
-#define ATMEGA_UERST 0xEA /* endpoint reset register */
-#define ATMEGA_UERST_MASK(n) (1 << (n))
-
-#define ATMEGA_UENUM 0xE9 /* endpoint number */
-
-#define ATMEGA_UEINTX 0xE8 /* interrupt register */
-#define ATMEGA_UEINTX_TXINI (1 << 0)
-#define ATMEGA_UEINTX_STALLEDI (1 << 1)
-#define ATMEGA_UEINTX_RXOUTI (1 << 2)
-#define ATMEGA_UEINTX_RXSTPI (1 << 3) /* received setup packet */
-#define ATMEGA_UEINTX_NAKOUTI (1 << 4)
-#define ATMEGA_UEINTX_RWAL (1 << 5)
-#define ATMEGA_UEINTX_NAKINI (1 << 6)
-#define ATMEGA_UEINTX_FIFOCON (1 << 7)
-
-#define ATMEGA_UDMFN 0xE6
-#define ATMEGA_UDMFN_FNCERR (1 << 4)
-
-#define ATMEGA_UDFNUMH 0xE5 /* frame number high */
-#define ATMEGA_UDFNUMH_MASK 7
-
-#define ATMEGA_UDFNUML 0xE4 /* frame number low */
-#define ATMEGA_UDFNUML_MASK 0xFF
-
-#define ATMEGA_FRAME_MASK 0x7FF
-
-#define ATMEGA_UDADDR 0xE3 /* USB address */
-#define ATMEGA_UDADDR_MASK 0x7F
-#define ATMEGA_UDADDR_ADDEN (1 << 7)
-
-#define ATMEGA_UDIEN 0xE2 /* USB device interrupt enable */
-#define ATMEGA_UDINT_SUSPE (1 << 0)
-#define ATMEGA_UDINT_MSOFE (1 << 1)
-#define ATMEGA_UDINT_SOFE (1 << 2)
-#define ATMEGA_UDINT_EORSTE (1 << 3)
-#define ATMEGA_UDINT_WAKEUPE (1 << 4)
-#define ATMEGA_UDINT_EORSME (1 << 5)
-#define ATMEGA_UDINT_UPRSME (1 << 6)
-
-#define ATMEGA_UDINT 0xE1 /* USB device interrupt status */
-#define ATMEGA_UDINT_SUSPI (1 << 0)
-#define ATMEGA_UDINT_MSOFI (1 << 1)
-#define ATMEGA_UDINT_SOFI (1 << 2)
-#define ATMEGA_UDINT_EORSTI (1 << 3)
-#define ATMEGA_UDINT_WAKEUPI (1 << 4)
-#define ATMEGA_UDINT_EORSMI (1 << 5)
-#define ATMEGA_UDINT_UPRSMI (1 << 6)
-
-#define ATMEGA_UDCON 0xE0 /* USB device connection register */
-#define ATMEGA_UDCON_DETACH (1 << 0)
-#define ATMEGA_UDCON_RMWKUP (1 << 1)
-#define ATMEGA_UDCON_LSM (1 << 2)
-#define ATMEGA_UDCON_RSTCPU (1 << 3)
-
-#define ATMEGA_USBINT 0xDA
-#define ATMEGA_USBINT_VBUSTI (1 << 0) /* USB VBUS interrupt */
-
-#define ATMEGA_USBSTA 0xD9
-#define ATMEGA_USBSTA_VBUS (1 << 0)
-#define ATMEGA_USBSTA_ID (1 << 1)
-
-#define ATMEGA_USBCON 0xD8
-#define ATMEGA_USBCON_VBUSTE (1 << 0)
-#define ATMEGA_USBCON_OTGPADE (1 << 4)
-#define ATMEGA_USBCON_FRZCLK (1 << 5)
-#define ATMEGA_USBCON_USBE (1 << 7)
-
-#define ATMEGA_UHWCON 0xD7
-#define ATMEGA_UHWCON_UVREGE (1 << 0)
-
-#define ATMEGA_READ_1(sc, reg) \
- bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
-
-#define ATMEGA_WRITE_1(sc, reg, data) \
- bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
-
-#define ATMEGA_WRITE_MULTI_1(sc, reg, ptr, len) \
- bus_space_write_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, ptr, len)
-
-#define ATMEGA_READ_MULTI_1(sc, reg, ptr, len) \
- bus_space_read_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, ptr, len)
-
-/*
- * Maximum number of endpoints supported:
- */
-#define ATMEGA_EP_MAX 7
-
-struct atmegadci_td;
-
-typedef uint8_t (atmegadci_cmd_t)(struct atmegadci_td *td);
-typedef void (atmegadci_clocks_t)(struct usb2_bus *);
-
-struct atmegadci_td {
- struct atmegadci_td *obj_next;
- atmegadci_cmd_t *func;
- struct usb2_page_cache *pc;
- uint32_t offset;
- uint32_t remainder;
- uint16_t max_packet_size;
- uint8_t error:1;
- uint8_t alt_next:1;
- uint8_t short_pkt:1;
- uint8_t support_multi_buffer:1;
- uint8_t did_stall:1;
- uint8_t ep_no:3;
-};
-
-struct atmegadci_std_temp {
- atmegadci_cmd_t *func;
- struct usb2_page_cache *pc;
- struct atmegadci_td *td;
- struct atmegadci_td *td_next;
- uint32_t len;
- uint32_t offset;
- uint16_t max_frame_size;
- uint8_t short_pkt;
- /*
- * short_pkt = 0: transfer should be short terminated
- * short_pkt = 1: transfer should not be short terminated
- */
- uint8_t setup_alt_next;
-};
-
-struct atmegadci_config_desc {
- struct usb2_config_descriptor confd;
- struct usb2_interface_descriptor ifcd;
- struct usb2_endpoint_descriptor endpd;
-} __packed;
-
-union atmegadci_hub_temp {
- uWord wValue;
- struct usb2_port_status ps;
-};
-
-struct atmegadci_flags {
- uint8_t change_connect:1;
- uint8_t change_suspend:1;
- uint8_t status_suspend:1; /* set if suspended */
- uint8_t status_vbus:1; /* set if present */
- uint8_t status_bus_reset:1; /* set if reset complete */
- uint8_t remote_wakeup:1;
- uint8_t self_powered:1;
- uint8_t clocks_off:1;
- uint8_t port_powered:1;
- uint8_t port_enabled:1;
- uint8_t d_pulled_up:1;
-};
-
-struct atmegadci_softc {
- struct usb2_bus sc_bus;
- union atmegadci_hub_temp sc_hub_temp;
- LIST_HEAD(, usb2_xfer) sc_interrupt_list_head;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
-
- /* must be set by by the bus interface layer */
- atmegadci_clocks_t *sc_clocks_on;
- atmegadci_clocks_t *sc_clocks_off;
-
- struct usb2_device *sc_devices[ATMEGA_MAX_DEVICES];
- struct resource *sc_irq_res;
- void *sc_intr_hdl;
-#if (ATMEGA_HAVE_BUS_SPACE != 0)
- struct resource *sc_io_res;
- bus_space_tag_t sc_io_tag;
- bus_space_handle_t sc_io_hdl;
-#endif
- uint8_t sc_rt_addr; /* root hub address */
- uint8_t sc_dv_addr; /* device address */
- uint8_t sc_conf; /* root hub config */
-
- uint8_t sc_hub_idata[1];
-
- struct atmegadci_flags sc_flags;
-};
-
-/* prototypes */
-
-usb2_error_t atmegadci_init(struct atmegadci_softc *sc);
-void atmegadci_uninit(struct atmegadci_softc *sc);
-void atmegadci_suspend(struct atmegadci_softc *sc);
-void atmegadci_resume(struct atmegadci_softc *sc);
-void atmegadci_interrupt(struct atmegadci_softc *sc);
-
-#endif /* _ATMEGADCI_H_ */
diff --git a/sys/dev/usb2/controller/atmegadci_atmelarm.c b/sys/dev/usb2/controller/atmegadci_atmelarm.c
deleted file mode 100644
index e63f5cc..0000000
--- a/sys/dev/usb2/controller/atmegadci_atmelarm.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*-
- * Copyright (c) 2009 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
diff --git a/sys/dev/usb2/controller/ehci2.c b/sys/dev/usb2/controller/ehci2.c
deleted file mode 100644
index 87a6d03..0000000
--- a/sys/dev/usb2/controller/ehci2.c
+++ /dev/null
@@ -1,3965 +0,0 @@
-/*-
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
- * Copyright (c) 2004 The NetBSD Foundation, Inc. All rights reserved.
- * Copyright (c) 2004 Lennart Augustsson. All rights reserved.
- * Copyright (c) 2004 Charles M. Hannum. 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.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-/*
- * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller.
- *
- * The EHCI 0.96 spec can be found at
- * http://developer.intel.com/technology/usb/download/ehci-r096.pdf
- * The EHCI 1.0 spec can be found at
- * http://developer.intel.com/technology/usb/download/ehci-r10.pdf
- * and the USB 2.0 spec at
- * http://www.usb.org/developers/docs/usb_20.zip
- *
- */
-
-/*
- * TODO:
- * 1) command failures are not recovered correctly
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_defs.h>
-
-#define USB_DEBUG_VAR ehcidebug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_transfer.h>
-#include <dev/usb2/core/usb2_device.h>
-#include <dev/usb2/core/usb2_hub.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/ehci2.h>
-
-#define EHCI_BUS2SC(bus) ((ehci_softc_t *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((ehci_softc_t *)0)->sc_bus))))
-
-#if USB_DEBUG
-static int ehcidebug = 0;
-static int ehcinohighspeed = 0;
-
-SYSCTL_NODE(_hw_usb2, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci");
-SYSCTL_INT(_hw_usb2_ehci, OID_AUTO, debug, CTLFLAG_RW,
- &ehcidebug, 0, "Debug level");
-SYSCTL_INT(_hw_usb2_ehci, OID_AUTO, no_hs, CTLFLAG_RW,
- &ehcinohighspeed, 0, "Disable High Speed USB");
-
-static void ehci_dump_regs(ehci_softc_t *sc);
-static void ehci_dump_sqh(ehci_softc_t *sc, ehci_qh_t *sqh);
-
-#endif
-
-#define EHCI_INTR_ENDPT 1
-
-extern struct usb2_bus_methods ehci_bus_methods;
-extern struct usb2_pipe_methods ehci_device_bulk_methods;
-extern struct usb2_pipe_methods ehci_device_ctrl_methods;
-extern struct usb2_pipe_methods ehci_device_intr_methods;
-extern struct usb2_pipe_methods ehci_device_isoc_fs_methods;
-extern struct usb2_pipe_methods ehci_device_isoc_hs_methods;
-extern struct usb2_pipe_methods ehci_root_ctrl_methods;
-extern struct usb2_pipe_methods ehci_root_intr_methods;
-
-static void ehci_do_poll(struct usb2_bus *bus);
-static void ehci_root_ctrl_poll(ehci_softc_t *sc);
-static void ehci_device_done(struct usb2_xfer *xfer, usb2_error_t error);
-static uint8_t ehci_check_transfer(struct usb2_xfer *xfer);
-static void ehci_timeout(void *arg);
-
-static usb2_sw_transfer_func_t ehci_root_intr_done;
-static usb2_sw_transfer_func_t ehci_root_ctrl_done;
-
-struct ehci_std_temp {
- ehci_softc_t *sc;
- struct usb2_page_cache *pc;
- ehci_qtd_t *td;
- ehci_qtd_t *td_next;
- uint32_t average;
- uint32_t qtd_status;
- uint32_t len;
- uint16_t max_frame_size;
- uint8_t shortpkt;
- uint8_t auto_data_toggle;
- uint8_t setup_alt_next;
- uint8_t short_frames_ok;
-};
-
-/*
- * Byte-order conversion functions.
- */
-static uint32_t
-htoehci32(ehci_softc_t *sc, const uint32_t v)
-{
- return ((sc->sc_flags & EHCI_SCFLG_BIGEDESC) ?
- htobe32(v) : htole32(v));
-}
-
-static uint32_t
-ehci32toh(ehci_softc_t *sc, const uint32_t v)
-{
- return ((sc->sc_flags & EHCI_SCFLG_BIGEDESC) ?
- be32toh(v) : le32toh(v));
-}
-
-void
-ehci_iterate_hw_softc(struct usb2_bus *bus, usb2_bus_mem_sub_cb_t *cb)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(bus);
- uint32_t i;
-
- cb(bus, &sc->sc_hw.pframes_pc, &sc->sc_hw.pframes_pg,
- sizeof(uint32_t) * EHCI_FRAMELIST_COUNT, EHCI_FRAMELIST_ALIGN);
-
- cb(bus, &sc->sc_hw.async_start_pc, &sc->sc_hw.async_start_pg,
- sizeof(ehci_qh_t), EHCI_QH_ALIGN);
-
- for (i = 0; i != EHCI_VIRTUAL_FRAMELIST_COUNT; i++) {
- cb(bus, sc->sc_hw.intr_start_pc + i,
- sc->sc_hw.intr_start_pg + i,
- sizeof(ehci_qh_t), EHCI_QH_ALIGN);
- }
-
- for (i = 0; i != EHCI_VIRTUAL_FRAMELIST_COUNT; i++) {
- cb(bus, sc->sc_hw.isoc_hs_start_pc + i,
- sc->sc_hw.isoc_hs_start_pg + i,
- sizeof(ehci_itd_t), EHCI_ITD_ALIGN);
- }
-
- for (i = 0; i != EHCI_VIRTUAL_FRAMELIST_COUNT; i++) {
- cb(bus, sc->sc_hw.isoc_fs_start_pc + i,
- sc->sc_hw.isoc_fs_start_pg + i,
- sizeof(ehci_sitd_t), EHCI_SITD_ALIGN);
- }
-}
-
-static usb2_error_t
-ehci_hc_reset(ehci_softc_t *sc)
-{
- uint32_t hcr;
- uint32_t n;
-
- EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
-
- for (n = 0; n != 100; n++) {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
- hcr = EOREAD4(sc, EHCI_USBSTS);
- if (hcr & EHCI_STS_HCH) {
- hcr = 0;
- break;
- }
- }
-
- /*
- * Fall through and try reset anyway even though
- * Table 2-9 in the EHCI spec says this will result
- * in undefined behavior.
- */
-
- EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
- for (n = 0; n != 100; n++) {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
- hcr = EOREAD4(sc, EHCI_USBCMD);
- if (!(hcr & EHCI_CMD_HCRESET)) {
- if (sc->sc_flags & EHCI_SCFLG_SETMODE)
- EOWRITE4(sc, 0x68, 0x3);
- hcr = 0;
- break;
- }
- }
-
- if (hcr) {
- return (USB_ERR_IOERROR);
- }
- return (0);
-}
-
-usb2_error_t
-ehci_init(ehci_softc_t *sc)
-{
- struct usb2_page_search buf_res;
- uint32_t version;
- uint32_t sparams;
- uint32_t cparams;
- uint32_t hcr;
- uint16_t i;
- uint16_t x;
- uint16_t y;
- uint16_t bit;
- usb2_error_t err = 0;
-
- DPRINTF("start\n");
-
- usb2_callout_init_mtx(&sc->sc_tmo_pcd, &sc->sc_bus.bus_mtx, 0);
-
-#if USB_DEBUG
- if (ehcidebug > 2) {
- ehci_dump_regs(sc);
- }
-#endif
-
- sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
-
- version = EREAD2(sc, EHCI_HCIVERSION);
- device_printf(sc->sc_bus.bdev, "EHCI version %x.%x\n",
- version >> 8, version & 0xff);
-
- sparams = EREAD4(sc, EHCI_HCSPARAMS);
- DPRINTF("sparams=0x%x\n", sparams);
-
- sc->sc_noport = EHCI_HCS_N_PORTS(sparams);
- cparams = EREAD4(sc, EHCI_HCCPARAMS);
- DPRINTF("cparams=0x%x\n", cparams);
-
- if (EHCI_HCC_64BIT(cparams)) {
- DPRINTF("HCC uses 64-bit structures\n");
-
- /* MUST clear segment register if 64 bit capable */
- EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
- }
- sc->sc_bus.usbrev = USB_REV_2_0;
-
- /* Reset the controller */
- DPRINTF("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev));
-
- USB_BUS_LOCK(&sc->sc_bus);
- err = ehci_hc_reset(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
- if (err) {
- device_printf(sc->sc_bus.bdev, "reset timeout\n");
- return (err);
- }
- /*
- * use current frame-list-size selection 0: 1024*4 bytes 1: 512*4
- * bytes 2: 256*4 bytes 3: unknown
- */
- if (EHCI_CMD_FLS(EOREAD4(sc, EHCI_USBCMD)) == 3) {
- device_printf(sc->sc_bus.bdev, "invalid frame-list-size\n");
- return (USB_ERR_IOERROR);
- }
- /* set up the bus struct */
- sc->sc_bus.methods = &ehci_bus_methods;
-
- sc->sc_eintrs = EHCI_NORMAL_INTRS;
-
- for (i = 0; i < EHCI_VIRTUAL_FRAMELIST_COUNT; i++) {
- ehci_qh_t *qh;
-
- usb2_get_page(sc->sc_hw.intr_start_pc + i, 0, &buf_res);
-
- qh = buf_res.buffer;
-
- /* initialize page cache pointer */
-
- qh->page_cache = sc->sc_hw.intr_start_pc + i;
-
- /* store a pointer to queue head */
-
- sc->sc_intr_p_last[i] = qh;
-
- qh->qh_self =
- htoehci32(sc, buf_res.physaddr) |
- htoehci32(sc, EHCI_LINK_QH);
-
- qh->qh_endp =
- htoehci32(sc, EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH));
- qh->qh_endphub =
- htoehci32(sc, EHCI_QH_SET_MULT(1));
- qh->qh_curqtd = 0;
-
- qh->qh_qtd.qtd_next =
- htoehci32(sc, EHCI_LINK_TERMINATE);
- qh->qh_qtd.qtd_altnext =
- htoehci32(sc, EHCI_LINK_TERMINATE);
- qh->qh_qtd.qtd_status =
- htoehci32(sc, EHCI_QTD_HALTED);
- }
-
- /*
- * the QHs are arranged to give poll intervals that are
- * powers of 2 times 1ms
- */
- bit = EHCI_VIRTUAL_FRAMELIST_COUNT / 2;
- while (bit) {
- x = bit;
- while (x & bit) {
- ehci_qh_t *qh_x;
- ehci_qh_t *qh_y;
-
- y = (x ^ bit) | (bit / 2);
-
- qh_x = sc->sc_intr_p_last[x];
- qh_y = sc->sc_intr_p_last[y];
-
- /*
- * the next QH has half the poll interval
- */
- qh_x->qh_link = qh_y->qh_self;
-
- x++;
- }
- bit >>= 1;
- }
-
- if (1) {
- ehci_qh_t *qh;
-
- qh = sc->sc_intr_p_last[0];
-
- /* the last (1ms) QH terminates */
- qh->qh_link = htoehci32(sc, EHCI_LINK_TERMINATE);
- }
- for (i = 0; i < EHCI_VIRTUAL_FRAMELIST_COUNT; i++) {
- ehci_sitd_t *sitd;
- ehci_itd_t *itd;
-
- usb2_get_page(sc->sc_hw.isoc_fs_start_pc + i, 0, &buf_res);
-
- sitd = buf_res.buffer;
-
- /* initialize page cache pointer */
-
- sitd->page_cache = sc->sc_hw.isoc_fs_start_pc + i;
-
- /* store a pointer to the transfer descriptor */
-
- sc->sc_isoc_fs_p_last[i] = sitd;
-
- /* initialize full speed isochronous */
-
- sitd->sitd_self =
- htoehci32(sc, buf_res.physaddr) |
- htoehci32(sc, EHCI_LINK_SITD);
-
- sitd->sitd_back =
- htoehci32(sc, EHCI_LINK_TERMINATE);
-
- sitd->sitd_next =
- sc->sc_intr_p_last[i | (EHCI_VIRTUAL_FRAMELIST_COUNT / 2)]->qh_self;
-
-
- usb2_get_page(sc->sc_hw.isoc_hs_start_pc + i, 0, &buf_res);
-
- itd = buf_res.buffer;
-
- /* initialize page cache pointer */
-
- itd->page_cache = sc->sc_hw.isoc_hs_start_pc + i;
-
- /* store a pointer to the transfer descriptor */
-
- sc->sc_isoc_hs_p_last[i] = itd;
-
- /* initialize high speed isochronous */
-
- itd->itd_self =
- htoehci32(sc, buf_res.physaddr) |
- htoehci32(sc, EHCI_LINK_ITD);
-
- itd->itd_next =
- sitd->sitd_self;
- }
-
- usb2_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res);
-
- if (1) {
- uint32_t *pframes;
-
- pframes = buf_res.buffer;
-
- /*
- * execution order:
- * pframes -> high speed isochronous ->
- * full speed isochronous -> interrupt QH's
- */
- for (i = 0; i < EHCI_FRAMELIST_COUNT; i++) {
- pframes[i] = sc->sc_isoc_hs_p_last
- [i & (EHCI_VIRTUAL_FRAMELIST_COUNT - 1)]->itd_self;
- }
- }
- /* setup sync list pointer */
- EOWRITE4(sc, EHCI_PERIODICLISTBASE, buf_res.physaddr);
-
- usb2_get_page(&sc->sc_hw.async_start_pc, 0, &buf_res);
-
- if (1) {
-
- ehci_qh_t *qh;
-
- qh = buf_res.buffer;
-
- /* initialize page cache pointer */
-
- qh->page_cache = &sc->sc_hw.async_start_pc;
-
- /* store a pointer to the queue head */
-
- sc->sc_async_p_last = qh;
-
- /* init dummy QH that starts the async list */
-
- qh->qh_self =
- htoehci32(sc, buf_res.physaddr) |
- htoehci32(sc, EHCI_LINK_QH);
-
- /* fill the QH */
- qh->qh_endp =
- htoehci32(sc, EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) | EHCI_QH_HRECL);
- qh->qh_endphub = htoehci32(sc, EHCI_QH_SET_MULT(1));
- qh->qh_link = qh->qh_self;
- qh->qh_curqtd = 0;
-
- /* fill the overlay qTD */
- qh->qh_qtd.qtd_next = htoehci32(sc, EHCI_LINK_TERMINATE);
- qh->qh_qtd.qtd_altnext = htoehci32(sc, EHCI_LINK_TERMINATE);
- qh->qh_qtd.qtd_status = htoehci32(sc, EHCI_QTD_HALTED);
- }
- /* flush all cache into memory */
-
- usb2_bus_mem_flush_all(&sc->sc_bus, &ehci_iterate_hw_softc);
-
-#if USB_DEBUG
- if (ehcidebug) {
- ehci_dump_sqh(sc, sc->sc_async_p_last);
- }
-#endif
-
- /* setup async list pointer */
- EOWRITE4(sc, EHCI_ASYNCLISTADDR, buf_res.physaddr | EHCI_LINK_QH);
-
-
- /* enable interrupts */
- EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
-
- /* turn on controller */
- EOWRITE4(sc, EHCI_USBCMD,
- EHCI_CMD_ITC_1 | /* 1 microframes interrupt delay */
- (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) |
- EHCI_CMD_ASE |
- EHCI_CMD_PSE |
- EHCI_CMD_RS);
-
- /* Take over port ownership */
- EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF);
-
- for (i = 0; i < 100; i++) {
- usb2_pause_mtx(NULL, hz / 1000);
- hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
- if (!hcr) {
- break;
- }
- }
- if (hcr) {
- device_printf(sc->sc_bus.bdev, "run timeout\n");
- return (USB_ERR_IOERROR);
- }
-
- if (!err) {
- /* catch any lost interrupts */
- ehci_do_poll(&sc->sc_bus);
- }
- return (err);
-}
-
-/*
- * shut down the controller when the system is going down
- */
-void
-ehci_detach(ehci_softc_t *sc)
-{
- USB_BUS_LOCK(&sc->sc_bus);
-
- usb2_callout_stop(&sc->sc_tmo_pcd);
-
- EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
-
- if (ehci_hc_reset(sc)) {
- DPRINTF("reset failed!\n");
- }
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- /* XXX let stray task complete */
- usb2_pause_mtx(NULL, hz / 20);
-
- usb2_callout_drain(&sc->sc_tmo_pcd);
-}
-
-void
-ehci_suspend(ehci_softc_t *sc)
-{
- uint32_t cmd;
- uint32_t hcr;
- uint8_t i;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- for (i = 1; i <= sc->sc_noport; i++) {
- cmd = EOREAD4(sc, EHCI_PORTSC(i));
- if (((cmd & EHCI_PS_PO) == 0) &&
- ((cmd & EHCI_PS_PE) == EHCI_PS_PE)) {
- EOWRITE4(sc, EHCI_PORTSC(i),
- cmd | EHCI_PS_SUSP);
- }
- }
-
- sc->sc_cmd = EOREAD4(sc, EHCI_USBCMD);
-
- cmd = sc->sc_cmd & ~(EHCI_CMD_ASE | EHCI_CMD_PSE);
- EOWRITE4(sc, EHCI_USBCMD, cmd);
-
- for (i = 0; i < 100; i++) {
- hcr = EOREAD4(sc, EHCI_USBSTS) &
- (EHCI_STS_ASS | EHCI_STS_PSS);
-
- if (hcr == 0) {
- break;
- }
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
- }
-
- if (hcr != 0) {
- device_printf(sc->sc_bus.bdev, "reset timeout\n");
- }
- cmd &= ~EHCI_CMD_RS;
- EOWRITE4(sc, EHCI_USBCMD, cmd);
-
- for (i = 0; i < 100; i++) {
- hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
- if (hcr == EHCI_STS_HCH) {
- break;
- }
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
- }
-
- if (hcr != EHCI_STS_HCH) {
- device_printf(sc->sc_bus.bdev,
- "config timeout\n");
- }
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-void
-ehci_resume(ehci_softc_t *sc)
-{
- struct usb2_page_search buf_res;
- uint32_t cmd;
- uint32_t hcr;
- uint8_t i;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* restore things in case the bios doesn't */
- EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
-
- usb2_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res);
- EOWRITE4(sc, EHCI_PERIODICLISTBASE, buf_res.physaddr);
-
- usb2_get_page(&sc->sc_hw.async_start_pc, 0, &buf_res);
- EOWRITE4(sc, EHCI_ASYNCLISTADDR, buf_res.physaddr | EHCI_LINK_QH);
-
- EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
-
- hcr = 0;
- for (i = 1; i <= sc->sc_noport; i++) {
- cmd = EOREAD4(sc, EHCI_PORTSC(i));
- if (((cmd & EHCI_PS_PO) == 0) &&
- ((cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP)) {
- EOWRITE4(sc, EHCI_PORTSC(i),
- cmd | EHCI_PS_FPR);
- hcr = 1;
- }
- }
-
- if (hcr) {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_WAIT));
-
- for (i = 1; i <= sc->sc_noport; i++) {
- cmd = EOREAD4(sc, EHCI_PORTSC(i));
- if (((cmd & EHCI_PS_PO) == 0) &&
- ((cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP)) {
- EOWRITE4(sc, EHCI_PORTSC(i),
- cmd & ~EHCI_PS_FPR);
- }
- }
- }
- EOWRITE4(sc, EHCI_USBCMD, sc->sc_cmd);
-
- for (i = 0; i < 100; i++) {
- hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
- if (hcr != EHCI_STS_HCH) {
- break;
- }
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
- }
- if (hcr == EHCI_STS_HCH) {
- device_printf(sc->sc_bus.bdev, "config timeout\n");
- }
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- usb2_pause_mtx(NULL,
- USB_MS_TO_TICKS(USB_RESUME_WAIT));
-
- /* catch any lost interrupts */
- ehci_do_poll(&sc->sc_bus);
-}
-
-void
-ehci_shutdown(ehci_softc_t *sc)
-{
- DPRINTF("stopping the HC\n");
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- if (ehci_hc_reset(sc)) {
- DPRINTF("reset failed!\n");
- }
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-#if USB_DEBUG
-static void
-ehci_dump_regs(ehci_softc_t *sc)
-{
- uint32_t i;
-
- i = EOREAD4(sc, EHCI_USBCMD);
- printf("cmd=0x%08x\n", i);
-
- if (i & EHCI_CMD_ITC_1)
- printf(" EHCI_CMD_ITC_1\n");
- if (i & EHCI_CMD_ITC_2)
- printf(" EHCI_CMD_ITC_2\n");
- if (i & EHCI_CMD_ITC_4)
- printf(" EHCI_CMD_ITC_4\n");
- if (i & EHCI_CMD_ITC_8)
- printf(" EHCI_CMD_ITC_8\n");
- if (i & EHCI_CMD_ITC_16)
- printf(" EHCI_CMD_ITC_16\n");
- if (i & EHCI_CMD_ITC_32)
- printf(" EHCI_CMD_ITC_32\n");
- if (i & EHCI_CMD_ITC_64)
- printf(" EHCI_CMD_ITC_64\n");
- if (i & EHCI_CMD_ASPME)
- printf(" EHCI_CMD_ASPME\n");
- if (i & EHCI_CMD_ASPMC)
- printf(" EHCI_CMD_ASPMC\n");
- if (i & EHCI_CMD_LHCR)
- printf(" EHCI_CMD_LHCR\n");
- if (i & EHCI_CMD_IAAD)
- printf(" EHCI_CMD_IAAD\n");
- if (i & EHCI_CMD_ASE)
- printf(" EHCI_CMD_ASE\n");
- if (i & EHCI_CMD_PSE)
- printf(" EHCI_CMD_PSE\n");
- if (i & EHCI_CMD_FLS_M)
- printf(" EHCI_CMD_FLS_M\n");
- if (i & EHCI_CMD_HCRESET)
- printf(" EHCI_CMD_HCRESET\n");
- if (i & EHCI_CMD_RS)
- printf(" EHCI_CMD_RS\n");
-
- i = EOREAD4(sc, EHCI_USBSTS);
-
- printf("sts=0x%08x\n", i);
-
- if (i & EHCI_STS_ASS)
- printf(" EHCI_STS_ASS\n");
- if (i & EHCI_STS_PSS)
- printf(" EHCI_STS_PSS\n");
- if (i & EHCI_STS_REC)
- printf(" EHCI_STS_REC\n");
- if (i & EHCI_STS_HCH)
- printf(" EHCI_STS_HCH\n");
- if (i & EHCI_STS_IAA)
- printf(" EHCI_STS_IAA\n");
- if (i & EHCI_STS_HSE)
- printf(" EHCI_STS_HSE\n");
- if (i & EHCI_STS_FLR)
- printf(" EHCI_STS_FLR\n");
- if (i & EHCI_STS_PCD)
- printf(" EHCI_STS_PCD\n");
- if (i & EHCI_STS_ERRINT)
- printf(" EHCI_STS_ERRINT\n");
- if (i & EHCI_STS_INT)
- printf(" EHCI_STS_INT\n");
-
- printf("ien=0x%08x\n",
- EOREAD4(sc, EHCI_USBINTR));
- printf("frindex=0x%08x ctrdsegm=0x%08x periodic=0x%08x async=0x%08x\n",
- EOREAD4(sc, EHCI_FRINDEX),
- EOREAD4(sc, EHCI_CTRLDSSEGMENT),
- EOREAD4(sc, EHCI_PERIODICLISTBASE),
- EOREAD4(sc, EHCI_ASYNCLISTADDR));
- for (i = 1; i <= sc->sc_noport; i++) {
- printf("port %d status=0x%08x\n", i,
- EOREAD4(sc, EHCI_PORTSC(i)));
- }
-}
-
-static void
-ehci_dump_link(ehci_softc_t *sc, uint32_t link, int type)
-{
- link = ehci32toh(sc, link);
- printf("0x%08x", link);
- if (link & EHCI_LINK_TERMINATE)
- printf("<T>");
- else {
- printf("<");
- if (type) {
- switch (EHCI_LINK_TYPE(link)) {
- case EHCI_LINK_ITD:
- printf("ITD");
- break;
- case EHCI_LINK_QH:
- printf("QH");
- break;
- case EHCI_LINK_SITD:
- printf("SITD");
- break;
- case EHCI_LINK_FSTN:
- printf("FSTN");
- break;
- }
- }
- printf(">");
- }
-}
-
-static void
-ehci_dump_qtd(ehci_softc_t *sc, ehci_qtd_t *qtd)
-{
- uint32_t s;
-
- printf(" next=");
- ehci_dump_link(sc, qtd->qtd_next, 0);
- printf(" altnext=");
- ehci_dump_link(sc, qtd->qtd_altnext, 0);
- printf("\n");
- s = ehci32toh(sc, qtd->qtd_status);
- printf(" status=0x%08x: toggle=%d bytes=0x%x ioc=%d c_page=0x%x\n",
- s, EHCI_QTD_GET_TOGGLE(s), EHCI_QTD_GET_BYTES(s),
- EHCI_QTD_GET_IOC(s), EHCI_QTD_GET_C_PAGE(s));
- printf(" cerr=%d pid=%d stat=%s%s%s%s%s%s%s%s\n",
- EHCI_QTD_GET_CERR(s), EHCI_QTD_GET_PID(s),
- (s & EHCI_QTD_ACTIVE) ? "ACTIVE" : "NOT_ACTIVE",
- (s & EHCI_QTD_HALTED) ? "-HALTED" : "",
- (s & EHCI_QTD_BUFERR) ? "-BUFERR" : "",
- (s & EHCI_QTD_BABBLE) ? "-BABBLE" : "",
- (s & EHCI_QTD_XACTERR) ? "-XACTERR" : "",
- (s & EHCI_QTD_MISSEDMICRO) ? "-MISSED" : "",
- (s & EHCI_QTD_SPLITXSTATE) ? "-SPLIT" : "",
- (s & EHCI_QTD_PINGSTATE) ? "-PING" : "");
-
- for (s = 0; s < 5; s++) {
- printf(" buffer[%d]=0x%08x\n", s,
- ehci32toh(sc, qtd->qtd_buffer[s]));
- }
- for (s = 0; s < 5; s++) {
- printf(" buffer_hi[%d]=0x%08x\n", s,
- ehci32toh(sc, qtd->qtd_buffer_hi[s]));
- }
-}
-
-static uint8_t
-ehci_dump_sqtd(ehci_softc_t *sc, ehci_qtd_t *sqtd)
-{
- uint8_t temp;
-
- usb2_pc_cpu_invalidate(sqtd->page_cache);
- printf("QTD(%p) at 0x%08x:\n", sqtd, ehci32toh(sc, sqtd->qtd_self));
- ehci_dump_qtd(sc, sqtd);
- temp = (sqtd->qtd_next & htoehci32(sc, EHCI_LINK_TERMINATE)) ? 1 : 0;
- return (temp);
-}
-
-static void
-ehci_dump_sqtds(ehci_softc_t *sc, ehci_qtd_t *sqtd)
-{
- uint16_t i;
- uint8_t stop;
-
- stop = 0;
- for (i = 0; sqtd && (i < 20) && !stop; sqtd = sqtd->obj_next, i++) {
- stop = ehci_dump_sqtd(sc, sqtd);
- }
- if (sqtd) {
- printf("dump aborted, too many TDs\n");
- }
-}
-
-static void
-ehci_dump_sqh(ehci_softc_t *sc, ehci_qh_t *qh)
-{
- uint32_t endp;
- uint32_t endphub;
-
- usb2_pc_cpu_invalidate(qh->page_cache);
- printf("QH(%p) at 0x%08x:\n", qh, ehci32toh(sc, qh->qh_self) & ~0x1F);
- printf(" link=");
- ehci_dump_link(sc, qh->qh_link, 1);
- printf("\n");
- endp = ehci32toh(sc, qh->qh_endp);
- printf(" endp=0x%08x\n", endp);
- printf(" addr=0x%02x inact=%d endpt=%d eps=%d dtc=%d hrecl=%d\n",
- EHCI_QH_GET_ADDR(endp), EHCI_QH_GET_INACT(endp),
- EHCI_QH_GET_ENDPT(endp), EHCI_QH_GET_EPS(endp),
- EHCI_QH_GET_DTC(endp), EHCI_QH_GET_HRECL(endp));
- printf(" mpl=0x%x ctl=%d nrl=%d\n",
- EHCI_QH_GET_MPL(endp), EHCI_QH_GET_CTL(endp),
- EHCI_QH_GET_NRL(endp));
- endphub = ehci32toh(sc, qh->qh_endphub);
- printf(" endphub=0x%08x\n", endphub);
- printf(" smask=0x%02x cmask=0x%02x huba=0x%02x port=%d mult=%d\n",
- EHCI_QH_GET_SMASK(endphub), EHCI_QH_GET_CMASK(endphub),
- EHCI_QH_GET_HUBA(endphub), EHCI_QH_GET_PORT(endphub),
- EHCI_QH_GET_MULT(endphub));
- printf(" curqtd=");
- ehci_dump_link(sc, qh->qh_curqtd, 0);
- printf("\n");
- printf("Overlay qTD:\n");
- ehci_dump_qtd(sc, (void *)&qh->qh_qtd);
-}
-
-static void
-ehci_dump_sitd(ehci_softc_t *sc, ehci_sitd_t *sitd)
-{
- usb2_pc_cpu_invalidate(sitd->page_cache);
- printf("SITD(%p) at 0x%08x\n", sitd, ehci32toh(sc, sitd->sitd_self) & ~0x1F);
- printf(" next=0x%08x\n", ehci32toh(sc, sitd->sitd_next));
- printf(" portaddr=0x%08x dir=%s addr=%d endpt=0x%x port=0x%x huba=0x%x\n",
- ehci32toh(sc, sitd->sitd_portaddr),
- (sitd->sitd_portaddr & htoehci32(sc, EHCI_SITD_SET_DIR_IN))
- ? "in" : "out",
- EHCI_SITD_GET_ADDR(ehci32toh(sc, sitd->sitd_portaddr)),
- EHCI_SITD_GET_ENDPT(ehci32toh(sc, sitd->sitd_portaddr)),
- EHCI_SITD_GET_PORT(ehci32toh(sc, sitd->sitd_portaddr)),
- EHCI_SITD_GET_HUBA(ehci32toh(sc, sitd->sitd_portaddr)));
- printf(" mask=0x%08x\n", ehci32toh(sc, sitd->sitd_mask));
- printf(" status=0x%08x <%s> len=0x%x\n", ehci32toh(sc, sitd->sitd_status),
- (sitd->sitd_status & htoehci32(sc, EHCI_SITD_ACTIVE)) ? "ACTIVE" : "",
- EHCI_SITD_GET_LEN(ehci32toh(sc, sitd->sitd_status)));
- printf(" back=0x%08x, bp=0x%08x,0x%08x,0x%08x,0x%08x\n",
- ehci32toh(sc, sitd->sitd_back),
- ehci32toh(sc, sitd->sitd_bp[0]),
- ehci32toh(sc, sitd->sitd_bp[1]),
- ehci32toh(sc, sitd->sitd_bp_hi[0]),
- ehci32toh(sc, sitd->sitd_bp_hi[1]));
-}
-
-static void
-ehci_dump_itd(ehci_softc_t *sc, ehci_itd_t *itd)
-{
- usb2_pc_cpu_invalidate(itd->page_cache);
- printf("ITD(%p) at 0x%08x\n", itd, ehci32toh(sc, itd->itd_self) & ~0x1F);
- printf(" next=0x%08x\n", ehci32toh(sc, itd->itd_next));
- printf(" status[0]=0x%08x; <%s>\n", ehci32toh(sc, itd->itd_status[0]),
- (itd->itd_status[0] & htoehci32(sc, EHCI_ITD_ACTIVE)) ? "ACTIVE" : "");
- printf(" status[1]=0x%08x; <%s>\n", ehci32toh(sc, itd->itd_status[1]),
- (itd->itd_status[1] & htoehci32(sc, EHCI_ITD_ACTIVE)) ? "ACTIVE" : "");
- printf(" status[2]=0x%08x; <%s>\n", ehci32toh(sc, itd->itd_status[2]),
- (itd->itd_status[2] & htoehci32(sc, EHCI_ITD_ACTIVE)) ? "ACTIVE" : "");
- printf(" status[3]=0x%08x; <%s>\n", ehci32toh(sc, itd->itd_status[3]),
- (itd->itd_status[3] & htoehci32(sc, EHCI_ITD_ACTIVE)) ? "ACTIVE" : "");
- printf(" status[4]=0x%08x; <%s>\n", ehci32toh(sc, itd->itd_status[4]),
- (itd->itd_status[4] & htoehci32(sc, EHCI_ITD_ACTIVE)) ? "ACTIVE" : "");
- printf(" status[5]=0x%08x; <%s>\n", ehci32toh(sc, itd->itd_status[5]),
- (itd->itd_status[5] & htoehci32(sc, EHCI_ITD_ACTIVE)) ? "ACTIVE" : "");
- printf(" status[6]=0x%08x; <%s>\n", ehci32toh(sc, itd->itd_status[6]),
- (itd->itd_status[6] & htoehci32(sc, EHCI_ITD_ACTIVE)) ? "ACTIVE" : "");
- printf(" status[7]=0x%08x; <%s>\n", ehci32toh(sc, itd->itd_status[7]),
- (itd->itd_status[7] & htoehci32(sc, EHCI_ITD_ACTIVE)) ? "ACTIVE" : "");
- printf(" bp[0]=0x%08x\n", ehci32toh(sc, itd->itd_bp[0]));
- printf(" addr=0x%02x; endpt=0x%01x\n",
- EHCI_ITD_GET_ADDR(ehci32toh(sc, itd->itd_bp[0])),
- EHCI_ITD_GET_ENDPT(ehci32toh(sc, itd->itd_bp[0])));
- printf(" bp[1]=0x%08x\n", ehci32toh(sc, itd->itd_bp[1]));
- printf(" dir=%s; mpl=0x%02x\n",
- (ehci32toh(sc, itd->itd_bp[1]) & EHCI_ITD_SET_DIR_IN) ? "in" : "out",
- EHCI_ITD_GET_MPL(ehci32toh(sc, itd->itd_bp[1])));
- printf(" bp[2..6]=0x%08x,0x%08x,0x%08x,0x%08x,0x%08x\n",
- ehci32toh(sc, itd->itd_bp[2]),
- ehci32toh(sc, itd->itd_bp[3]),
- ehci32toh(sc, itd->itd_bp[4]),
- ehci32toh(sc, itd->itd_bp[5]),
- ehci32toh(sc, itd->itd_bp[6]));
- printf(" bp_hi=0x%08x,0x%08x,0x%08x,0x%08x,\n"
- " 0x%08x,0x%08x,0x%08x\n",
- ehci32toh(sc, itd->itd_bp_hi[0]),
- ehci32toh(sc, itd->itd_bp_hi[1]),
- ehci32toh(sc, itd->itd_bp_hi[2]),
- ehci32toh(sc, itd->itd_bp_hi[3]),
- ehci32toh(sc, itd->itd_bp_hi[4]),
- ehci32toh(sc, itd->itd_bp_hi[5]),
- ehci32toh(sc, itd->itd_bp_hi[6]));
-}
-
-static void
-ehci_dump_isoc(ehci_softc_t *sc)
-{
- ehci_itd_t *itd;
- ehci_sitd_t *sitd;
- uint16_t max = 1000;
- uint16_t pos;
-
- pos = (EOREAD4(sc, EHCI_FRINDEX) / 8) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
-
- printf("%s: isochronous dump from frame 0x%03x:\n",
- __FUNCTION__, pos);
-
- itd = sc->sc_isoc_hs_p_last[pos];
- sitd = sc->sc_isoc_fs_p_last[pos];
-
- while (itd && max && max--) {
- ehci_dump_itd(sc, itd);
- itd = itd->prev;
- }
-
- while (sitd && max && max--) {
- ehci_dump_sitd(sc, sitd);
- sitd = sitd->prev;
- }
-}
-
-#endif
-
-static void
-ehci_transfer_intr_enqueue(struct usb2_xfer *xfer)
-{
- /* check for early completion */
- if (ehci_check_transfer(xfer)) {
- return;
- }
- /* put transfer on interrupt queue */
- usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
-
- /* start timeout, if any */
- if (xfer->timeout != 0) {
- usb2_transfer_timeout_ms(xfer, &ehci_timeout, xfer->timeout);
- }
-}
-
-#define EHCI_APPEND_FS_TD(std,last) (last) = _ehci_append_fs_td(std,last)
-static ehci_sitd_t *
-_ehci_append_fs_td(ehci_sitd_t *std, ehci_sitd_t *last)
-{
- DPRINTFN(11, "%p to %p\n", std, last);
-
- /* (sc->sc_bus.mtx) must be locked */
-
- std->next = last->next;
- std->sitd_next = last->sitd_next;
-
- std->prev = last;
-
- usb2_pc_cpu_flush(std->page_cache);
-
- /*
- * the last->next->prev is never followed: std->next->prev = std;
- */
- last->next = std;
- last->sitd_next = std->sitd_self;
-
- usb2_pc_cpu_flush(last->page_cache);
-
- return (std);
-}
-
-#define EHCI_APPEND_HS_TD(std,last) (last) = _ehci_append_hs_td(std,last)
-static ehci_itd_t *
-_ehci_append_hs_td(ehci_itd_t *std, ehci_itd_t *last)
-{
- DPRINTFN(11, "%p to %p\n", std, last);
-
- /* (sc->sc_bus.mtx) must be locked */
-
- std->next = last->next;
- std->itd_next = last->itd_next;
-
- std->prev = last;
-
- usb2_pc_cpu_flush(std->page_cache);
-
- /*
- * the last->next->prev is never followed: std->next->prev = std;
- */
- last->next = std;
- last->itd_next = std->itd_self;
-
- usb2_pc_cpu_flush(last->page_cache);
-
- return (std);
-}
-
-#define EHCI_APPEND_QH(sqh,last) (last) = _ehci_append_qh(sqh,last)
-static ehci_qh_t *
-_ehci_append_qh(ehci_qh_t *sqh, ehci_qh_t *last)
-{
- DPRINTFN(11, "%p to %p\n", sqh, last);
-
- if (sqh->prev != NULL) {
- /* should not happen */
- DPRINTFN(0, "QH already linked!\n");
- return (last);
- }
- /* (sc->sc_bus.mtx) must be locked */
-
- sqh->next = last->next;
- sqh->qh_link = last->qh_link;
-
- sqh->prev = last;
-
- usb2_pc_cpu_flush(sqh->page_cache);
-
- /*
- * the last->next->prev is never followed: sqh->next->prev = sqh;
- */
-
- last->next = sqh;
- last->qh_link = sqh->qh_self;
-
- usb2_pc_cpu_flush(last->page_cache);
-
- return (sqh);
-}
-
-#define EHCI_REMOVE_FS_TD(std,last) (last) = _ehci_remove_fs_td(std,last)
-static ehci_sitd_t *
-_ehci_remove_fs_td(ehci_sitd_t *std, ehci_sitd_t *last)
-{
- DPRINTFN(11, "%p from %p\n", std, last);
-
- /* (sc->sc_bus.mtx) must be locked */
-
- std->prev->next = std->next;
- std->prev->sitd_next = std->sitd_next;
-
- usb2_pc_cpu_flush(std->prev->page_cache);
-
- if (std->next) {
- std->next->prev = std->prev;
- usb2_pc_cpu_flush(std->next->page_cache);
- }
- return ((last == std) ? std->prev : last);
-}
-
-#define EHCI_REMOVE_HS_TD(std,last) (last) = _ehci_remove_hs_td(std,last)
-static ehci_itd_t *
-_ehci_remove_hs_td(ehci_itd_t *std, ehci_itd_t *last)
-{
- DPRINTFN(11, "%p from %p\n", std, last);
-
- /* (sc->sc_bus.mtx) must be locked */
-
- std->prev->next = std->next;
- std->prev->itd_next = std->itd_next;
-
- usb2_pc_cpu_flush(std->prev->page_cache);
-
- if (std->next) {
- std->next->prev = std->prev;
- usb2_pc_cpu_flush(std->next->page_cache);
- }
- return ((last == std) ? std->prev : last);
-}
-
-#define EHCI_REMOVE_QH(sqh,last) (last) = _ehci_remove_qh(sqh,last)
-static ehci_qh_t *
-_ehci_remove_qh(ehci_qh_t *sqh, ehci_qh_t *last)
-{
- DPRINTFN(11, "%p from %p\n", sqh, last);
-
- /* (sc->sc_bus.mtx) must be locked */
-
- /* only remove if not removed from a queue */
- if (sqh->prev) {
-
- sqh->prev->next = sqh->next;
- sqh->prev->qh_link = sqh->qh_link;
-
- usb2_pc_cpu_flush(sqh->prev->page_cache);
-
- if (sqh->next) {
- sqh->next->prev = sqh->prev;
- usb2_pc_cpu_flush(sqh->next->page_cache);
- }
- last = ((last == sqh) ? sqh->prev : last);
-
- sqh->prev = 0;
-
- usb2_pc_cpu_flush(sqh->page_cache);
- }
- return (last);
-}
-
-static usb2_error_t
-ehci_non_isoc_done_sub(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- ehci_qtd_t *td;
- ehci_qtd_t *td_alt_next;
- uint32_t status;
- uint16_t len;
-
- td = xfer->td_transfer_cache;
- td_alt_next = td->alt_next;
-
- if (xfer->aframes != xfer->nframes) {
- xfer->frlengths[xfer->aframes] = 0;
- }
- while (1) {
-
- usb2_pc_cpu_invalidate(td->page_cache);
- status = ehci32toh(sc, td->qtd_status);
-
- len = EHCI_QTD_GET_BYTES(status);
-
- /*
- * Verify the status length and
- * add the length to "frlengths[]":
- */
- if (len > td->len) {
- /* should not happen */
- DPRINTF("Invalid status length, "
- "0x%04x/0x%04x bytes\n", len, td->len);
- status |= EHCI_QTD_HALTED;
- } else if (xfer->aframes != xfer->nframes) {
- xfer->frlengths[xfer->aframes] += td->len - len;
- }
- /* Check for last transfer */
- if (((void *)td) == xfer->td_transfer_last) {
- if (len == 0) {
- /*
- * Halt is ok if descriptor is last,
- * and complete:
- */
- status &= ~EHCI_QTD_HALTED;
- }
- td = NULL;
- break;
- }
- /* Check for transfer error */
- if (status & EHCI_QTD_HALTED) {
- /* the transfer is finished */
- td = NULL;
- break;
- }
- /* Check for short transfer */
- if (len > 0) {
- if (xfer->flags_int.short_frames_ok) {
- /* follow alt next */
- td = td->alt_next;
- } else {
- /* the transfer is finished */
- td = NULL;
- }
- break;
- }
- td = td->obj_next;
-
- if (td->alt_next != td_alt_next) {
- /* this USB frame is complete */
- break;
- }
- }
-
- /* update transfer cache */
-
- xfer->td_transfer_cache = td;
-
- /* update data toggle */
-
- xfer->pipe->toggle_next =
- (status & EHCI_QTD_TOGGLE_MASK) ? 1 : 0;
-
-#if USB_DEBUG
- if (status & EHCI_QTD_STATERRS) {
- DPRINTFN(11, "error, addr=%d, endpt=0x%02x, frame=0x%02x"
- "status=%s%s%s%s%s%s%s%s\n",
- xfer->address, xfer->endpoint, xfer->aframes,
- (status & EHCI_QTD_ACTIVE) ? "[ACTIVE]" : "[NOT_ACTIVE]",
- (status & EHCI_QTD_HALTED) ? "[HALTED]" : "",
- (status & EHCI_QTD_BUFERR) ? "[BUFERR]" : "",
- (status & EHCI_QTD_BABBLE) ? "[BABBLE]" : "",
- (status & EHCI_QTD_XACTERR) ? "[XACTERR]" : "",
- (status & EHCI_QTD_MISSEDMICRO) ? "[MISSED]" : "",
- (status & EHCI_QTD_SPLITXSTATE) ? "[SPLIT]" : "",
- (status & EHCI_QTD_PINGSTATE) ? "[PING]" : "");
- }
-#endif
-
- return ((status & EHCI_QTD_HALTED) ?
- USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION);
-}
-
-static void
-ehci_non_isoc_done(struct usb2_xfer *xfer)
-{
- usb2_error_t err = 0;
-
- DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
-#if USB_DEBUG
- if (ehcidebug > 10) {
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- ehci_dump_sqtds(sc, xfer->td_transfer_first);
- }
-#endif
-
- /* reset scanner */
-
- xfer->td_transfer_cache = xfer->td_transfer_first;
-
- if (xfer->flags_int.control_xfr) {
-
- if (xfer->flags_int.control_hdr) {
-
- err = ehci_non_isoc_done_sub(xfer);
- }
- xfer->aframes = 1;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
- while (xfer->aframes != xfer->nframes) {
-
- err = ehci_non_isoc_done_sub(xfer);
- xfer->aframes++;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- err = ehci_non_isoc_done_sub(xfer);
- }
-done:
- ehci_device_done(xfer, err);
-}
-
-/*------------------------------------------------------------------------*
- * ehci_check_transfer
- *
- * Return values:
- * 0: USB transfer is not finished
- * Else: USB transfer is finished
- *------------------------------------------------------------------------*/
-static uint8_t
-ehci_check_transfer(struct usb2_xfer *xfer)
-{
- struct usb2_pipe_methods *methods = xfer->pipe->methods;
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- uint32_t status;
-
- DPRINTFN(13, "xfer=%p checking transfer\n", xfer);
-
- if (methods == &ehci_device_isoc_fs_methods) {
- ehci_sitd_t *td;
-
- /* isochronous full speed transfer */
-
- td = xfer->td_transfer_last;
- usb2_pc_cpu_invalidate(td->page_cache);
- status = ehci32toh(sc, td->sitd_status);
-
- /* also check if first is complete */
-
- td = xfer->td_transfer_first;
- usb2_pc_cpu_invalidate(td->page_cache);
- status |= ehci32toh(sc, td->sitd_status);
-
- if (!(status & EHCI_SITD_ACTIVE)) {
- ehci_device_done(xfer, USB_ERR_NORMAL_COMPLETION);
- goto transferred;
- }
- } else if (methods == &ehci_device_isoc_hs_methods) {
- ehci_itd_t *td;
-
- /* isochronous high speed transfer */
-
- td = xfer->td_transfer_last;
- usb2_pc_cpu_invalidate(td->page_cache);
- status =
- td->itd_status[0] | td->itd_status[1] |
- td->itd_status[2] | td->itd_status[3] |
- td->itd_status[4] | td->itd_status[5] |
- td->itd_status[6] | td->itd_status[7];
-
- /* also check first transfer */
- td = xfer->td_transfer_first;
- usb2_pc_cpu_invalidate(td->page_cache);
- status |=
- td->itd_status[0] | td->itd_status[1] |
- td->itd_status[2] | td->itd_status[3] |
- td->itd_status[4] | td->itd_status[5] |
- td->itd_status[6] | td->itd_status[7];
-
- /* if no transactions are active we continue */
- if (!(status & htoehci32(sc, EHCI_ITD_ACTIVE))) {
- ehci_device_done(xfer, USB_ERR_NORMAL_COMPLETION);
- goto transferred;
- }
- } else {
- ehci_qtd_t *td;
-
- /* non-isochronous transfer */
-
- /*
- * check whether there is an error somewhere in the middle,
- * or whether there was a short packet (SPD and not ACTIVE)
- */
- td = xfer->td_transfer_cache;
-
- while (1) {
- usb2_pc_cpu_invalidate(td->page_cache);
- status = ehci32toh(sc, td->qtd_status);
-
- /*
- * if there is an active TD the transfer isn't done
- */
- if (status & EHCI_QTD_ACTIVE) {
- /* update cache */
- xfer->td_transfer_cache = td;
- goto done;
- }
- /*
- * last transfer descriptor makes the transfer done
- */
- if (((void *)td) == xfer->td_transfer_last) {
- break;
- }
- /*
- * any kind of error makes the transfer done
- */
- if (status & EHCI_QTD_HALTED) {
- break;
- }
- /*
- * if there is no alternate next transfer, a short
- * packet also makes the transfer done
- */
- if (EHCI_QTD_GET_BYTES(status)) {
- if (xfer->flags_int.short_frames_ok) {
- /* follow alt next */
- if (td->alt_next) {
- td = td->alt_next;
- continue;
- }
- }
- /* transfer is done */
- break;
- }
- td = td->obj_next;
- }
- ehci_non_isoc_done(xfer);
- goto transferred;
- }
-
-done:
- DPRINTFN(13, "xfer=%p is still active\n", xfer);
- return (0);
-
-transferred:
- return (1);
-}
-
-static void
-ehci_pcd_enable(ehci_softc_t *sc)
-{
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- sc->sc_eintrs |= EHCI_STS_PCD;
- EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
-
- /* acknowledge any PCD interrupt */
- EOWRITE4(sc, EHCI_USBSTS, EHCI_STS_PCD);
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &ehci_root_intr_done);
-}
-
-static void
-ehci_interrupt_poll(ehci_softc_t *sc)
-{
- struct usb2_xfer *xfer;
-
-repeat:
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- /*
- * check if transfer is transferred
- */
- if (ehci_check_transfer(xfer)) {
- /* queue has been modified */
- goto repeat;
- }
- }
-}
-
-/*------------------------------------------------------------------------*
- * ehci_interrupt - EHCI interrupt handler
- *
- * NOTE: Do not access "sc->sc_bus.bdev" inside the interrupt handler,
- * hence the interrupt handler will be setup before "sc->sc_bus.bdev"
- * is present !
- *------------------------------------------------------------------------*/
-void
-ehci_interrupt(ehci_softc_t *sc)
-{
- uint32_t status;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- DPRINTFN(16, "real interrupt\n");
-
-#if USB_DEBUG
- if (ehcidebug > 15) {
- ehci_dump_regs(sc);
- }
-#endif
-
- status = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS));
- if (status == 0) {
- /* the interrupt was not for us */
- goto done;
- }
- if (!(status & sc->sc_eintrs)) {
- goto done;
- }
- EOWRITE4(sc, EHCI_USBSTS, status); /* acknowledge */
-
- status &= sc->sc_eintrs;
-
- if (status & EHCI_STS_HSE) {
- printf("%s: unrecoverable error, "
- "controller halted\n", __FUNCTION__);
-#if USB_DEBUG
- ehci_dump_regs(sc);
- ehci_dump_isoc(sc);
-#endif
- }
- if (status & EHCI_STS_PCD) {
- /*
- * Disable PCD interrupt for now, because it will be
- * on until the port has been reset.
- */
- sc->sc_eintrs &= ~EHCI_STS_PCD;
- EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &ehci_root_intr_done);
-
- /* do not allow RHSC interrupts > 1 per second */
- usb2_callout_reset(&sc->sc_tmo_pcd, hz,
- (void *)&ehci_pcd_enable, sc);
- }
- status &= ~(EHCI_STS_INT | EHCI_STS_ERRINT | EHCI_STS_PCD | EHCI_STS_IAA);
-
- if (status != 0) {
- /* block unprocessed interrupts */
- sc->sc_eintrs &= ~status;
- EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
- printf("%s: blocking interrupts 0x%x\n", __FUNCTION__, status);
- }
- /* poll all the USB transfers */
- ehci_interrupt_poll(sc);
-
-done:
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-/*
- * called when a request does not complete
- */
-static void
-ehci_timeout(void *arg)
-{
- struct usb2_xfer *xfer = arg;
-
- DPRINTF("xfer=%p\n", xfer);
-
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- /* transfer is transferred */
- ehci_device_done(xfer, USB_ERR_TIMEOUT);
-}
-
-static void
-ehci_do_poll(struct usb2_bus *bus)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(bus);
-
- USB_BUS_LOCK(&sc->sc_bus);
- ehci_interrupt_poll(sc);
- ehci_root_ctrl_poll(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-static void
-ehci_setup_standard_chain_sub(struct ehci_std_temp *temp)
-{
- struct usb2_page_search buf_res;
- ehci_qtd_t *td;
- ehci_qtd_t *td_next;
- ehci_qtd_t *td_alt_next;
- uint32_t qtd_altnext;
- uint32_t buf_offset;
- uint32_t average;
- uint32_t len_old;
- uint8_t shortpkt_old;
- uint8_t precompute;
-
- qtd_altnext = htoehci32(temp->sc, EHCI_LINK_TERMINATE);
- td_alt_next = NULL;
- buf_offset = 0;
- shortpkt_old = temp->shortpkt;
- len_old = temp->len;
- precompute = 1;
-
-restart:
-
- td = temp->td;
- td_next = temp->td_next;
-
- while (1) {
-
- if (temp->len == 0) {
-
- if (temp->shortpkt) {
- break;
- }
- /* send a Zero Length Packet, ZLP, last */
-
- temp->shortpkt = 1;
- average = 0;
-
- } else {
-
- average = temp->average;
-
- if (temp->len < average) {
- if (temp->len % temp->max_frame_size) {
- temp->shortpkt = 1;
- }
- average = temp->len;
- }
- }
-
- if (td_next == NULL) {
- panic("%s: out of EHCI transfer descriptors!", __FUNCTION__);
- }
- /* get next TD */
-
- td = td_next;
- td_next = td->obj_next;
-
- /* check if we are pre-computing */
-
- if (precompute) {
-
- /* update remaining length */
-
- temp->len -= average;
-
- continue;
- }
- /* fill out current TD */
-
- td->qtd_status =
- temp->qtd_status |
- htoehci32(temp->sc, EHCI_QTD_SET_BYTES(average));
-
- if (average == 0) {
-
- if (temp->auto_data_toggle == 0) {
-
- /* update data toggle, ZLP case */
-
- temp->qtd_status ^=
- htoehci32(temp->sc, EHCI_QTD_TOGGLE_MASK);
- }
- td->len = 0;
-
- td->qtd_buffer[0] = 0;
- td->qtd_buffer_hi[0] = 0;
-
- td->qtd_buffer[1] = 0;
- td->qtd_buffer_hi[1] = 0;
-
- } else {
-
- uint8_t x;
-
- if (temp->auto_data_toggle == 0) {
-
- /* update data toggle */
-
- if (((average + temp->max_frame_size - 1) /
- temp->max_frame_size) & 1) {
- temp->qtd_status ^=
- htoehci32(temp->sc, EHCI_QTD_TOGGLE_MASK);
- }
- }
- td->len = average;
-
- /* update remaining length */
-
- temp->len -= average;
-
- /* fill out buffer pointers */
-
- usb2_get_page(temp->pc, buf_offset, &buf_res);
- td->qtd_buffer[0] =
- htoehci32(temp->sc, buf_res.physaddr);
- td->qtd_buffer_hi[0] = 0;
-
- x = 1;
-
- while (average > EHCI_PAGE_SIZE) {
- average -= EHCI_PAGE_SIZE;
- buf_offset += EHCI_PAGE_SIZE;
- usb2_get_page(temp->pc, buf_offset, &buf_res);
- td->qtd_buffer[x] =
- htoehci32(temp->sc,
- buf_res.physaddr & (~0xFFF));
- td->qtd_buffer_hi[x] = 0;
- x++;
- }
-
- /*
- * NOTE: The "average" variable is never zero after
- * exiting the loop above !
- *
- * NOTE: We have to subtract one from the offset to
- * ensure that we are computing the physical address
- * of a valid page !
- */
- buf_offset += average;
- usb2_get_page(temp->pc, buf_offset - 1, &buf_res);
- td->qtd_buffer[x] =
- htoehci32(temp->sc,
- buf_res.physaddr & (~0xFFF));
- td->qtd_buffer_hi[x] = 0;
- }
-
- if (td_next) {
- /* link the current TD with the next one */
- td->qtd_next = td_next->qtd_self;
- }
- td->qtd_altnext = qtd_altnext;
- td->alt_next = td_alt_next;
-
- usb2_pc_cpu_flush(td->page_cache);
- }
-
- if (precompute) {
- precompute = 0;
-
- /* setup alt next pointer, if any */
- if (temp->short_frames_ok) {
- if (temp->setup_alt_next) {
- td_alt_next = td_next;
- qtd_altnext = td_next->qtd_self;
- }
- } else {
- /* we use this field internally */
- td_alt_next = td_next;
- }
-
- /* restore */
- temp->shortpkt = shortpkt_old;
- temp->len = len_old;
- goto restart;
- }
- temp->td = td;
- temp->td_next = td_next;
-}
-
-static void
-ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
-{
- struct ehci_std_temp temp;
- struct usb2_pipe_methods *methods;
- ehci_qh_t *qh;
- ehci_qtd_t *td;
- uint32_t qh_endp;
- uint32_t qh_endphub;
- uint32_t x;
-
- DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
- xfer->address, UE_GET_ADDR(xfer->endpoint),
- xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
-
- temp.average = xfer->max_usb2_frame_size;
- temp.max_frame_size = xfer->max_frame_size;
- temp.sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- /* toggle the DMA set we are using */
- xfer->flags_int.curr_dma_set ^= 1;
-
- /* get next DMA set */
- td = xfer->td_start[xfer->flags_int.curr_dma_set];
-
- xfer->td_transfer_first = td;
- xfer->td_transfer_cache = td;
-
- temp.td = NULL;
- temp.td_next = td;
- temp.qtd_status = 0;
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.short_frames_ok = xfer->flags_int.short_frames_ok;
-
- if (xfer->flags_int.control_xfr) {
- if (xfer->pipe->toggle_next) {
- /* DATA1 is next */
- temp.qtd_status |=
- htoehci32(temp.sc, EHCI_QTD_SET_TOGGLE(1));
- }
- temp.auto_data_toggle = 0;
- } else {
- temp.auto_data_toggle = 1;
- }
-
- if (usb2_get_speed(xfer->xroot->udev) != USB_SPEED_HIGH) {
- /* max 3 retries */
- temp.qtd_status |=
- htoehci32(temp.sc, EHCI_QTD_SET_CERR(3));
- }
- /* check if we should prepend a setup message */
-
- if (xfer->flags_int.control_xfr) {
- if (xfer->flags_int.control_hdr) {
-
- temp.qtd_status &=
- htoehci32(temp.sc, EHCI_QTD_SET_CERR(3));
- temp.qtd_status |= htole32
- (EHCI_QTD_ACTIVE |
- EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) |
- EHCI_QTD_SET_TOGGLE(0));
-
- temp.len = xfer->frlengths[0];
- temp.pc = xfer->frbuffers + 0;
- temp.shortpkt = temp.len ? 1 : 0;
-
- ehci_setup_standard_chain_sub(&temp);
- }
- x = 1;
- } else {
- x = 0;
- }
-
- while (x != xfer->nframes) {
-
- /* DATA0 / DATA1 message */
-
- temp.len = xfer->frlengths[x];
- temp.pc = xfer->frbuffers + x;
-
- x++;
-
- if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
- }
- /* keep previous data toggle and error count */
-
- temp.qtd_status &=
- htoehci32(temp.sc, EHCI_QTD_SET_CERR(3) |
- EHCI_QTD_SET_TOGGLE(1));
-
- if (temp.len == 0) {
-
- /* make sure that we send an USB packet */
-
- temp.shortpkt = 0;
-
- } else {
-
- /* regular data transfer */
-
- temp.shortpkt = (xfer->flags.force_short_xfer) ? 0 : 1;
- }
-
- /* set endpoint direction */
-
- temp.qtd_status |=
- (UE_GET_DIR(xfer->endpoint) == UE_DIR_IN) ?
- htoehci32(temp.sc, EHCI_QTD_ACTIVE |
- EHCI_QTD_SET_PID(EHCI_QTD_PID_IN)) :
- htoehci32(temp.sc, EHCI_QTD_ACTIVE |
- EHCI_QTD_SET_PID(EHCI_QTD_PID_OUT));
-
- ehci_setup_standard_chain_sub(&temp);
- }
-
- /* check if we should append a status stage */
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- /*
- * Send a DATA1 message and invert the current endpoint
- * direction.
- */
-
- temp.qtd_status &= htoehci32(temp.sc, EHCI_QTD_SET_CERR(3) |
- EHCI_QTD_SET_TOGGLE(1));
- temp.qtd_status |=
- (UE_GET_DIR(xfer->endpoint) == UE_DIR_OUT) ?
- htoehci32(temp.sc, EHCI_QTD_ACTIVE |
- EHCI_QTD_SET_PID(EHCI_QTD_PID_IN) |
- EHCI_QTD_SET_TOGGLE(1)) :
- htoehci32(temp.sc, EHCI_QTD_ACTIVE |
- EHCI_QTD_SET_PID(EHCI_QTD_PID_OUT) |
- EHCI_QTD_SET_TOGGLE(1));
-
- temp.len = 0;
- temp.pc = NULL;
- temp.shortpkt = 0;
-
- ehci_setup_standard_chain_sub(&temp);
- }
- td = temp.td;
-
- /* the last TD terminates the transfer: */
- td->qtd_next = htoehci32(temp.sc, EHCI_LINK_TERMINATE);
- td->qtd_altnext = htoehci32(temp.sc, EHCI_LINK_TERMINATE);
- td->qtd_status |= htoehci32(temp.sc, EHCI_QTD_IOC);
-
- usb2_pc_cpu_flush(td->page_cache);
-
- /* must have at least one frame! */
-
- xfer->td_transfer_last = td;
-
-#if USB_DEBUG
- if (ehcidebug > 8) {
- DPRINTF("nexttog=%d; data before transfer:\n",
- xfer->pipe->toggle_next);
- ehci_dump_sqtds(temp.sc,
- xfer->td_transfer_first);
- }
-#endif
-
- methods = xfer->pipe->methods;
-
- qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- /* the "qh_link" field is filled when the QH is added */
-
- qh_endp =
- (EHCI_QH_SET_ADDR(xfer->address) |
- EHCI_QH_SET_ENDPT(UE_GET_ADDR(xfer->endpoint)) |
- EHCI_QH_SET_MPL(xfer->max_packet_size));
-
- if (usb2_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) {
- qh_endp |= (EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) |
- EHCI_QH_DTC);
- if (methods != &ehci_device_intr_methods)
- qh_endp |= EHCI_QH_SET_NRL(8);
- } else {
-
- if (usb2_get_speed(xfer->xroot->udev) == USB_SPEED_FULL) {
- qh_endp |= (EHCI_QH_SET_EPS(EHCI_QH_SPEED_FULL) |
- EHCI_QH_DTC);
- } else {
- qh_endp |= (EHCI_QH_SET_EPS(EHCI_QH_SPEED_LOW) |
- EHCI_QH_DTC);
- }
-
- if (methods == &ehci_device_ctrl_methods) {
- qh_endp |= EHCI_QH_CTL;
- }
- if (methods != &ehci_device_intr_methods) {
- /* Only try one time per microframe! */
- qh_endp |= EHCI_QH_SET_NRL(1);
- }
- }
-
- qh->qh_endp = htoehci32(temp.sc, qh_endp);
-
- qh_endphub =
- (EHCI_QH_SET_MULT(xfer->max_packet_count & 3) |
- EHCI_QH_SET_CMASK(xfer->usb2_cmask) |
- EHCI_QH_SET_SMASK(xfer->usb2_smask) |
- EHCI_QH_SET_HUBA(xfer->xroot->udev->hs_hub_addr) |
- EHCI_QH_SET_PORT(xfer->xroot->udev->hs_port_no));
-
- qh->qh_endphub = htoehci32(temp.sc, qh_endphub);
- qh->qh_curqtd = htoehci32(temp.sc, 0);
-
- /* fill the overlay qTD */
- qh->qh_qtd.qtd_status = htoehci32(temp.sc, 0);
-
- if (temp.auto_data_toggle) {
-
- /* let the hardware compute the data toggle */
-
- qh->qh_endp &= htoehci32(temp.sc, ~EHCI_QH_DTC);
-
- if (xfer->pipe->toggle_next) {
- /* DATA1 is next */
- qh->qh_qtd.qtd_status |=
- htoehci32(temp.sc, EHCI_QTD_SET_TOGGLE(1));
- }
- }
- td = xfer->td_transfer_first;
-
- qh->qh_qtd.qtd_next = td->qtd_self;
- qh->qh_qtd.qtd_altnext =
- htoehci32(temp.sc, EHCI_LINK_TERMINATE);
-
- usb2_pc_cpu_flush(qh->page_cache);
-
- if (xfer->xroot->udev->pwr_save.suspended == 0) {
- EHCI_APPEND_QH(qh, *qh_last);
- }
-}
-
-static void
-ehci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- uint16_t i;
- uint16_t m;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- ehci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
- /* clear any old interrupt data */
- bzero(sc->sc_hub_idata, sizeof(sc->sc_hub_idata));
-
- /* set bits */
- m = (sc->sc_noport + 1);
- if (m > (8 * sizeof(sc->sc_hub_idata))) {
- m = (8 * sizeof(sc->sc_hub_idata));
- }
- for (i = 1; i < m; i++) {
- /* pick out CHANGE bits from the status register */
- if (EOREAD4(sc, EHCI_PORTSC(i)) & EHCI_PS_CLEAR) {
- sc->sc_hub_idata[i / 8] |= 1 << (i % 8);
- DPRINTF("port %d changed\n", i);
- }
- }
-done:
- return;
-}
-
-static void
-ehci_isoc_fs_done(ehci_softc_t *sc, struct usb2_xfer *xfer)
-{
- uint32_t nframes = xfer->nframes;
- uint32_t status;
- uint32_t *plen = xfer->frlengths;
- uint16_t len = 0;
- ehci_sitd_t *td = xfer->td_transfer_first;
- ehci_sitd_t **pp_last = &sc->sc_isoc_fs_p_last[xfer->qh_pos];
-
- DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
- while (nframes--) {
- if (td == NULL) {
- panic("%s:%d: out of TD's\n",
- __FUNCTION__, __LINE__);
- }
- if (pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]) {
- pp_last = &sc->sc_isoc_fs_p_last[0];
- }
-#if USB_DEBUG
- if (ehcidebug > 15) {
- DPRINTF("isoc FS-TD\n");
- ehci_dump_sitd(sc, td);
- }
-#endif
- usb2_pc_cpu_invalidate(td->page_cache);
- status = ehci32toh(sc, td->sitd_status);
-
- len = EHCI_SITD_GET_LEN(status);
-
- if (*plen >= len) {
- len = *plen - len;
- } else {
- len = 0;
- }
-
- *plen = len;
-
- /* remove FS-TD from schedule */
- EHCI_REMOVE_FS_TD(td, *pp_last);
-
- pp_last++;
- plen++;
- td = td->obj_next;
- }
-
- xfer->aframes = xfer->nframes;
-}
-
-static void
-ehci_isoc_hs_done(ehci_softc_t *sc, struct usb2_xfer *xfer)
-{
- uint32_t nframes = xfer->nframes;
- uint32_t status;
- uint32_t *plen = xfer->frlengths;
- uint16_t len = 0;
- uint8_t td_no = 0;
- ehci_itd_t *td = xfer->td_transfer_first;
- ehci_itd_t **pp_last = &sc->sc_isoc_hs_p_last[xfer->qh_pos];
-
- DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
- while (nframes--) {
- if (td == NULL) {
- panic("%s:%d: out of TD's\n",
- __FUNCTION__, __LINE__);
- }
- if (pp_last >= &sc->sc_isoc_hs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]) {
- pp_last = &sc->sc_isoc_hs_p_last[0];
- }
-#if USB_DEBUG
- if (ehcidebug > 15) {
- DPRINTF("isoc HS-TD\n");
- ehci_dump_itd(sc, td);
- }
-#endif
-
- usb2_pc_cpu_invalidate(td->page_cache);
- status = ehci32toh(sc, td->itd_status[td_no]);
-
- len = EHCI_ITD_GET_LEN(status);
-
- if (*plen >= len) {
- /*
- * The length is valid. NOTE: The complete
- * length is written back into the status
- * field, and not the remainder like with
- * other transfer descriptor types.
- */
- } else {
- /* Invalid length - truncate */
- len = 0;
- }
-
- *plen = len;
-
- plen++;
- td_no++;
-
- if ((td_no == 8) || (nframes == 0)) {
- /* remove HS-TD from schedule */
- EHCI_REMOVE_HS_TD(td, *pp_last);
- pp_last++;
-
- td_no = 0;
- td = td->obj_next;
- }
- }
- xfer->aframes = xfer->nframes;
-}
-
-/* NOTE: "done" can be run two times in a row,
- * from close and from interrupt
- */
-static void
-ehci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
-{
- struct usb2_pipe_methods *methods = xfer->pipe->methods;
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
- xfer, xfer->pipe, error);
-
- if ((methods == &ehci_device_bulk_methods) ||
- (methods == &ehci_device_ctrl_methods)) {
-#if USB_DEBUG
- if (ehcidebug > 8) {
- DPRINTF("nexttog=%d; data after transfer:\n",
- xfer->pipe->toggle_next);
- ehci_dump_sqtds(sc,
- xfer->td_transfer_first);
- }
-#endif
-
- EHCI_REMOVE_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
- sc->sc_async_p_last);
- }
- if (methods == &ehci_device_intr_methods) {
- EHCI_REMOVE_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
- sc->sc_intr_p_last[xfer->qh_pos]);
- }
- /*
- * Only finish isochronous transfers once which will update
- * "xfer->frlengths".
- */
- if (xfer->td_transfer_first &&
- xfer->td_transfer_last) {
- if (methods == &ehci_device_isoc_fs_methods) {
- ehci_isoc_fs_done(sc, xfer);
- }
- if (methods == &ehci_device_isoc_hs_methods) {
- ehci_isoc_hs_done(sc, xfer);
- }
- xfer->td_transfer_first = NULL;
- xfer->td_transfer_last = NULL;
- }
- /* dequeue transfer and start next transfer */
- usb2_transfer_done(xfer, error);
-}
-
-/*------------------------------------------------------------------------*
- * ehci bulk support
- *------------------------------------------------------------------------*/
-static void
-ehci_device_bulk_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_device_bulk_close(struct usb2_xfer *xfer)
-{
- ehci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ehci_device_bulk_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_device_bulk_start(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- /* setup TD's and QH */
- ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
-
- /* put transfer on interrupt queue */
- ehci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods ehci_device_bulk_methods =
-{
- .open = ehci_device_bulk_open,
- .close = ehci_device_bulk_close,
- .enter = ehci_device_bulk_enter,
- .start = ehci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * ehci control support
- *------------------------------------------------------------------------*/
-static void
-ehci_device_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_device_ctrl_close(struct usb2_xfer *xfer)
-{
- ehci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ehci_device_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_device_ctrl_start(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- /* setup TD's and QH */
- ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
-
- /* put transfer on interrupt queue */
- ehci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods ehci_device_ctrl_methods =
-{
- .open = ehci_device_ctrl_open,
- .close = ehci_device_ctrl_close,
- .enter = ehci_device_ctrl_enter,
- .start = ehci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * ehci interrupt support
- *------------------------------------------------------------------------*/
-static void
-ehci_device_intr_open(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- uint16_t best;
- uint16_t bit;
- uint16_t x;
- uint8_t slot;
-
- /* Allocate a microframe slot first: */
-
- slot = usb2_intr_schedule_adjust
- (xfer->xroot->udev, xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX);
-
- if (usb2_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) {
- xfer->usb2_uframe = slot;
- xfer->usb2_smask = (1 << slot) & 0xFF;
- xfer->usb2_cmask = 0;
- } else {
- xfer->usb2_uframe = slot;
- xfer->usb2_smask = (1 << slot) & 0x3F;
- xfer->usb2_cmask = (-(4 << slot)) & 0xFE;
- }
-
- /*
- * Find the best QH position corresponding to the given interval:
- */
-
- best = 0;
- bit = EHCI_VIRTUAL_FRAMELIST_COUNT / 2;
- while (bit) {
- if (xfer->interval >= bit) {
- x = bit;
- best = bit;
- while (x & bit) {
- if (sc->sc_intr_stat[x] <
- sc->sc_intr_stat[best]) {
- best = x;
- }
- x++;
- }
- break;
- }
- bit >>= 1;
- }
-
- sc->sc_intr_stat[best]++;
- xfer->qh_pos = best;
-
- DPRINTFN(3, "best=%d interval=%d\n",
- best, xfer->interval);
-}
-
-static void
-ehci_device_intr_close(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- uint8_t slot;
-
- slot = usb2_intr_schedule_adjust
- (xfer->xroot->udev, -(xfer->max_frame_size), xfer->usb2_uframe);
-
- sc->sc_intr_stat[xfer->qh_pos]--;
-
- ehci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ehci_device_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_device_intr_start(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- /* setup TD's and QH */
- ehci_setup_standard_chain(xfer, &sc->sc_intr_p_last[xfer->qh_pos]);
-
- /* put transfer on interrupt queue */
- ehci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods ehci_device_intr_methods =
-{
- .open = ehci_device_intr_open,
- .close = ehci_device_intr_close,
- .enter = ehci_device_intr_enter,
- .start = ehci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * ehci full speed isochronous support
- *------------------------------------------------------------------------*/
-static void
-ehci_device_isoc_fs_open(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- ehci_sitd_t *td;
- uint32_t sitd_portaddr;
- uint8_t ds;
-
- sitd_portaddr =
- EHCI_SITD_SET_ADDR(xfer->address) |
- EHCI_SITD_SET_ENDPT(UE_GET_ADDR(xfer->endpoint)) |
- EHCI_SITD_SET_HUBA(xfer->xroot->udev->hs_hub_addr) |
- EHCI_SITD_SET_PORT(xfer->xroot->udev->hs_port_no);
-
- if (UE_GET_DIR(xfer->endpoint) == UE_DIR_IN) {
- sitd_portaddr |= EHCI_SITD_SET_DIR_IN;
- }
- sitd_portaddr = htoehci32(sc, sitd_portaddr);
-
- /* initialize all TD's */
-
- for (ds = 0; ds != 2; ds++) {
-
- for (td = xfer->td_start[ds]; td; td = td->obj_next) {
-
- td->sitd_portaddr = sitd_portaddr;
-
- /*
- * TODO: make some kind of automatic
- * SMASK/CMASK selection based on micro-frame
- * usage
- *
- * micro-frame usage (8 microframes per 1ms)
- */
- td->sitd_back = htoehci32(sc, EHCI_LINK_TERMINATE);
-
- usb2_pc_cpu_flush(td->page_cache);
- }
- }
-}
-
-static void
-ehci_device_isoc_fs_close(struct usb2_xfer *xfer)
-{
- ehci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ehci_device_isoc_fs_enter(struct usb2_xfer *xfer)
-{
- struct usb2_page_search buf_res;
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- struct usb2_fs_isoc_schedule *fss_start;
- struct usb2_fs_isoc_schedule *fss_end;
- struct usb2_fs_isoc_schedule *fss;
- ehci_sitd_t *td;
- ehci_sitd_t *td_last = NULL;
- ehci_sitd_t **pp_last;
- uint32_t *plen;
- uint32_t buf_offset;
- uint32_t nframes;
- uint32_t temp;
- uint32_t sitd_mask;
- uint16_t tlen;
- uint8_t sa;
- uint8_t sb;
- uint8_t error;
-
-#if USB_DEBUG
- uint8_t once = 1;
-
-#endif
-
- DPRINTFN(6, "xfer=%p next=%d nframes=%d\n",
- xfer, xfer->pipe->isoc_next, xfer->nframes);
-
- /* get the current frame index */
-
- nframes = EOREAD4(sc, EHCI_FRINDEX) / 8;
-
- /*
- * check if the frame index is within the window where the frames
- * will be inserted
- */
- buf_offset = (nframes - xfer->pipe->isoc_next) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
-
- if ((xfer->pipe->is_synced == 0) ||
- (buf_offset < xfer->nframes)) {
- /*
- * If there is data underflow or the pipe queue is empty we
- * schedule the transfer a few frames ahead of the current
- * frame position. Else two isochronous transfers might
- * overlap.
- */
- xfer->pipe->isoc_next = (nframes + 3) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
- xfer->pipe->is_synced = 1;
- DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next);
- }
- /*
- * compute how many milliseconds the insertion is ahead of the
- * current frame position:
- */
- buf_offset = (xfer->pipe->isoc_next - nframes) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
-
- /*
- * pre-compute when the isochronous transfer will be finished:
- */
- xfer->isoc_time_complete =
- usb2_fs_isoc_schedule_isoc_time_expand
- (xfer->xroot->udev, &fss_start, &fss_end, nframes) + buf_offset +
- xfer->nframes;
-
- /* get the real number of frames */
-
- nframes = xfer->nframes;
-
- buf_offset = 0;
-
- plen = xfer->frlengths;
-
- /* toggle the DMA set we are using */
- xfer->flags_int.curr_dma_set ^= 1;
-
- /* get next DMA set */
- td = xfer->td_start[xfer->flags_int.curr_dma_set];
- xfer->td_transfer_first = td;
-
- pp_last = &sc->sc_isoc_fs_p_last[xfer->pipe->isoc_next];
-
- /* store starting position */
-
- xfer->qh_pos = xfer->pipe->isoc_next;
-
- fss = fss_start + (xfer->qh_pos % USB_ISOC_TIME_MAX);
-
- while (nframes--) {
- if (td == NULL) {
- panic("%s:%d: out of TD's\n",
- __FUNCTION__, __LINE__);
- }
- if (pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]) {
- pp_last = &sc->sc_isoc_fs_p_last[0];
- }
- if (fss >= fss_end) {
- fss = fss_start;
- }
- /* reuse sitd_portaddr and sitd_back from last transfer */
-
- if (*plen > xfer->max_frame_size) {
-#if USB_DEBUG
- if (once) {
- once = 0;
- printf("%s: frame length(%d) exceeds %d "
- "bytes (frame truncated)\n",
- __FUNCTION__, *plen,
- xfer->max_frame_size);
- }
-#endif
- *plen = xfer->max_frame_size;
- }
- /*
- * We currently don't care if the ISOCHRONOUS schedule is
- * full!
- */
- error = usb2_fs_isoc_schedule_alloc(fss, &sa, *plen);
- if (error) {
- /*
- * The FULL speed schedule is FULL! Set length
- * to zero.
- */
- *plen = 0;
- }
- if (*plen) {
- /*
- * only call "usb2_get_page()" when we have a
- * non-zero length
- */
- usb2_get_page(xfer->frbuffers, buf_offset, &buf_res);
- td->sitd_bp[0] = htoehci32(sc, buf_res.physaddr);
- buf_offset += *plen;
- /*
- * NOTE: We need to subtract one from the offset so
- * that we are on a valid page!
- */
- usb2_get_page(xfer->frbuffers, buf_offset - 1,
- &buf_res);
- temp = buf_res.physaddr & ~0xFFF;
- } else {
- td->sitd_bp[0] = 0;
- temp = 0;
- }
-
- if (UE_GET_DIR(xfer->endpoint) == UE_DIR_OUT) {
- tlen = *plen;
- if (tlen <= 188) {
- temp |= 1; /* T-count = 1, TP = ALL */
- tlen = 1;
- } else {
- tlen += 187;
- tlen /= 188;
- temp |= tlen; /* T-count = [1..6] */
- temp |= 8; /* TP = Begin */
- }
-
- tlen += sa;
-
- if (tlen >= 8) {
- sb = 0;
- } else {
- sb = (1 << tlen);
- }
-
- sa = (1 << sa);
- sa = (sb - sa) & 0x3F;
- sb = 0;
- } else {
- sb = (-(4 << sa)) & 0xFE;
- sa = (1 << sa) & 0x3F;
- }
-
- sitd_mask = (EHCI_SITD_SET_SMASK(sa) |
- EHCI_SITD_SET_CMASK(sb));
-
- td->sitd_bp[1] = htoehci32(sc, temp);
-
- td->sitd_mask = htoehci32(sc, sitd_mask);
-
- if (nframes == 0) {
- td->sitd_status = htole32
- (EHCI_SITD_IOC |
- EHCI_SITD_ACTIVE |
- EHCI_SITD_SET_LEN(*plen));
- } else {
- td->sitd_status = htole32
- (EHCI_SITD_ACTIVE |
- EHCI_SITD_SET_LEN(*plen));
- }
- usb2_pc_cpu_flush(td->page_cache);
-
-#if USB_DEBUG
- if (ehcidebug > 15) {
- DPRINTF("FS-TD %d\n", nframes);
- ehci_dump_sitd(sc, td);
- }
-#endif
- /* insert TD into schedule */
- EHCI_APPEND_FS_TD(td, *pp_last);
- pp_last++;
-
- plen++;
- fss++;
- td_last = td;
- td = td->obj_next;
- }
-
- xfer->td_transfer_last = td_last;
-
- /* update isoc_next */
- xfer->pipe->isoc_next = (pp_last - &sc->sc_isoc_fs_p_last[0]) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
-}
-
-static void
-ehci_device_isoc_fs_start(struct usb2_xfer *xfer)
-{
- /* put transfer on interrupt queue */
- ehci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods ehci_device_isoc_fs_methods =
-{
- .open = ehci_device_isoc_fs_open,
- .close = ehci_device_isoc_fs_close,
- .enter = ehci_device_isoc_fs_enter,
- .start = ehci_device_isoc_fs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * ehci high speed isochronous support
- *------------------------------------------------------------------------*/
-static void
-ehci_device_isoc_hs_open(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- ehci_itd_t *td;
- uint32_t temp;
- uint8_t ds;
-
- /* initialize all TD's */
-
- for (ds = 0; ds != 2; ds++) {
-
- for (td = xfer->td_start[ds]; td; td = td->obj_next) {
-
- /* set TD inactive */
- td->itd_status[0] = 0;
- td->itd_status[1] = 0;
- td->itd_status[2] = 0;
- td->itd_status[3] = 0;
- td->itd_status[4] = 0;
- td->itd_status[5] = 0;
- td->itd_status[6] = 0;
- td->itd_status[7] = 0;
-
- /* set endpoint and address */
- td->itd_bp[0] = htole32
- (EHCI_ITD_SET_ADDR(xfer->address) |
- EHCI_ITD_SET_ENDPT(UE_GET_ADDR(xfer->endpoint)));
-
- temp =
- EHCI_ITD_SET_MPL(xfer->max_packet_size & 0x7FF);
-
- /* set direction */
- if (UE_GET_DIR(xfer->endpoint) == UE_DIR_IN) {
- temp |= EHCI_ITD_SET_DIR_IN;
- }
- /* set maximum packet size */
- td->itd_bp[1] = htoehci32(sc, temp);
-
- /* set transfer multiplier */
- td->itd_bp[2] = htoehci32(sc, xfer->max_packet_count & 3);
-
- usb2_pc_cpu_flush(td->page_cache);
- }
- }
-}
-
-static void
-ehci_device_isoc_hs_close(struct usb2_xfer *xfer)
-{
- ehci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ehci_device_isoc_hs_enter(struct usb2_xfer *xfer)
-{
- struct usb2_page_search buf_res;
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- ehci_itd_t *td;
- ehci_itd_t *td_last = NULL;
- ehci_itd_t **pp_last;
- bus_size_t page_addr;
- uint32_t *plen;
- uint32_t status;
- uint32_t buf_offset;
- uint32_t nframes;
- uint32_t itd_offset[8 + 1];
- uint8_t x;
- uint8_t td_no;
- uint8_t page_no;
-
-#if USB_DEBUG
- uint8_t once = 1;
-
-#endif
-
- DPRINTFN(6, "xfer=%p next=%d nframes=%d\n",
- xfer, xfer->pipe->isoc_next, xfer->nframes);
-
- /* get the current frame index */
-
- nframes = EOREAD4(sc, EHCI_FRINDEX) / 8;
-
- /*
- * check if the frame index is within the window where the frames
- * will be inserted
- */
- buf_offset = (nframes - xfer->pipe->isoc_next) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
-
- if ((xfer->pipe->is_synced == 0) ||
- (buf_offset < ((xfer->nframes + 7) / 8))) {
- /*
- * If there is data underflow or the pipe queue is empty we
- * schedule the transfer a few frames ahead of the current
- * frame position. Else two isochronous transfers might
- * overlap.
- */
- xfer->pipe->isoc_next = (nframes + 3) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
- xfer->pipe->is_synced = 1;
- DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next);
- }
- /*
- * compute how many milliseconds the insertion is ahead of the
- * current frame position:
- */
- buf_offset = (xfer->pipe->isoc_next - nframes) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
-
- /*
- * pre-compute when the isochronous transfer will be finished:
- */
- xfer->isoc_time_complete =
- usb2_isoc_time_expand(&sc->sc_bus, nframes) + buf_offset +
- ((xfer->nframes + 7) / 8);
-
- /* get the real number of frames */
-
- nframes = xfer->nframes;
-
- buf_offset = 0;
- td_no = 0;
-
- plen = xfer->frlengths;
-
- /* toggle the DMA set we are using */
- xfer->flags_int.curr_dma_set ^= 1;
-
- /* get next DMA set */
- td = xfer->td_start[xfer->flags_int.curr_dma_set];
- xfer->td_transfer_first = td;
-
- pp_last = &sc->sc_isoc_hs_p_last[xfer->pipe->isoc_next];
-
- /* store starting position */
-
- xfer->qh_pos = xfer->pipe->isoc_next;
-
- while (nframes--) {
- if (td == NULL) {
- panic("%s:%d: out of TD's\n",
- __FUNCTION__, __LINE__);
- }
- if (pp_last >= &sc->sc_isoc_hs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]) {
- pp_last = &sc->sc_isoc_hs_p_last[0];
- }
- /* range check */
- if (*plen > xfer->max_frame_size) {
-#if USB_DEBUG
- if (once) {
- once = 0;
- printf("%s: frame length(%d) exceeds %d bytes "
- "(frame truncated)\n",
- __FUNCTION__, *plen, xfer->max_frame_size);
- }
-#endif
- *plen = xfer->max_frame_size;
- }
- status = (EHCI_ITD_SET_LEN(*plen) |
- EHCI_ITD_ACTIVE |
- EHCI_ITD_SET_PG(0));
- td->itd_status[td_no] = htoehci32(sc, status);
- itd_offset[td_no] = buf_offset;
- buf_offset += *plen;
- plen++;
- td_no++;
-
- if ((td_no == 8) || (nframes == 0)) {
-
- /* the rest of the transfers are not active, if any */
- for (x = td_no; x != 8; x++) {
- td->itd_status[x] = 0; /* not active */
- }
-
- /* check if there is any data to be transferred */
- if (itd_offset[0] != buf_offset) {
- page_no = 0;
- itd_offset[td_no] = buf_offset;
-
- /* get first page offset */
- usb2_get_page(xfer->frbuffers, itd_offset[0], &buf_res);
- /* get page address */
- page_addr = buf_res.physaddr & ~0xFFF;
- /* update page address */
- td->itd_bp[0] &= htoehci32(sc, 0xFFF);
- td->itd_bp[0] |= htoehci32(sc, page_addr);
-
- for (x = 0; x != td_no; x++) {
- /* set page number and page offset */
- status = (EHCI_ITD_SET_PG(page_no) |
- (buf_res.physaddr & 0xFFF));
- td->itd_status[x] |= htoehci32(sc, status);
-
- /* get next page offset */
- if (itd_offset[x + 1] == buf_offset) {
- /*
- * We subtract one so that
- * we don't go off the last
- * page!
- */
- usb2_get_page(xfer->frbuffers, buf_offset - 1, &buf_res);
- } else {
- usb2_get_page(xfer->frbuffers, itd_offset[x + 1], &buf_res);
- }
-
- /* check if we need a new page */
- if ((buf_res.physaddr ^ page_addr) & ~0xFFF) {
- /* new page needed */
- page_addr = buf_res.physaddr & ~0xFFF;
- if (page_no == 6) {
- panic("%s: too many pages\n", __FUNCTION__);
- }
- page_no++;
- /* update page address */
- td->itd_bp[page_no] &= htoehci32(sc, 0xFFF);
- td->itd_bp[page_no] |= htoehci32(sc, page_addr);
- }
- }
- }
- /* set IOC bit if we are complete */
- if (nframes == 0) {
- td->itd_status[7] |= htoehci32(sc, EHCI_ITD_IOC);
- }
- usb2_pc_cpu_flush(td->page_cache);
-#if USB_DEBUG
- if (ehcidebug > 15) {
- DPRINTF("HS-TD %d\n", nframes);
- ehci_dump_itd(sc, td);
- }
-#endif
- /* insert TD into schedule */
- EHCI_APPEND_HS_TD(td, *pp_last);
- pp_last++;
-
- td_no = 0;
- td_last = td;
- td = td->obj_next;
- }
- }
-
- xfer->td_transfer_last = td_last;
-
- /* update isoc_next */
- xfer->pipe->isoc_next = (pp_last - &sc->sc_isoc_hs_p_last[0]) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
-}
-
-static void
-ehci_device_isoc_hs_start(struct usb2_xfer *xfer)
-{
- /* put transfer on interrupt queue */
- ehci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods ehci_device_isoc_hs_methods =
-{
- .open = ehci_device_isoc_hs_open,
- .close = ehci_device_isoc_hs_close,
- .enter = ehci_device_isoc_hs_enter,
- .start = ehci_device_isoc_hs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * ehci root control support
- *------------------------------------------------------------------------*
- * simulate a hardware hub by handling
- * all the necessary requests
- *------------------------------------------------------------------------*/
-
-static void
-ehci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- ehci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/* data structures and routines
- * to emulate the root hub:
- */
-
-static const
-struct usb2_device_descriptor ehci_devd =
-{
- sizeof(struct usb2_device_descriptor),
- UDESC_DEVICE, /* type */
- {0x00, 0x02}, /* USB version */
- UDCLASS_HUB, /* class */
- UDSUBCLASS_HUB, /* subclass */
- UDPROTO_HSHUBSTT, /* protocol */
- 64, /* max packet */
- {0}, {0}, {0x00, 0x01}, /* device id */
- 1, 2, 0, /* string indicies */
- 1 /* # of configurations */
-};
-
-static const
-struct usb2_device_qualifier ehci_odevd =
-{
- sizeof(struct usb2_device_qualifier),
- UDESC_DEVICE_QUALIFIER, /* type */
- {0x00, 0x02}, /* USB version */
- UDCLASS_HUB, /* class */
- UDSUBCLASS_HUB, /* subclass */
- UDPROTO_FSHUB, /* protocol */
- 0, /* max packet */
- 0, /* # of configurations */
- 0
-};
-
-static const struct ehci_config_desc ehci_confd = {
- .confd = {
- .bLength = sizeof(struct usb2_config_descriptor),
- .bDescriptorType = UDESC_CONFIG,
- .wTotalLength[0] = sizeof(ehci_confd),
- .bNumInterface = 1,
- .bConfigurationValue = 1,
- .iConfiguration = 0,
- .bmAttributes = UC_SELF_POWERED,
- .bMaxPower = 0 /* max power */
- },
-
- .ifcd = {
- .bLength = sizeof(struct usb2_interface_descriptor),
- .bDescriptorType = UDESC_INTERFACE,
- .bNumEndpoints = 1,
- .bInterfaceClass = UICLASS_HUB,
- .bInterfaceSubClass = UISUBCLASS_HUB,
- .bInterfaceProtocol = UIPROTO_HSHUBSTT,
- 0
- },
-
- .endpd = {
- .bLength = sizeof(struct usb2_endpoint_descriptor),
- .bDescriptorType = UDESC_ENDPOINT,
- .bEndpointAddress = UE_DIR_IN | EHCI_INTR_ENDPT,
- .bmAttributes = UE_INTERRUPT,
- .wMaxPacketSize[0] = 8, /* max packet (63 ports) */
- .bInterval = 255,
- },
-};
-
-static const
-struct usb2_hub_descriptor ehci_hubd =
-{
- 0, /* dynamic length */
- UDESC_HUB,
- 0,
- {0, 0},
- 0,
- 0,
- {0},
-};
-
-static void
-ehci_disown(ehci_softc_t *sc, uint16_t index, uint8_t lowspeed)
-{
- uint32_t port;
- uint32_t v;
-
- DPRINTF("index=%d lowspeed=%d\n", index, lowspeed);
-
- port = EHCI_PORTSC(index);
- v = EOREAD4(sc, port) & ~EHCI_PS_CLEAR;
- EOWRITE4(sc, port, v | EHCI_PS_PO);
-}
-
-static void
-ehci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- DPRINTF("\n");
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-ehci_root_ctrl_task(struct usb2_bus *bus)
-{
- ehci_root_ctrl_poll(EHCI_BUS2SC(bus));
-}
-
-static void
-ehci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- char *ptr;
- uint32_t port;
- uint32_t v;
- uint16_t i;
- uint16_t value;
- uint16_t index;
- uint8_t l;
- uint8_t use_polling;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- ehci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* buffer reset */
- std->ptr = sc->sc_hub_desc.temp;
- std->len = 0;
-
- value = UGETW(std->req.wValue);
- index = UGETW(std->req.wIndex);
-
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- DPRINTFN(3, "type=0x%02x request=0x%02x wLen=0x%04x "
- "wValue=0x%04x wIndex=0x%04x\n",
- std->req.bmRequestType, std->req.bRequest,
- UGETW(std->req.wLength), value, index);
-
-#define C(x,y) ((x) | ((y) << 8))
- switch (C(std->req.bRequest, std->req.bmRequestType)) {
- case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
- case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
- case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
- /*
- * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
- * for the integrated root hub.
- */
- break;
- case C(UR_GET_CONFIG, UT_READ_DEVICE):
- std->len = 1;
- sc->sc_hub_desc.temp[0] = sc->sc_conf;
- break;
- case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
- switch (value >> 8) {
- case UDESC_DEVICE:
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- std->len = sizeof(ehci_devd);
- sc->sc_hub_desc.devd = ehci_devd;
- break;
- /*
- * We can't really operate at another speed,
- * but the specification says we need this
- * descriptor:
- */
- case UDESC_DEVICE_QUALIFIER:
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- std->len = sizeof(ehci_odevd);
- sc->sc_hub_desc.odevd = ehci_odevd;
- break;
-
- case UDESC_CONFIG:
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- std->len = sizeof(ehci_confd);
- std->ptr = USB_ADD_BYTES(&ehci_confd, 0);
- break;
-
- case UDESC_STRING:
- switch (value & 0xff) {
- case 0: /* Language table */
- ptr = "\001";
- break;
-
- case 1: /* Vendor */
- ptr = sc->sc_vendor;
- break;
-
- case 2: /* Product */
- ptr = "EHCI root HUB";
- break;
-
- default:
- ptr = "";
- break;
- }
-
- std->len = usb2_make_str_desc
- (sc->sc_hub_desc.temp,
- sizeof(sc->sc_hub_desc.temp),
- ptr);
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- break;
- case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
- std->len = 1;
- sc->sc_hub_desc.temp[0] = 0;
- break;
- case C(UR_GET_STATUS, UT_READ_DEVICE):
- std->len = 2;
- USETW(sc->sc_hub_desc.stat.wStatus, UDS_SELF_POWERED);
- break;
- case C(UR_GET_STATUS, UT_READ_INTERFACE):
- case C(UR_GET_STATUS, UT_READ_ENDPOINT):
- std->len = 2;
- USETW(sc->sc_hub_desc.stat.wStatus, 0);
- break;
- case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
- if (value >= USB_MAX_DEVICES) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- sc->sc_addr = value;
- break;
- case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
- if ((value != 0) && (value != 1)) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- sc->sc_conf = value;
- break;
- case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
- break;
- case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
- case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
- case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
- std->err = USB_ERR_IOERROR;
- goto done;
- case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
- break;
- case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
- break;
- /* Hub requests */
- case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
- break;
- case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
- DPRINTFN(9, "UR_CLEAR_PORT_FEATURE\n");
-
- if ((index < 1) ||
- (index > sc->sc_noport)) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- port = EHCI_PORTSC(index);
- v = EOREAD4(sc, port) & ~EHCI_PS_CLEAR;
- switch (value) {
- case UHF_PORT_ENABLE:
- EOWRITE4(sc, port, v & ~EHCI_PS_PE);
- break;
- case UHF_PORT_SUSPEND:
- if ((v & EHCI_PS_SUSP) && (!(v & EHCI_PS_FPR))) {
-
- /*
- * waking up a High Speed device is rather
- * complicated if
- */
- EOWRITE4(sc, port, v | EHCI_PS_FPR);
- }
- /* wait 20ms for resume sequence to complete */
- if (use_polling) {
- /* polling */
- DELAY(20000);
- } else {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 50);
- }
-
- EOWRITE4(sc, port, v & ~(EHCI_PS_SUSP |
- EHCI_PS_FPR | (3 << 10) /* High Speed */ ));
-
- /* settle time */
- if (use_polling) {
- /* polling */
- DELAY(4000);
- } else {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 250);
- }
- break;
- case UHF_PORT_POWER:
- EOWRITE4(sc, port, v & ~EHCI_PS_PP);
- break;
- case UHF_PORT_TEST:
- DPRINTFN(3, "clear port test "
- "%d\n", index);
- break;
- case UHF_PORT_INDICATOR:
- DPRINTFN(3, "clear port ind "
- "%d\n", index);
- EOWRITE4(sc, port, v & ~EHCI_PS_PIC);
- break;
- case UHF_C_PORT_CONNECTION:
- EOWRITE4(sc, port, v | EHCI_PS_CSC);
- break;
- case UHF_C_PORT_ENABLE:
- EOWRITE4(sc, port, v | EHCI_PS_PEC);
- break;
- case UHF_C_PORT_SUSPEND:
- EOWRITE4(sc, port, v | EHCI_PS_SUSP);
- break;
- case UHF_C_PORT_OVER_CURRENT:
- EOWRITE4(sc, port, v | EHCI_PS_OCC);
- break;
- case UHF_C_PORT_RESET:
- sc->sc_isreset = 0;
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- break;
- case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- v = EOREAD4(sc, EHCI_HCSPARAMS);
-
- sc->sc_hub_desc.hubd = ehci_hubd;
- sc->sc_hub_desc.hubd.bNbrPorts = sc->sc_noport;
- USETW(sc->sc_hub_desc.hubd.wHubCharacteristics,
- (EHCI_HCS_PPC(v) ? UHD_PWR_INDIVIDUAL : UHD_PWR_NO_SWITCH) |
- (EHCI_HCS_P_INDICATOR(EREAD4(sc, EHCI_HCSPARAMS)) ?
- UHD_PORT_IND : 0));
- /* XXX can't find out? */
- sc->sc_hub_desc.hubd.bPwrOn2PwrGood = 200;
- for (l = 0; l < sc->sc_noport; l++) {
- /* XXX can't find out? */
- sc->sc_hub_desc.hubd.DeviceRemovable[l / 8] &= ~(1 << (l % 8));
- }
- sc->sc_hub_desc.hubd.bDescLength =
- 8 + ((sc->sc_noport + 7) / 8);
- std->len = sc->sc_hub_desc.hubd.bDescLength;
- break;
- case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
- std->len = 16;
- bzero(sc->sc_hub_desc.temp, 16);
- break;
- case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
- DPRINTFN(9, "get port status i=%d\n",
- index);
- if ((index < 1) ||
- (index > sc->sc_noport)) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- v = EOREAD4(sc, EHCI_PORTSC(index));
- DPRINTFN(9, "port status=0x%04x\n", v);
- if (sc->sc_flags & EHCI_SCFLG_FORCESPEED) {
- if ((v & 0xc000000) == 0x8000000)
- i = UPS_HIGH_SPEED;
- else if ((v & 0xc000000) == 0x4000000)
- i = UPS_LOW_SPEED;
- else
- i = 0;
- } else {
- i = UPS_HIGH_SPEED;
- }
- if (v & EHCI_PS_CS)
- i |= UPS_CURRENT_CONNECT_STATUS;
- if (v & EHCI_PS_PE)
- i |= UPS_PORT_ENABLED;
- if ((v & EHCI_PS_SUSP) && !(v & EHCI_PS_FPR))
- i |= UPS_SUSPEND;
- if (v & EHCI_PS_OCA)
- i |= UPS_OVERCURRENT_INDICATOR;
- if (v & EHCI_PS_PR)
- i |= UPS_RESET;
- if (v & EHCI_PS_PP)
- i |= UPS_PORT_POWER;
- USETW(sc->sc_hub_desc.ps.wPortStatus, i);
- i = 0;
- if (v & EHCI_PS_CSC)
- i |= UPS_C_CONNECT_STATUS;
- if (v & EHCI_PS_PEC)
- i |= UPS_C_PORT_ENABLED;
- if (v & EHCI_PS_OCC)
- i |= UPS_C_OVERCURRENT_INDICATOR;
- if (v & EHCI_PS_FPR)
- i |= UPS_C_SUSPEND;
- if (sc->sc_isreset)
- i |= UPS_C_PORT_RESET;
- USETW(sc->sc_hub_desc.ps.wPortChange, i);
- std->len = sizeof(sc->sc_hub_desc.ps);
- break;
- case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
- std->err = USB_ERR_IOERROR;
- goto done;
- case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
- break;
- case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
- if ((index < 1) ||
- (index > sc->sc_noport)) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- port = EHCI_PORTSC(index);
- v = EOREAD4(sc, port) & ~EHCI_PS_CLEAR;
- switch (value) {
- case UHF_PORT_ENABLE:
- EOWRITE4(sc, port, v | EHCI_PS_PE);
- break;
- case UHF_PORT_SUSPEND:
- EOWRITE4(sc, port, v | EHCI_PS_SUSP);
- break;
- case UHF_PORT_RESET:
- DPRINTFN(6, "reset port %d\n", index);
-#if USB_DEBUG
- if (ehcinohighspeed) {
- /*
- * Connect USB device to companion
- * controller.
- */
- ehci_disown(sc, index, 1);
- break;
- }
-#endif
- if (EHCI_PS_IS_LOWSPEED(v)) {
- /* Low speed device, give up ownership. */
- ehci_disown(sc, index, 1);
- break;
- }
- /* Start reset sequence. */
- v &= ~(EHCI_PS_PE | EHCI_PS_PR);
- EOWRITE4(sc, port, v | EHCI_PS_PR);
-
- if (use_polling) {
- /* polling */
- DELAY(USB_PORT_ROOT_RESET_DELAY * 1000);
- } else {
- /* Wait for reset to complete. */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_PORT_ROOT_RESET_DELAY));
- }
-
- /* Terminate reset sequence. */
- if (!(sc->sc_flags & EHCI_SCFLG_NORESTERM))
- EOWRITE4(sc, port, v);
-
- if (use_polling) {
- /* polling */
- DELAY(EHCI_PORT_RESET_COMPLETE * 1000);
- } else {
- /* Wait for HC to complete reset. */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(EHCI_PORT_RESET_COMPLETE));
- }
-
- v = EOREAD4(sc, port);
- DPRINTF("ehci after reset, status=0x%08x\n", v);
- if (v & EHCI_PS_PR) {
- device_printf(sc->sc_bus.bdev,
- "port reset timeout\n");
- std->err = USB_ERR_TIMEOUT;
- goto done;
- }
- if (!(v & EHCI_PS_PE)) {
- /*
- * Not a high speed device, give up
- * ownership.
- */
- ehci_disown(sc, index, 0);
- break;
- }
- sc->sc_isreset = 1;
- DPRINTF("ehci port %d reset, status = 0x%08x\n",
- index, v);
- break;
-
- case UHF_PORT_POWER:
- DPRINTFN(3, "set port power %d\n", index);
- EOWRITE4(sc, port, v | EHCI_PS_PP);
- break;
-
- case UHF_PORT_TEST:
- DPRINTFN(3, "set port test %d\n", index);
- break;
-
- case UHF_PORT_INDICATOR:
- DPRINTFN(3, "set port ind %d\n", index);
- EOWRITE4(sc, port, v | EHCI_PS_PIC);
- break;
-
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- break;
- case C(UR_CLEAR_TT_BUFFER, UT_WRITE_CLASS_OTHER):
- case C(UR_RESET_TT, UT_WRITE_CLASS_OTHER):
- case C(UR_GET_TT_STATE, UT_READ_CLASS_OTHER):
- case C(UR_STOP_TT, UT_WRITE_CLASS_OTHER):
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
-done:
- return;
-}
-
-static void
-ehci_root_ctrl_poll(ehci_softc_t *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &ehci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods ehci_root_ctrl_methods =
-{
- .open = ehci_root_ctrl_open,
- .close = ehci_root_ctrl_close,
- .enter = ehci_root_ctrl_enter,
- .start = ehci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * ehci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-ehci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_root_intr_close(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- ehci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ehci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_root_intr_start(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods ehci_root_intr_methods =
-{
- .open = ehci_root_intr_open,
- .close = ehci_root_intr_close,
- .enter = ehci_root_intr_enter,
- .start = ehci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
-ehci_xfer_setup(struct usb2_setup_params *parm)
-{
- struct usb2_page_search page_info;
- struct usb2_page_cache *pc;
- ehci_softc_t *sc;
- struct usb2_xfer *xfer;
- void *last_obj;
- uint32_t nqtd;
- uint32_t nqh;
- uint32_t nsitd;
- uint32_t nitd;
- uint32_t n;
-
- sc = EHCI_BUS2SC(parm->udev->bus);
- xfer = parm->curr_xfer;
-
- nqtd = 0;
- nqh = 0;
- nsitd = 0;
- nitd = 0;
-
- /*
- * compute maximum number of some structures
- */
- if (parm->methods == &ehci_device_ctrl_methods) {
-
- /*
- * The proof for the "nqtd" formula is illustrated like
- * this:
- *
- * +------------------------------------+
- * | |
- * | |remainder -> |
- * | +-----+---+ |
- * | | xxx | x | frm 0 |
- * | +-----+---++ |
- * | | xxx | xx | frm 1 |
- * | +-----+----+ |
- * | ... |
- * +------------------------------------+
- *
- * "xxx" means a completely full USB transfer descriptor
- *
- * "x" and "xx" means a short USB packet
- *
- * For the remainder of an USB transfer modulo
- * "max_data_length" we need two USB transfer descriptors.
- * One to transfer the remaining data and one to finalise
- * with a zero length packet in case the "force_short_xfer"
- * flag is set. We only need two USB transfer descriptors in
- * the case where the transfer length of the first one is a
- * factor of "max_frame_size". The rest of the needed USB
- * transfer descriptors is given by the buffer size divided
- * by the maximum data payload.
- */
- parm->hc_max_packet_size = 0x400;
- parm->hc_max_packet_count = 1;
- parm->hc_max_frame_size = EHCI_QTD_PAYLOAD_MAX;
- xfer->flags_int.bdma_enable = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nqh = 1;
- nqtd = ((2 * xfer->nframes) + 1 /* STATUS */
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
-
- } else if (parm->methods == &ehci_device_bulk_methods) {
-
- parm->hc_max_packet_size = 0x400;
- parm->hc_max_packet_count = 1;
- parm->hc_max_frame_size = EHCI_QTD_PAYLOAD_MAX;
- xfer->flags_int.bdma_enable = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nqh = 1;
- nqtd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
-
- } else if (parm->methods == &ehci_device_intr_methods) {
-
- if (parm->speed == USB_SPEED_HIGH) {
- parm->hc_max_packet_size = 0x400;
- parm->hc_max_packet_count = 3;
- } else if (parm->speed == USB_SPEED_FULL) {
- parm->hc_max_packet_size = USB_FS_BYTES_PER_HS_UFRAME;
- parm->hc_max_packet_count = 1;
- } else {
- parm->hc_max_packet_size = USB_FS_BYTES_PER_HS_UFRAME / 8;
- parm->hc_max_packet_count = 1;
- }
-
- parm->hc_max_frame_size = EHCI_QTD_PAYLOAD_MAX;
- xfer->flags_int.bdma_enable = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nqh = 1;
- nqtd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
-
- } else if (parm->methods == &ehci_device_isoc_fs_methods) {
-
- parm->hc_max_packet_size = 0x3FF;
- parm->hc_max_packet_count = 1;
- parm->hc_max_frame_size = 0x3FF;
- xfer->flags_int.bdma_enable = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nsitd = xfer->nframes;
-
- } else if (parm->methods == &ehci_device_isoc_hs_methods) {
-
- parm->hc_max_packet_size = 0x400;
- parm->hc_max_packet_count = 3;
- parm->hc_max_frame_size = 0xC00;
- xfer->flags_int.bdma_enable = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nitd = (xfer->nframes + 7) / 8;
-
- } else {
-
- parm->hc_max_packet_size = 0x400;
- parm->hc_max_packet_count = 1;
- parm->hc_max_frame_size = 0x400;
-
- usb2_transfer_setup_sub(parm);
- }
-
-alloc_dma_set:
-
- if (parm->err) {
- return;
- }
- /*
- * Allocate queue heads and transfer descriptors
- */
- last_obj = NULL;
-
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, sizeof(ehci_itd_t),
- EHCI_ITD_ALIGN, nitd)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- if (parm->buf) {
- for (n = 0; n != nitd; n++) {
- ehci_itd_t *td;
-
- usb2_get_page(pc + n, 0, &page_info);
-
- td = page_info.buffer;
-
- /* init TD */
- td->itd_self = htoehci32(sc, page_info.physaddr | EHCI_LINK_ITD);
- td->obj_next = last_obj;
- td->page_cache = pc + n;
-
- last_obj = td;
-
- usb2_pc_cpu_flush(pc + n);
- }
- }
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, sizeof(ehci_sitd_t),
- EHCI_SITD_ALIGN, nsitd)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- if (parm->buf) {
- for (n = 0; n != nsitd; n++) {
- ehci_sitd_t *td;
-
- usb2_get_page(pc + n, 0, &page_info);
-
- td = page_info.buffer;
-
- /* init TD */
- td->sitd_self = htoehci32(sc, page_info.physaddr | EHCI_LINK_SITD);
- td->obj_next = last_obj;
- td->page_cache = pc + n;
-
- last_obj = td;
-
- usb2_pc_cpu_flush(pc + n);
- }
- }
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, sizeof(ehci_qtd_t),
- EHCI_QTD_ALIGN, nqtd)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- if (parm->buf) {
- for (n = 0; n != nqtd; n++) {
- ehci_qtd_t *qtd;
-
- usb2_get_page(pc + n, 0, &page_info);
-
- qtd = page_info.buffer;
-
- /* init TD */
- qtd->qtd_self = htoehci32(sc, page_info.physaddr);
- qtd->obj_next = last_obj;
- qtd->page_cache = pc + n;
-
- last_obj = qtd;
-
- usb2_pc_cpu_flush(pc + n);
- }
- }
- xfer->td_start[xfer->flags_int.curr_dma_set] = last_obj;
-
- last_obj = NULL;
-
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, sizeof(ehci_qh_t),
- EHCI_QH_ALIGN, nqh)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- if (parm->buf) {
- for (n = 0; n != nqh; n++) {
- ehci_qh_t *qh;
-
- usb2_get_page(pc + n, 0, &page_info);
-
- qh = page_info.buffer;
-
- /* init QH */
- qh->qh_self = htoehci32(sc, page_info.physaddr | EHCI_LINK_QH);
- qh->obj_next = last_obj;
- qh->page_cache = pc + n;
-
- last_obj = qh;
-
- usb2_pc_cpu_flush(pc + n);
- }
- }
- xfer->qh_start[xfer->flags_int.curr_dma_set] = last_obj;
-
- if (!xfer->flags_int.curr_dma_set) {
- xfer->flags_int.curr_dma_set = 1;
- goto alloc_dma_set;
- }
-}
-
-static void
-ehci_xfer_unsetup(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
- struct usb2_pipe *pipe)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(udev->bus);
-
- DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
- pipe, udev->address,
- edesc->bEndpointAddress, udev->flags.usb2_mode,
- sc->sc_addr);
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- if (udev->device_index == sc->sc_addr) {
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &ehci_root_ctrl_methods;
- break;
- case UE_DIR_IN | EHCI_INTR_ENDPT:
- pipe->methods = &ehci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
- if ((udev->speed != USB_SPEED_HIGH) &&
- ((udev->hs_hub_addr == 0) ||
- (udev->hs_port_no == 0) ||
- (udev->bus->devices[udev->hs_hub_addr] == NULL) ||
- (udev->bus->devices[udev->hs_hub_addr]->hub == NULL))) {
- /* We need a transaction translator */
- goto done;
- }
- switch (edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- pipe->methods = &ehci_device_ctrl_methods;
- break;
- case UE_INTERRUPT:
- pipe->methods = &ehci_device_intr_methods;
- break;
- case UE_ISOCHRONOUS:
- if (udev->speed == USB_SPEED_HIGH) {
- pipe->methods = &ehci_device_isoc_hs_methods;
- } else if (udev->speed == USB_SPEED_FULL) {
- pipe->methods = &ehci_device_isoc_fs_methods;
- }
- break;
- case UE_BULK:
- if (udev->speed != USB_SPEED_LOW) {
- pipe->methods = &ehci_device_bulk_methods;
- }
- break;
- default:
- /* do nothing */
- break;
- }
- }
-done:
- return;
-}
-
-static void
-ehci_get_dma_delay(struct usb2_bus *bus, uint32_t *pus)
-{
- /*
- * Wait until the hardware has finished any possible use of
- * the transfer descriptor(s) and QH
- */
- *pus = (188); /* microseconds */
-}
-
-static void
-ehci_device_resume(struct usb2_device *udev)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(udev->bus);
- struct usb2_xfer *xfer;
- struct usb2_pipe_methods *methods;
-
- DPRINTF("\n");
-
- USB_BUS_LOCK(udev->bus);
-
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-
- if (xfer->xroot->udev == udev) {
-
- methods = xfer->pipe->methods;
-
- if ((methods == &ehci_device_bulk_methods) ||
- (methods == &ehci_device_ctrl_methods)) {
- EHCI_APPEND_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
- sc->sc_async_p_last);
- }
- if (methods == &ehci_device_intr_methods) {
- EHCI_APPEND_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
- sc->sc_intr_p_last[xfer->qh_pos]);
- }
- }
- }
-
- USB_BUS_UNLOCK(udev->bus);
-
- return;
-}
-
-static void
-ehci_device_suspend(struct usb2_device *udev)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(udev->bus);
- struct usb2_xfer *xfer;
- struct usb2_pipe_methods *methods;
-
- DPRINTF("\n");
-
- USB_BUS_LOCK(udev->bus);
-
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-
- if (xfer->xroot->udev == udev) {
-
- methods = xfer->pipe->methods;
-
- if ((methods == &ehci_device_bulk_methods) ||
- (methods == &ehci_device_ctrl_methods)) {
- EHCI_REMOVE_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
- sc->sc_async_p_last);
- }
- if (methods == &ehci_device_intr_methods) {
- EHCI_REMOVE_QH(xfer->qh_start[xfer->flags_int.curr_dma_set],
- sc->sc_intr_p_last[xfer->qh_pos]);
- }
- }
- }
-
- USB_BUS_UNLOCK(udev->bus);
-
- return;
-}
-
-static void
-ehci_set_hw_power(struct usb2_bus *bus)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(bus);
- uint32_t temp;
- uint32_t flags;
-
- DPRINTF("\n");
-
- USB_BUS_LOCK(bus);
-
- flags = bus->hw_power_state;
-
- temp = EOREAD4(sc, EHCI_USBCMD);
-
- temp &= ~(EHCI_CMD_ASE | EHCI_CMD_PSE);
-
- if (flags & (USB_HW_POWER_CONTROL |
- USB_HW_POWER_BULK)) {
- DPRINTF("Async is active\n");
- temp |= EHCI_CMD_ASE;
- }
- if (flags & (USB_HW_POWER_INTERRUPT |
- USB_HW_POWER_ISOC)) {
- DPRINTF("Periodic is active\n");
- temp |= EHCI_CMD_PSE;
- }
- EOWRITE4(sc, EHCI_USBCMD, temp);
-
- USB_BUS_UNLOCK(bus);
-
- return;
-}
-
-struct usb2_bus_methods ehci_bus_methods =
-{
- .pipe_init = ehci_pipe_init,
- .xfer_setup = ehci_xfer_setup,
- .xfer_unsetup = ehci_xfer_unsetup,
- .do_poll = ehci_do_poll,
- .get_dma_delay = ehci_get_dma_delay,
- .device_resume = ehci_device_resume,
- .device_suspend = ehci_device_suspend,
- .set_hw_power = ehci_set_hw_power,
- .roothub_exec = ehci_root_ctrl_task,
-};
diff --git a/sys/dev/usb2/controller/ehci2.h b/sys/dev/usb2/controller/ehci2.h
deleted file mode 100644
index 9d7baa1..0000000
--- a/sys/dev/usb2/controller/ehci2.h
+++ /dev/null
@@ -1,532 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (lennart@augustsson.net).
- *
- * 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.
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``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 FOUNDATION OR CONTRIBUTORS
- * 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.
- */
-
-#ifndef _EHCI_H_
-#define _EHCI_H_
-
-#define EHCI_MAX_DEVICES USB_MAX_DEVICES
-
-/* PCI config registers */
-#define PCI_CBMEM 0x10 /* configuration base MEM */
-#define PCI_INTERFACE_EHCI 0x20
-#define PCI_USBREV 0x60 /* RO USB protocol revision */
-#define PCI_USB_REV_MASK 0xff
-#define PCI_USB_REV_PRE_1_0 0x00
-#define PCI_USB_REV_1_0 0x10
-#define PCI_USB_REV_1_1 0x11
-#define PCI_USB_REV_2_0 0x20
-#define PCI_EHCI_FLADJ 0x61 /* RW Frame len adj, SOF=59488+6*fladj */
-#define PCI_EHCI_PORTWAKECAP 0x62 /* RW Port wake caps (opt) */
-
-/* EHCI Extended Capabilities */
-#define EHCI_EC_LEGSUP 0x01
-#define EHCI_EECP_NEXT(x) (((x) >> 8) & 0xff)
-#define EHCI_EECP_ID(x) ((x) & 0xff)
-
-/* Legacy support extended capability */
-#define EHCI_LEGSUP_BIOS_SEM 0x02
-#define EHCI_LEGSUP_OS_SEM 0x03
-#define EHCI_LEGSUP_USBLEGCTLSTS 0x04
-
-/* EHCI capability registers */
-#define EHCI_CAPLENGTH 0x00 /* RO Capability register length field */
-/* reserved 0x01 */
-#define EHCI_HCIVERSION 0x02 /* RO Interface version number */
-#define EHCI_HCSPARAMS 0x04 /* RO Structural parameters */
-#define EHCI_HCS_DEBUGPORT(x) (((x) >> 20) & 0xf)
-#define EHCI_HCS_P_INDICATOR(x) ((x) & 0x10000)
-#define EHCI_HCS_N_CC(x) (((x) >> 12) & 0xf) /* # of companion ctlrs */
-#define EHCI_HCS_N_PCC(x) (((x) >> 8) & 0xf) /* # of ports per comp. */
-#define EHCI_HCS_PPC(x) ((x) & 0x10) /* port power control */
-#define EHCI_HCS_N_PORTS(x) ((x) & 0xf) /* # of ports */
-#define EHCI_HCCPARAMS 0x08 /* RO Capability parameters */
-#define EHCI_HCC_EECP(x) (((x) >> 8) & 0xff) /* extended ports caps */
-#define EHCI_HCC_IST(x) (((x) >> 4) & 0xf) /* isoc sched threshold */
-#define EHCI_HCC_ASPC(x) ((x) & 0x4) /* async sched park cap */
-#define EHCI_HCC_PFLF(x) ((x) & 0x2) /* prog frame list flag */
-#define EHCI_HCC_64BIT(x) ((x) & 0x1) /* 64 bit address cap */
-#define EHCI_HCSP_PORTROUTE 0x0c /* RO Companion port route description */
-
-/* EHCI operational registers. Offset given by EHCI_CAPLENGTH register */
-#define EHCI_USBCMD 0x00 /* RO, RW, WO Command register */
-#define EHCI_CMD_ITC_M 0x00ff0000 /* RW interrupt threshold ctrl */
-#define EHCI_CMD_ITC_1 0x00010000
-#define EHCI_CMD_ITC_2 0x00020000
-#define EHCI_CMD_ITC_4 0x00040000
-#define EHCI_CMD_ITC_8 0x00080000
-#define EHCI_CMD_ITC_16 0x00100000
-#define EHCI_CMD_ITC_32 0x00200000
-#define EHCI_CMD_ITC_64 0x00400000
-#define EHCI_CMD_ASPME 0x00000800 /* RW/RO async park enable */
-#define EHCI_CMD_ASPMC 0x00000300 /* RW/RO async park count */
-#define EHCI_CMD_LHCR 0x00000080 /* RW light host ctrl reset */
-#define EHCI_CMD_IAAD 0x00000040 /* RW intr on async adv door
- * bell */
-#define EHCI_CMD_ASE 0x00000020 /* RW async sched enable */
-#define EHCI_CMD_PSE 0x00000010 /* RW periodic sched enable */
-#define EHCI_CMD_FLS_M 0x0000000c /* RW/RO frame list size */
-#define EHCI_CMD_FLS(x) (((x) >> 2) & 3) /* RW/RO frame list size */
-#define EHCI_CMD_HCRESET 0x00000002 /* RW reset */
-#define EHCI_CMD_RS 0x00000001 /* RW run/stop */
-#define EHCI_USBSTS 0x04 /* RO, RW, RWC Status register */
-#define EHCI_STS_ASS 0x00008000 /* RO async sched status */
-#define EHCI_STS_PSS 0x00004000 /* RO periodic sched status */
-#define EHCI_STS_REC 0x00002000 /* RO reclamation */
-#define EHCI_STS_HCH 0x00001000 /* RO host controller halted */
-#define EHCI_STS_IAA 0x00000020 /* RWC interrupt on async adv */
-#define EHCI_STS_HSE 0x00000010 /* RWC host system error */
-#define EHCI_STS_FLR 0x00000008 /* RWC frame list rollover */
-#define EHCI_STS_PCD 0x00000004 /* RWC port change detect */
-#define EHCI_STS_ERRINT 0x00000002 /* RWC error interrupt */
-#define EHCI_STS_INT 0x00000001 /* RWC interrupt */
-#define EHCI_STS_INTRS(x) ((x) & 0x3f)
-
-/*
- * NOTE: the doorbell interrupt is enabled, but the doorbell is never
- * used! SiS chipsets require this.
- */
-#define EHCI_NORMAL_INTRS (EHCI_STS_IAA | EHCI_STS_HSE | \
- EHCI_STS_PCD | EHCI_STS_ERRINT | EHCI_STS_INT)
-
-#define EHCI_USBINTR 0x08 /* RW Interrupt register */
-#define EHCI_INTR_IAAE 0x00000020 /* interrupt on async advance
- * ena */
-#define EHCI_INTR_HSEE 0x00000010 /* host system error ena */
-#define EHCI_INTR_FLRE 0x00000008 /* frame list rollover ena */
-#define EHCI_INTR_PCIE 0x00000004 /* port change ena */
-#define EHCI_INTR_UEIE 0x00000002 /* USB error intr ena */
-#define EHCI_INTR_UIE 0x00000001 /* USB intr ena */
-
-#define EHCI_FRINDEX 0x0c /* RW Frame Index register */
-
-#define EHCI_CTRLDSSEGMENT 0x10 /* RW Control Data Structure Segment */
-
-#define EHCI_PERIODICLISTBASE 0x14 /* RW Periodic List Base */
-#define EHCI_ASYNCLISTADDR 0x18 /* RW Async List Base */
-
-#define EHCI_CONFIGFLAG 0x40 /* RW Configure Flag register */
-#define EHCI_CONF_CF 0x00000001 /* RW configure flag */
-
-#define EHCI_PORTSC(n) (0x40+(4*(n))) /* RO, RW, RWC Port Status reg */
-#define EHCI_PS_WKOC_E 0x00400000 /* RW wake on over current ena */
-#define EHCI_PS_WKDSCNNT_E 0x00200000 /* RW wake on disconnect ena */
-#define EHCI_PS_WKCNNT_E 0x00100000 /* RW wake on connect ena */
-#define EHCI_PS_PTC 0x000f0000 /* RW port test control */
-#define EHCI_PS_PIC 0x0000c000 /* RW port indicator control */
-#define EHCI_PS_PO 0x00002000 /* RW port owner */
-#define EHCI_PS_PP 0x00001000 /* RW,RO port power */
-#define EHCI_PS_LS 0x00000c00 /* RO line status */
-#define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == 0x00000400)
-#define EHCI_PS_PR 0x00000100 /* RW port reset */
-#define EHCI_PS_SUSP 0x00000080 /* RW suspend */
-#define EHCI_PS_FPR 0x00000040 /* RW force port resume */
-#define EHCI_PS_OCC 0x00000020 /* RWC over current change */
-#define EHCI_PS_OCA 0x00000010 /* RO over current active */
-#define EHCI_PS_PEC 0x00000008 /* RWC port enable change */
-#define EHCI_PS_PE 0x00000004 /* RW port enable */
-#define EHCI_PS_CSC 0x00000002 /* RWC connect status change */
-#define EHCI_PS_CS 0x00000001 /* RO connect status */
-#define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC)
-
-#define EHCI_USBMODE 0x68 /* RW USB Device mode register */
-#define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */
-#define EHCI_UM_CM_IDLE 0x0 /* Idle */
-#define EHCI_UM_CM_HOST 0x3 /* Host Controller */
-#define EHCI_UM_ES 0x00000004 /* R/WO Endian Select */
-#define EHCI_UM_ES_LE 0x0 /* Little-endian byte alignment */
-#define EHCI_UM_ES_BE 0x4 /* Big-endian byte alignment */
-#define EHCI_UM_SDIS 0x00000010 /* R/WO Stream Disable Mode */
-
-#define EHCI_PORT_RESET_COMPLETE 2 /* ms */
-
-/*
- * Alignment NOTE: structures must be aligned so that the hardware can index
- * without performing addition.
- */
-#define EHCI_FRAMELIST_ALIGN 0x1000 /* bytes */
-#define EHCI_FRAMELIST_COUNT 1024 /* units */
-#define EHCI_VIRTUAL_FRAMELIST_COUNT 128 /* units */
-
-#if ((8*EHCI_VIRTUAL_FRAMELIST_COUNT) < USB_MAX_HS_ISOC_FRAMES_PER_XFER)
-#error "maximum number of high-speed isochronous frames is higher than supported!"
-#endif
-
-#if (EHCI_VIRTUAL_FRAMELIST_COUNT < USB_MAX_FS_ISOC_FRAMES_PER_XFER)
-#error "maximum number of full-speed isochronous frames is higher than supported!"
-#endif
-
-/* Link types */
-#define EHCI_LINK_TERMINATE 0x00000001
-#define EHCI_LINK_TYPE(x) ((x) & 0x00000006)
-#define EHCI_LINK_ITD 0x0
-#define EHCI_LINK_QH 0x2
-#define EHCI_LINK_SITD 0x4
-#define EHCI_LINK_FSTN 0x6
-#define EHCI_LINK_ADDR(x) ((x) &~ 0x1f)
-
-/* Structures alignment (bytes) */
-#define EHCI_ITD_ALIGN 128
-#define EHCI_SITD_ALIGN 64
-#define EHCI_QTD_ALIGN 64
-#define EHCI_QH_ALIGN 128
-#define EHCI_FSTN_ALIGN 32
-/* Data buffers are divided into one or more pages */
-#define EHCI_PAGE_SIZE 0x1000
-#if ((USB_PAGE_SIZE < EHCI_PAGE_SIZE) || (EHCI_PAGE_SIZE == 0) || \
- (USB_PAGE_SIZE < EHCI_ITD_ALIGN) || (EHCI_ITD_ALIGN == 0) || \
- (USB_PAGE_SIZE < EHCI_SITD_ALIGN) || (EHCI_SITD_ALIGN == 0) || \
- (USB_PAGE_SIZE < EHCI_QTD_ALIGN) || (EHCI_QTD_ALIGN == 0) || \
- (USB_PAGE_SIZE < EHCI_QH_ALIGN) || (EHCI_QH_ALIGN == 0) || \
- (USB_PAGE_SIZE < EHCI_FSTN_ALIGN) || (EHCI_FSTN_ALIGN == 0))
-#error "Invalid USB page size!"
-#endif
-
-
-/*
- * Isochronous Transfer Descriptor. This descriptor is used for high speed
- * transfers only.
- */
-struct ehci_itd {
- volatile uint32_t itd_next;
- volatile uint32_t itd_status[8];
-#define EHCI_ITD_SET_LEN(x) ((x) << 16)
-#define EHCI_ITD_GET_LEN(x) (((x) >> 16) & 0xFFF)
-#define EHCI_ITD_IOC (1 << 15)
-#define EHCI_ITD_SET_PG(x) ((x) << 12)
-#define EHCI_ITD_GET_PG(x) (((x) >> 12) & 0x7)
-#define EHCI_ITD_SET_OFFS(x) (x)
-#define EHCI_ITD_GET_OFFS(x) (((x) >> 0) & 0xFFF)
-#define EHCI_ITD_ACTIVE (1 << 31)
-#define EHCI_ITD_DATABUFERR (1 << 30)
-#define EHCI_ITD_BABBLE (1 << 29)
-#define EHCI_ITD_XACTERR (1 << 28)
- volatile uint32_t itd_bp[7];
- /* itd_bp[0] */
-#define EHCI_ITD_SET_ADDR(x) (x)
-#define EHCI_ITD_GET_ADDR(x) (((x) >> 0) & 0x7F)
-#define EHCI_ITD_SET_ENDPT(x) ((x) << 8)
-#define EHCI_ITD_GET_ENDPT(x) (((x) >> 8) & 0xF)
- /* itd_bp[1] */
-#define EHCI_ITD_SET_DIR_IN (1 << 11)
-#define EHCI_ITD_SET_DIR_OUT (0 << 11)
-#define EHCI_ITD_SET_MPL(x) (x)
-#define EHCI_ITD_GET_MPL(x) (((x) >> 0) & 0x7FF)
- volatile uint32_t itd_bp_hi[7];
-/*
- * Extra information needed:
- */
- uint32_t itd_self;
- struct ehci_itd *next;
- struct ehci_itd *prev;
- struct ehci_itd *obj_next;
- struct usb2_page_cache *page_cache;
-} __aligned(EHCI_ITD_ALIGN);
-
-typedef struct ehci_itd ehci_itd_t;
-
-/*
- * Split Transaction Isochronous Transfer Descriptor. This descriptor is used
- * for full speed transfers only.
- */
-struct ehci_sitd {
- volatile uint32_t sitd_next;
- volatile uint32_t sitd_portaddr;
-#define EHCI_SITD_SET_DIR_OUT (0 << 31)
-#define EHCI_SITD_SET_DIR_IN (1 << 31)
-#define EHCI_SITD_SET_ADDR(x) (x)
-#define EHCI_SITD_GET_ADDR(x) ((x) & 0x7F)
-#define EHCI_SITD_SET_ENDPT(x) ((x) << 8)
-#define EHCI_SITD_GET_ENDPT(x) (((x) >> 8) & 0xF)
-#define EHCI_SITD_GET_DIR(x) ((x) >> 31)
-#define EHCI_SITD_SET_PORT(x) ((x) << 24)
-#define EHCI_SITD_GET_PORT(x) (((x) >> 24) & 0x7F)
-#define EHCI_SITD_SET_HUBA(x) ((x) << 16)
-#define EHCI_SITD_GET_HUBA(x) (((x) >> 16) & 0x7F)
- volatile uint32_t sitd_mask;
-#define EHCI_SITD_SET_SMASK(x) (x)
-#define EHCI_SITD_SET_CMASK(x) ((x) << 8)
- volatile uint32_t sitd_status;
-#define EHCI_SITD_COMPLETE_SPLIT (1<<1)
-#define EHCI_SITD_START_SPLIT (0<<1)
-#define EHCI_SITD_MISSED_MICRO_FRAME (1<<2)
-#define EHCI_SITD_XACTERR (1<<3)
-#define EHCI_SITD_BABBLE (1<<4)
-#define EHCI_SITD_DATABUFERR (1<<5)
-#define EHCI_SITD_ERROR (1<<6)
-#define EHCI_SITD_ACTIVE (1<<7)
-#define EHCI_SITD_IOC (1<<31)
-#define EHCI_SITD_SET_LEN(len) ((len)<<16)
-#define EHCI_SITD_GET_LEN(x) (((x)>>16) & 0x3FF)
- volatile uint32_t sitd_bp[2];
- volatile uint32_t sitd_back;
- volatile uint32_t sitd_bp_hi[2];
-/*
- * Extra information needed:
- */
- uint32_t sitd_self;
- struct ehci_sitd *next;
- struct ehci_sitd *prev;
- struct ehci_sitd *obj_next;
- struct usb2_page_cache *page_cache;
-} __aligned(EHCI_SITD_ALIGN);
-
-typedef struct ehci_sitd ehci_sitd_t;
-
-/* Queue Element Transfer Descriptor */
-struct ehci_qtd {
- volatile uint32_t qtd_next;
- volatile uint32_t qtd_altnext;
- volatile uint32_t qtd_status;
-#define EHCI_QTD_GET_STATUS(x) (((x) >> 0) & 0xff)
-#define EHCI_QTD_SET_STATUS(x) ((x) << 0)
-#define EHCI_QTD_ACTIVE 0x80
-#define EHCI_QTD_HALTED 0x40
-#define EHCI_QTD_BUFERR 0x20
-#define EHCI_QTD_BABBLE 0x10
-#define EHCI_QTD_XACTERR 0x08
-#define EHCI_QTD_MISSEDMICRO 0x04
-#define EHCI_QTD_SPLITXSTATE 0x02
-#define EHCI_QTD_PINGSTATE 0x01
-#define EHCI_QTD_STATERRS 0x74
-#define EHCI_QTD_GET_PID(x) (((x) >> 8) & 0x3)
-#define EHCI_QTD_SET_PID(x) ((x) << 8)
-#define EHCI_QTD_PID_OUT 0x0
-#define EHCI_QTD_PID_IN 0x1
-#define EHCI_QTD_PID_SETUP 0x2
-#define EHCI_QTD_GET_CERR(x) (((x) >> 10) & 0x3)
-#define EHCI_QTD_SET_CERR(x) ((x) << 10)
-#define EHCI_QTD_GET_C_PAGE(x) (((x) >> 12) & 0x7)
-#define EHCI_QTD_SET_C_PAGE(x) ((x) << 12)
-#define EHCI_QTD_GET_IOC(x) (((x) >> 15) & 0x1)
-#define EHCI_QTD_IOC 0x00008000
-#define EHCI_QTD_GET_BYTES(x) (((x) >> 16) & 0x7fff)
-#define EHCI_QTD_SET_BYTES(x) ((x) << 16)
-#define EHCI_QTD_GET_TOGGLE(x) (((x) >> 31) & 0x1)
-#define EHCI_QTD_SET_TOGGLE(x) ((x) << 31)
-#define EHCI_QTD_TOGGLE_MASK 0x80000000
-#define EHCI_QTD_NBUFFERS 5
-#define EHCI_QTD_PAYLOAD_MAX ((EHCI_QTD_NBUFFERS-1)*EHCI_PAGE_SIZE)
- volatile uint32_t qtd_buffer[EHCI_QTD_NBUFFERS];
- volatile uint32_t qtd_buffer_hi[EHCI_QTD_NBUFFERS];
-/*
- * Extra information needed:
- */
- struct ehci_qtd *alt_next;
- struct ehci_qtd *obj_next;
- struct usb2_page_cache *page_cache;
- uint32_t qtd_self;
- uint16_t len;
-} __aligned(EHCI_QTD_ALIGN);
-
-typedef struct ehci_qtd ehci_qtd_t;
-
-/* Queue Head Sub Structure */
-struct ehci_qh_sub {
- volatile uint32_t qtd_next;
- volatile uint32_t qtd_altnext;
- volatile uint32_t qtd_status;
- volatile uint32_t qtd_buffer[EHCI_QTD_NBUFFERS];
- volatile uint32_t qtd_buffer_hi[EHCI_QTD_NBUFFERS];
-} __aligned(4);
-
-/* Queue Head */
-struct ehci_qh {
- volatile uint32_t qh_link;
- volatile uint32_t qh_endp;
-#define EHCI_QH_GET_ADDR(x) (((x) >> 0) & 0x7f) /* endpoint addr */
-#define EHCI_QH_SET_ADDR(x) (x)
-#define EHCI_QH_ADDRMASK 0x0000007f
-#define EHCI_QH_GET_INACT(x) (((x) >> 7) & 0x01) /* inactivate on next */
-#define EHCI_QH_INACT 0x00000080
-#define EHCI_QH_GET_ENDPT(x) (((x) >> 8) & 0x0f) /* endpoint no */
-#define EHCI_QH_SET_ENDPT(x) ((x) << 8)
-#define EHCI_QH_GET_EPS(x) (((x) >> 12) & 0x03) /* endpoint speed */
-#define EHCI_QH_SET_EPS(x) ((x) << 12)
-#define EHCI_QH_SPEED_FULL 0x0
-#define EHCI_QH_SPEED_LOW 0x1
-#define EHCI_QH_SPEED_HIGH 0x2
-#define EHCI_QH_GET_DTC(x) (((x) >> 14) & 0x01) /* data toggle control */
-#define EHCI_QH_DTC 0x00004000
-#define EHCI_QH_GET_HRECL(x) (((x) >> 15) & 0x01) /* head of reclamation */
-#define EHCI_QH_HRECL 0x00008000
-#define EHCI_QH_GET_MPL(x) (((x) >> 16) & 0x7ff) /* max packet len */
-#define EHCI_QH_SET_MPL(x) ((x) << 16)
-#define EHCI_QH_MPLMASK 0x07ff0000
-#define EHCI_QH_GET_CTL(x) (((x) >> 27) & 0x01) /* control endpoint */
-#define EHCI_QH_CTL 0x08000000
-#define EHCI_QH_GET_NRL(x) (((x) >> 28) & 0x0f) /* NAK reload */
-#define EHCI_QH_SET_NRL(x) ((x) << 28)
- volatile uint32_t qh_endphub;
-#define EHCI_QH_GET_SMASK(x) (((x) >> 0) & 0xff) /* intr sched mask */
-#define EHCI_QH_SET_SMASK(x) ((x) << 0)
-#define EHCI_QH_GET_CMASK(x) (((x) >> 8) & 0xff) /* split completion mask */
-#define EHCI_QH_SET_CMASK(x) ((x) << 8)
-#define EHCI_QH_GET_HUBA(x) (((x) >> 16) & 0x7f) /* hub address */
-#define EHCI_QH_SET_HUBA(x) ((x) << 16)
-#define EHCI_QH_GET_PORT(x) (((x) >> 23) & 0x7f) /* hub port */
-#define EHCI_QH_SET_PORT(x) ((x) << 23)
-#define EHCI_QH_GET_MULT(x) (((x) >> 30) & 0x03) /* pipe multiplier */
-#define EHCI_QH_SET_MULT(x) ((x) << 30)
- volatile uint32_t qh_curqtd;
- struct ehci_qh_sub qh_qtd;
-/*
- * Extra information needed:
- */
- struct ehci_qh *next;
- struct ehci_qh *prev;
- struct ehci_qh *obj_next;
- struct usb2_page_cache *page_cache;
- uint32_t qh_self;
-} __aligned(EHCI_QH_ALIGN);
-
-typedef struct ehci_qh ehci_qh_t;
-
-/* Periodic Frame Span Traversal Node */
-struct ehci_fstn {
- volatile uint32_t fstn_link;
- volatile uint32_t fstn_back;
-} __aligned(EHCI_FSTN_ALIGN);
-
-typedef struct ehci_fstn ehci_fstn_t;
-
-struct ehci_hw_softc {
- struct usb2_page_cache pframes_pc;
- struct usb2_page_cache async_start_pc;
- struct usb2_page_cache intr_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT];
- struct usb2_page_cache isoc_hs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT];
- struct usb2_page_cache isoc_fs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT];
-
- struct usb2_page pframes_pg;
- struct usb2_page async_start_pg;
- struct usb2_page intr_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT];
- struct usb2_page isoc_hs_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT];
- struct usb2_page isoc_fs_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT];
-};
-
-struct ehci_config_desc {
- struct usb2_config_descriptor confd;
- struct usb2_interface_descriptor ifcd;
- struct usb2_endpoint_descriptor endpd;
-} __packed;
-
-union ehci_hub_desc {
- struct usb2_status stat;
- struct usb2_port_status ps;
- struct usb2_device_descriptor devd;
- struct usb2_device_qualifier odevd;
- struct usb2_hub_descriptor hubd;
- uint8_t temp[128];
-};
-
-typedef struct ehci_softc {
- struct ehci_hw_softc sc_hw;
- struct usb2_bus sc_bus; /* base device */
- struct usb2_callout sc_tmo_pcd;
- union ehci_hub_desc sc_hub_desc;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
-
- struct usb2_device *sc_devices[EHCI_MAX_DEVICES];
- struct resource *sc_io_res;
- struct resource *sc_irq_res;
- struct ehci_qh *sc_async_p_last;
- struct ehci_qh *sc_intr_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT];
- struct ehci_sitd *sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT];
- struct ehci_itd *sc_isoc_hs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT];
- void *sc_intr_hdl;
- bus_size_t sc_io_size;
- bus_space_tag_t sc_io_tag;
- bus_space_handle_t sc_io_hdl;
-
- uint32_t sc_eintrs;
- uint32_t sc_cmd; /* shadow of cmd register during
- * suspend */
-
- uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT];
- uint16_t sc_id_vendor; /* vendor ID for root hub */
- uint16_t sc_flags; /* chip specific flags */
-#define EHCI_SCFLG_SETMODE 0x0001 /* set bridge mode again after init */
-#define EHCI_SCFLG_FORCESPEED 0x0002 /* force speed */
-#define EHCI_SCFLG_NORESTERM 0x0004 /* don't terminate reset sequence */
-#define EHCI_SCFLG_BIGEDESC 0x0008 /* big-endian byte order descriptors */
-#define EHCI_SCFLG_BIGEMMIO 0x0010 /* big-endian byte order MMIO */
-#define EHCI_SCFLG_TT 0x0020 /* transaction translator present */
-
- uint8_t sc_offs; /* offset to operational registers */
- uint8_t sc_doorbell_disable; /* set on doorbell failure */
- uint8_t sc_noport;
- uint8_t sc_addr; /* device address */
- uint8_t sc_conf; /* device configuration */
- uint8_t sc_isreset;
- uint8_t sc_hub_idata[8];
-
- char sc_vendor[16]; /* vendor string for root hub */
-
-} ehci_softc_t;
-
-#define EREAD1(sc, a) bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a))
-#define EREAD2(sc, a) bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (a))
-#define EREAD4(sc, a) bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (a))
-#define EWRITE1(sc, a, x) \
- bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a), (x))
-#define EWRITE2(sc, a, x) \
- bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (a), (x))
-#define EWRITE4(sc, a, x) \
- bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (a), (x))
-#define EOREAD1(sc, a) \
- bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a))
-#define EOREAD2(sc, a) \
- bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a))
-#define EOREAD4(sc, a) \
- bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a))
-#define EOWRITE1(sc, a, x) \
- bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a), (x))
-#define EOWRITE2(sc, a, x) \
- bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a), (x))
-#define EOWRITE4(sc, a, x) \
- bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (sc)->sc_offs+(a), (x))
-
-usb2_bus_mem_cb_t ehci_iterate_hw_softc;
-
-usb2_error_t ehci_init(ehci_softc_t *sc);
-void ehci_detach(struct ehci_softc *sc);
-void ehci_suspend(struct ehci_softc *sc);
-void ehci_resume(struct ehci_softc *sc);
-void ehci_shutdown(ehci_softc_t *sc);
-void ehci_interrupt(ehci_softc_t *sc);
-
-#endif /* _EHCI_H_ */
diff --git a/sys/dev/usb2/controller/ehci2_ixp4xx.c b/sys/dev/usb2/controller/ehci2_ixp4xx.c
deleted file mode 100644
index 91ce863..0000000
--- a/sys/dev/usb2/controller/ehci2_ixp4xx.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*-
- * Copyright (c) 2008 Sam Leffler. 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.
- * 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.
- */
-
-/*
- * IXP435 attachment driver for the USB Enhanced Host Controller.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_bus.h"
-
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/ehci2.h>
-
-#include <arm/xscale/ixp425/ixp425reg.h>
-#include <arm/xscale/ixp425/ixp425var.h>
-
-#define EHCI_VENDORID_IXP4XX 0x42fa05
-#define EHCI_HC_DEVSTR "IXP4XX Integrated USB 2.0 controller"
-
-struct ixp_ehci_softc {
- ehci_softc_t base; /* storage for EHCI code */
- bus_space_tag_t iot;
- bus_space_handle_t ioh;
- struct bus_space tag; /* tag for private bus space ops */
-};
-
-static device_attach_t ehci_ixp_attach;
-static device_detach_t ehci_ixp_detach;
-static device_shutdown_t ehci_ixp_shutdown;
-static device_suspend_t ehci_ixp_suspend;
-static device_resume_t ehci_ixp_resume;
-
-static uint8_t ehci_bs_r_1(void *, bus_space_handle_t, bus_size_t);
-static void ehci_bs_w_1(void *, bus_space_handle_t, bus_size_t, u_int8_t);
-static uint16_t ehci_bs_r_2(void *, bus_space_handle_t, bus_size_t);
-static void ehci_bs_w_2(void *, bus_space_handle_t, bus_size_t, uint16_t);
-static uint32_t ehci_bs_r_4(void *, bus_space_handle_t, bus_size_t);
-static void ehci_bs_w_4(void *, bus_space_handle_t, bus_size_t, uint32_t);
-
-static int
-ehci_ixp_suspend(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- int err;
-
- err = bus_generic_suspend(self);
- if (err)
- return (err);
- ehci_suspend(sc);
- return (0);
-}
-
-static int
-ehci_ixp_resume(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
-
- ehci_resume(sc);
-
- bus_generic_resume(self);
-
- return (0);
-}
-
-static int
-ehci_ixp_shutdown(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- int err;
-
- err = bus_generic_shutdown(self);
- if (err)
- return (err);
- ehci_shutdown(sc);
-
- return (0);
-}
-
-static int
-ehci_ixp_probe(device_t self)
-{
-
- device_set_desc(self, EHCI_HC_DEVSTR);
-
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-ehci_ixp_attach(device_t self)
-{
- struct ixp_ehci_softc *isc = device_get_softc(self);
- ehci_softc_t *sc = &isc->base;
- int err;
- int rid;
-
- /* initialise some bus fields */
- sc->sc_bus.parent = self;
- sc->sc_bus.devices = sc->sc_devices;
- sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
-
- /* get all DMA memory */
- if (usb2_bus_mem_alloc_all(&sc->sc_bus,
- USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
- return (ENOMEM);
- }
-
- sc->sc_bus.usbrev = USB_REV_2_0;
-
- /* NB: hints fix the memory location and irq */
-
- rid = 0;
- sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (!sc->sc_io_res) {
- device_printf(self, "Could not map memory\n");
- goto error;
- }
-
- /*
- * Craft special resource for bus space ops that handle
- * byte-alignment of non-word addresses. Also, since
- * we're already intercepting bus space ops we handle
- * the register window offset that could otherwise be
- * done with bus_space_subregion.
- */
- isc->iot = rman_get_bustag(sc->sc_io_res);
- isc->tag.bs_cookie = isc->iot;
- /* read single */
- isc->tag.bs_r_1 = ehci_bs_r_1,
- isc->tag.bs_r_2 = ehci_bs_r_2,
- isc->tag.bs_r_4 = ehci_bs_r_4,
- /* write (single) */
- isc->tag.bs_w_1 = ehci_bs_w_1,
- isc->tag.bs_w_2 = ehci_bs_w_2,
- isc->tag.bs_w_4 = ehci_bs_w_4,
-
- sc->sc_io_tag = &isc->tag;
- sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
- sc->sc_io_size = IXP435_USB1_SIZE - 0x100;
-
- rid = 0;
- sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
- RF_ACTIVE);
- if (sc->sc_irq_res == NULL) {
- device_printf(self, "Could not allocate irq\n");
- goto error;
- }
- sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
- if (!sc->sc_bus.bdev) {
- device_printf(self, "Could not add USB device\n");
- goto error;
- }
- device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
- device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);
-
- sprintf(sc->sc_vendor, "Intel");
-
-
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl);
- if (err) {
- device_printf(self, "Could not setup irq, %d\n", err);
- sc->sc_intr_hdl = NULL;
- goto error;
- }
-
- /*
- * Arrange to force Host mode, select big-endian byte alignment,
- * and arrange to not terminate reset operations (the adapter
- * will ignore it if we do but might as well save a reg write).
- * Also, the controller has an embedded Transaction Translator
- * which means port speed must be read from the Port Status
- * register following a port enable.
- */
- sc->sc_flags |= EHCI_SCFLG_TT
- | EHCI_SCFLG_SETMODE
- | EHCI_SCFLG_BIGEDESC
- | EHCI_SCFLG_BIGEMMIO
- | EHCI_SCFLG_NORESTERM
- ;
-
- err = ehci_init(sc);
- if (!err) {
- err = device_probe_and_attach(sc->sc_bus.bdev);
- }
- if (err) {
- device_printf(self, "USB init failed err=%d\n", err);
- goto error;
- }
- return (0);
-
-error:
- ehci_ixp_detach(self);
- return (ENXIO);
-}
-
-static int
-ehci_ixp_detach(device_t self)
-{
- struct ixp_ehci_softc *isc = device_get_softc(self);
- ehci_softc_t *sc = &isc->base;
- device_t bdev;
- int err;
-
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(self);
-
- /*
- * disable interrupts that might have been switched on in ehci_init
- */
- if (sc->sc_io_res) {
- EWRITE4(sc, EHCI_USBINTR, 0);
- }
-
- if (sc->sc_irq_res && sc->sc_intr_hdl) {
- /*
- * only call ehci_detach() after ehci_init()
- */
- ehci_detach(sc);
-
- err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
-
- if (err)
- /* XXX or should we panic? */
- device_printf(self, "Could not tear down irq, %d\n",
- err);
- sc->sc_intr_hdl = NULL;
- }
-
- if (sc->sc_irq_res) {
- bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
- sc->sc_irq_res = NULL;
- }
- if (sc->sc_io_res) {
- bus_release_resource(self, SYS_RES_MEMORY, 0,
- sc->sc_io_res);
- sc->sc_io_res = NULL;
- }
- usb2_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
-
- return (0);
-}
-
-/*
- * Bus space accessors for PIO operations.
- */
-
-static uint8_t
-ehci_bs_r_1(void *t, bus_space_handle_t h, bus_size_t o)
-{
- return bus_space_read_1((bus_space_tag_t) t, h,
- 0x100 + (o &~ 3) + (3 - (o & 3)));
-}
-
-static void
-ehci_bs_w_1(void *t, bus_space_handle_t h, bus_size_t o, u_int8_t v)
-{
- panic("%s", __func__);
-}
-
-static uint16_t
-ehci_bs_r_2(void *t, bus_space_handle_t h, bus_size_t o)
-{
- return bus_space_read_2((bus_space_tag_t) t, h,
- 0x100 + (o &~ 3) + (2 - (o & 3)));
-}
-
-static void
-ehci_bs_w_2(void *t, bus_space_handle_t h, bus_size_t o, uint16_t v)
-{
- panic("%s", __func__);
-}
-
-static uint32_t
-ehci_bs_r_4(void *t, bus_space_handle_t h, bus_size_t o)
-{
- return bus_space_read_4((bus_space_tag_t) t, h, 0x100 + o);
-}
-
-static void
-ehci_bs_w_4(void *t, bus_space_handle_t h, bus_size_t o, uint32_t v)
-{
- bus_space_write_4((bus_space_tag_t) t, h, 0x100 + o, v);
-}
-
-static device_method_t ehci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ehci_ixp_probe),
- DEVMETHOD(device_attach, ehci_ixp_attach),
- DEVMETHOD(device_detach, ehci_ixp_detach),
- DEVMETHOD(device_suspend, ehci_ixp_suspend),
- DEVMETHOD(device_resume, ehci_ixp_resume),
- DEVMETHOD(device_shutdown, ehci_ixp_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
-};
-
-static driver_t ehci_driver = {
- "ehci",
- ehci_methods,
- sizeof(struct ixp_ehci_softc),
-};
-
-static devclass_t ehci_devclass;
-
-DRIVER_MODULE(ehci, ixp, ehci_driver, ehci_devclass, 0, 0);
-MODULE_DEPEND(ehci, usb2_controller, 1, 1, 1);
-MODULE_DEPEND(ehci, usb2_core, 1, 1, 1);
diff --git a/sys/dev/usb2/controller/ehci2_mbus.c b/sys/dev/usb2/controller/ehci2_mbus.c
deleted file mode 100644
index 404617b..0000000
--- a/sys/dev/usb2/controller/ehci2_mbus.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*-
- * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
- * All rights reserved.
- *
- * Developed by Semihalf.
- *
- * 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.
- * 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.
- * 3. Neither the name of MARVELL nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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.
- */
-
-/*
- * MBus attachment driver for the USB Enhanced Host Controller.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_bus.h"
-
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/ehci2.h>
-
-#include <arm/mv/mvreg.h>
-#include <arm/mv/mvvar.h>
-
-#define EHCI_VENDORID_MRVL 0x1286
-#define EHCI_HC_DEVSTR "Marvell Integrated USB 2.0 controller"
-
-static device_attach_t ehci_mbus_attach;
-static device_detach_t ehci_mbus_detach;
-static device_shutdown_t ehci_mbus_shutdown;
-static device_suspend_t ehci_mbus_suspend;
-static device_resume_t ehci_mbus_resume;
-
-static int err_intr(void *arg);
-
-static struct resource *irq_err;
-static void *ih_err;
-
-#define USB_BRIDGE_INTR_CAUSE 0x210
-#define USB_BRIDGE_INTR_MASK 0x214
-
-#define MV_USB_ADDR_DECODE_ERR (1 << 0)
-#define MV_USB_HOST_UNDERFLOW (1 << 1)
-#define MV_USB_HOST_OVERFLOW (1 << 2)
-#define MV_USB_DEVICE_UNDERFLOW (1 << 3)
-
-static int
-ehci_mbus_suspend(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- int err;
-
- err = bus_generic_suspend(self);
- if (err)
- return (err);
- ehci_suspend(sc);
- return (0);
-}
-
-static int
-ehci_mbus_resume(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
-
- ehci_resume(sc);
-
- bus_generic_resume(self);
-
- return (0);
-}
-
-static int
-ehci_mbus_shutdown(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- int err;
-
- err = bus_generic_shutdown(self);
- if (err)
- return (err);
- ehci_shutdown(sc);
-
- return (0);
-}
-
-static int
-ehci_mbus_probe(device_t self)
-{
-
- device_set_desc(self, EHCI_HC_DEVSTR);
-
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-ehci_mbus_attach(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- bus_space_handle_t bsh;
- int err;
- int rid;
-
- /* initialise some bus fields */
- sc->sc_bus.parent = self;
- sc->sc_bus.devices = sc->sc_devices;
- sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
-
- /* get all DMA memory */
- if (usb2_bus_mem_alloc_all(&sc->sc_bus,
- USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
- return (ENOMEM);
- }
-
- sc->sc_bus.usbrev = USB_REV_2_0;
-
- rid = 0;
- sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (!sc->sc_io_res) {
- device_printf(self, "Could not map memory\n");
- goto error;
- }
- sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
- bsh = rman_get_bushandle(sc->sc_io_res);
- sc->sc_io_size = MV_USB_SIZE - MV_USB_HOST_OFST;
-
- /*
- * Marvell EHCI host controller registers start at certain offset within
- * the whole USB registers range, so create a subregion for the host
- * mode configuration purposes.
- */
- if (bus_space_subregion(sc->sc_io_tag, bsh, MV_USB_HOST_OFST,
- sc->sc_io_size, &sc->sc_io_hdl) != 0)
- panic("%s: unable to subregion USB host registers",
- device_get_name(self));
-
- rid = 0;
- irq_err = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (irq_err == NULL) {
- device_printf(self, "Could not allocate error irq\n");
- ehci_mbus_detach(self);
- return (ENXIO);
- }
-
- /*
- * Notice: Marvell EHCI controller has TWO interrupt lines, so make sure to
- * use the correct rid for the main one (controller interrupt) --
- * refer to obio_devices[] for the right resource number to use here.
- */
- rid = 1;
- sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (sc->sc_irq_res == NULL) {
- device_printf(self, "Could not allocate irq\n");
- goto error;
- }
-
- sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
- if (!sc->sc_bus.bdev) {
- device_printf(self, "Could not add USB device\n");
- goto error;
- }
- device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
- device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);
-
- sprintf(sc->sc_vendor, "Marvell");
-
- err = bus_setup_intr(self, irq_err, INTR_FAST | INTR_TYPE_BIO,
- err_intr, NULL, sc, &ih_err);
- if (err) {
- device_printf(self, "Could not setup error irq, %d\n", err);
- ih_err = NULL;
- goto error;
- }
-
- EWRITE4(sc, USB_BRIDGE_INTR_MASK, MV_USB_ADDR_DECODE_ERR |
- MV_USB_HOST_UNDERFLOW | MV_USB_HOST_OVERFLOW |
- MV_USB_DEVICE_UNDERFLOW);
-
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl);
- if (err) {
- device_printf(self, "Could not setup irq, %d\n", err);
- sc->sc_intr_hdl = NULL;
- goto error;
- }
-
- /*
- * Workaround for Marvell integrated EHCI controller: reset of
- * the EHCI core clears the USBMODE register, which sets the core in
- * an undefined state (neither host nor agent), so it needs to be set
- * again for proper operation.
- *
- * Refer to errata document MV-S500832-00D.pdf (p. 5.24 GL USB-2) for
- * details.
- */
- sc->sc_flags |= EHCI_SCFLG_SETMODE;
- if (bootverbose)
- device_printf(self, "5.24 GL USB-2 workaround enabled\n");
-
- /* XXX all MV chips need it? */
- sc->sc_flags |= EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_NORESTERM;
-
- err = ehci_init(sc);
- if (!err) {
- err = device_probe_and_attach(sc->sc_bus.bdev);
- }
- if (err) {
- device_printf(self, "USB init failed err=%d\n", err);
- goto error;
- }
- return (0);
-
-error:
- ehci_mbus_detach(self);
- return (ENXIO);
-}
-
-static int
-ehci_mbus_detach(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- device_t bdev;
- int err;
-
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(self);
-
- /*
- * disable interrupts that might have been switched on in ehci_init
- */
- if (sc->sc_io_res) {
- EWRITE4(sc, EHCI_USBINTR, 0);
- EWRITE4(sc, USB_BRIDGE_INTR_MASK, 0);
- }
- if (sc->sc_irq_res && sc->sc_intr_hdl) {
- /*
- * only call ehci_detach() after ehci_init()
- */
- ehci_detach(sc);
-
- err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
-
- if (err)
- /* XXX or should we panic? */
- device_printf(self, "Could not tear down irq, %d\n",
- err);
- sc->sc_intr_hdl = NULL;
- }
- if (irq_err && ih_err) {
- err = bus_teardown_intr(self, irq_err, ih_err);
-
- if (err)
- device_printf(self, "Could not tear down irq, %d\n",
- err);
- ih_err = NULL;
- }
- if (irq_err) {
- bus_release_resource(self, SYS_RES_IRQ, 0, irq_err);
- irq_err = NULL;
- }
- if (sc->sc_irq_res) {
- bus_release_resource(self, SYS_RES_IRQ, 1, sc->sc_irq_res);
- sc->sc_irq_res = NULL;
- }
- if (sc->sc_io_res) {
- bus_release_resource(self, SYS_RES_MEMORY, 0,
- sc->sc_io_res);
- sc->sc_io_res = NULL;
- }
- usb2_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
-
- return (0);
-}
-
-static int
-err_intr(void *arg)
-{
- ehci_softc_t *sc = arg;
- unsigned int cause;
-
- cause = EREAD4(sc, USB_BRIDGE_INTR_CAUSE);
- if (cause) {
- printf("IRQ ERR: cause: 0x%08x\n", cause);
- if (cause & MV_USB_ADDR_DECODE_ERR)
- printf("IRQ ERR: Address decoding error\n");
- if (cause & MV_USB_HOST_UNDERFLOW)
- printf("IRQ ERR: USB Host Underflow\n");
- if (cause & MV_USB_HOST_OVERFLOW)
- printf("IRQ ERR: USB Host Overflow\n");
- if (cause & MV_USB_DEVICE_UNDERFLOW)
- printf("IRQ ERR: USB Device Underflow\n");
- if (cause & ~(MV_USB_ADDR_DECODE_ERR | MV_USB_HOST_UNDERFLOW |
- MV_USB_HOST_OVERFLOW | MV_USB_DEVICE_UNDERFLOW))
- printf("IRQ ERR: Unknown error\n");
-
- EWRITE4(sc, USB_BRIDGE_INTR_CAUSE, 0);
- }
- return (FILTER_HANDLED);
-}
-
-static device_method_t ehci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ehci_mbus_probe),
- DEVMETHOD(device_attach, ehci_mbus_attach),
- DEVMETHOD(device_detach, ehci_mbus_detach),
- DEVMETHOD(device_suspend, ehci_mbus_suspend),
- DEVMETHOD(device_resume, ehci_mbus_resume),
- DEVMETHOD(device_shutdown, ehci_mbus_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
-};
-
-static driver_t ehci_driver = {
- "ehci",
- ehci_methods,
- sizeof(ehci_softc_t),
-};
-
-static devclass_t ehci_devclass;
-
-DRIVER_MODULE(ehci, mbus, ehci_driver, ehci_devclass, 0, 0);
-MODULE_DEPEND(ehci, usb2_controller, 1, 1, 1);
-MODULE_DEPEND(ehci, usb2_core, 1, 1, 1);
diff --git a/sys/dev/usb2/controller/ehci2_pci.c b/sys/dev/usb2/controller/ehci2_pci.c
deleted file mode 100644
index 5e39c8f..0000000
--- a/sys/dev/usb2/controller/ehci2_pci.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (augustss@carlstedt.se) at
- * Carlstedt Research & Technology.
- *
- * 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.
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``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 FOUNDATION OR CONTRIBUTORS
- * 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$");
-
-/*
- * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller.
- *
- * The EHCI 1.0 spec can be found at
- * http://developer.intel.com/technology/usb/download/ehci-r10.pdf
- * and the USB 2.0 spec at
- * http://www.usb.org/developers/docs/usb_20.zip
- */
-
-/* The low level controller code for EHCI has been split into
- * PCI probes and EHCI specific code. This was done to facilitate the
- * sharing of code between *BSD's
- */
-
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/usb2_pci.h>
-#include <dev/usb2/controller/ehci2.h>
-
-#define PCI_EHCI_VENDORID_ACERLABS 0x10b9
-#define PCI_EHCI_VENDORID_AMD 0x1022
-#define PCI_EHCI_VENDORID_APPLE 0x106b
-#define PCI_EHCI_VENDORID_ATI 0x1002
-#define PCI_EHCI_VENDORID_CMDTECH 0x1095
-#define PCI_EHCI_VENDORID_INTEL 0x8086
-#define PCI_EHCI_VENDORID_NEC 0x1033
-#define PCI_EHCI_VENDORID_OPTI 0x1045
-#define PCI_EHCI_VENDORID_PHILIPS 0x1131
-#define PCI_EHCI_VENDORID_SIS 0x1039
-#define PCI_EHCI_VENDORID_NVIDIA 0x12D2
-#define PCI_EHCI_VENDORID_NVIDIA2 0x10DE
-#define PCI_EHCI_VENDORID_VIA 0x1106
-
-#define PCI_EHCI_BASE_REG 0x10
-
-static void ehci_pci_takecontroller(device_t self);
-
-static device_probe_t ehci_pci_probe;
-static device_attach_t ehci_pci_attach;
-static device_detach_t ehci_pci_detach;
-static device_suspend_t ehci_pci_suspend;
-static device_resume_t ehci_pci_resume;
-static device_shutdown_t ehci_pci_shutdown;
-
-static int
-ehci_pci_suspend(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- int err;
-
- err = bus_generic_suspend(self);
- if (err)
- return (err);
- ehci_suspend(sc);
- return (0);
-}
-
-static int
-ehci_pci_resume(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
-
- ehci_pci_takecontroller(self);
- ehci_resume(sc);
-
- bus_generic_resume(self);
-
- return (0);
-}
-
-static int
-ehci_pci_shutdown(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- int err;
-
- err = bus_generic_shutdown(self);
- if (err)
- return (err);
- ehci_shutdown(sc);
-
- return (0);
-}
-
-static const char *
-ehci_pci_match(device_t self)
-{
- uint32_t device_id = pci_get_devid(self);
-
- switch (device_id) {
- case 0x268c8086:
- return ("Intel 63XXESB USB 2.0 controller");
-
- case 0x523910b9:
- return "ALi M5239 USB 2.0 controller";
-
- case 0x10227463:
- return "AMD 8111 USB 2.0 controller";
-
- case 0x20951022:
- return ("AMD CS5536 (Geode) USB 2.0 controller");
-
- case 0x43451002:
- return "ATI SB200 USB 2.0 controller";
- case 0x43731002:
- return "ATI SB400 USB 2.0 controller";
-
- case 0x25ad8086:
- return "Intel 6300ESB USB 2.0 controller";
- case 0x24cd8086:
- return "Intel 82801DB/L/M (ICH4) USB 2.0 controller";
- case 0x24dd8086:
- return "Intel 82801EB/R (ICH5) USB 2.0 controller";
- case 0x265c8086:
- return "Intel 82801FB (ICH6) USB 2.0 controller";
- case 0x27cc8086:
- return "Intel 82801GB/R (ICH7) USB 2.0 controller";
-
- case 0x28368086:
- return "Intel 82801H (ICH8) USB 2.0 controller USB2-A";
- case 0x283a8086:
- return "Intel 82801H (ICH8) USB 2.0 controller USB2-B";
- case 0x293a8086:
- return "Intel 82801I (ICH9) USB 2.0 controller";
- case 0x293c8086:
- return "Intel 82801I (ICH9) USB 2.0 controller";
-
- case 0x00e01033:
- return ("NEC uPD 720100 USB 2.0 controller");
-
- case 0x006810de:
- return "NVIDIA nForce2 USB 2.0 controller";
- case 0x008810de:
- return "NVIDIA nForce2 Ultra 400 USB 2.0 controller";
- case 0x00d810de:
- return "NVIDIA nForce3 USB 2.0 controller";
- case 0x00e810de:
- return "NVIDIA nForce3 250 USB 2.0 controller";
- case 0x005b10de:
- return "NVIDIA nForce4 USB 2.0 controller";
-
- case 0x15621131:
- return "Philips ISP156x USB 2.0 controller";
-
- case 0x31041106:
- return ("VIA VT6202 USB 2.0 controller");
-
- default:
- break;
- }
-
- if ((pci_get_class(self) == PCIC_SERIALBUS)
- && (pci_get_subclass(self) == PCIS_SERIALBUS_USB)
- && (pci_get_progif(self) == PCI_INTERFACE_EHCI)) {
- return ("EHCI (generic) USB 2.0 controller");
- }
- return (NULL); /* dunno */
-}
-
-static int
-ehci_pci_probe(device_t self)
-{
- const char *desc = ehci_pci_match(self);
-
- if (desc) {
- device_set_desc(self, desc);
- return (0);
- } else {
- return (ENXIO);
- }
-}
-
-static int
-ehci_pci_attach(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- int err;
- int rid;
-
- /* initialise some bus fields */
- sc->sc_bus.parent = self;
- sc->sc_bus.devices = sc->sc_devices;
- sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
-
- /* get all DMA memory */
- if (usb2_bus_mem_alloc_all(&sc->sc_bus,
- USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
- return (ENOMEM);
- }
-
- pci_enable_busmaster(self);
-
- switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USB_REV_MASK) {
- case PCI_USB_REV_PRE_1_0:
- case PCI_USB_REV_1_0:
- case PCI_USB_REV_1_1:
- /*
- * NOTE: some EHCI USB controllers have the wrong USB
- * revision number. It appears those controllers are
- * fully compliant so we just ignore this value in
- * some common cases.
- */
- device_printf(self, "pre-2.0 USB revision (ignored)\n");
- /* fallthrough */
- case PCI_USB_REV_2_0:
- sc->sc_bus.usbrev = USB_REV_2_0;
- break;
- default:
- /* Quirk for Parallels Desktop 4.0 */
- device_printf(self, "USB revision is unknown. Assuming v2.0.\n");
- sc->sc_bus.usbrev = USB_REV_2_0;
- break;
- }
-
- rid = PCI_CBMEM;
- sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
- RF_ACTIVE);
- if (!sc->sc_io_res) {
- device_printf(self, "Could not map memory\n");
- goto error;
- }
- sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
- sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
- sc->sc_io_size = rman_get_size(sc->sc_io_res);
-
- rid = 0;
- sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (sc->sc_irq_res == NULL) {
- device_printf(self, "Could not allocate irq\n");
- goto error;
- }
- sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
- if (!sc->sc_bus.bdev) {
- device_printf(self, "Could not add USB device\n");
- goto error;
- }
- device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
-
- /*
- * ehci_pci_match will never return NULL if ehci_pci_probe
- * succeeded
- */
- device_set_desc(sc->sc_bus.bdev, ehci_pci_match(self));
- switch (pci_get_vendor(self)) {
- case PCI_EHCI_VENDORID_ACERLABS:
- sprintf(sc->sc_vendor, "AcerLabs");
- break;
- case PCI_EHCI_VENDORID_AMD:
- sprintf(sc->sc_vendor, "AMD");
- break;
- case PCI_EHCI_VENDORID_APPLE:
- sprintf(sc->sc_vendor, "Apple");
- break;
- case PCI_EHCI_VENDORID_ATI:
- sprintf(sc->sc_vendor, "ATI");
- break;
- case PCI_EHCI_VENDORID_CMDTECH:
- sprintf(sc->sc_vendor, "CMDTECH");
- break;
- case PCI_EHCI_VENDORID_INTEL:
- sprintf(sc->sc_vendor, "Intel");
- break;
- case PCI_EHCI_VENDORID_NEC:
- sprintf(sc->sc_vendor, "NEC");
- break;
- case PCI_EHCI_VENDORID_OPTI:
- sprintf(sc->sc_vendor, "OPTi");
- break;
- case PCI_EHCI_VENDORID_PHILIPS:
- sprintf(sc->sc_vendor, "Philips");
- break;
- case PCI_EHCI_VENDORID_SIS:
- sprintf(sc->sc_vendor, "SiS");
- break;
- case PCI_EHCI_VENDORID_NVIDIA:
- case PCI_EHCI_VENDORID_NVIDIA2:
- sprintf(sc->sc_vendor, "nVidia");
- break;
- case PCI_EHCI_VENDORID_VIA:
- sprintf(sc->sc_vendor, "VIA");
- break;
- default:
- if (bootverbose)
- device_printf(self, "(New EHCI DeviceId=0x%08x)\n",
- pci_get_devid(self));
- sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
- }
-
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl);
-#else
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl);
-#endif
- if (err) {
- device_printf(self, "Could not setup irq, %d\n", err);
- sc->sc_intr_hdl = NULL;
- goto error;
- }
- ehci_pci_takecontroller(self);
- err = ehci_init(sc);
- if (!err) {
- err = device_probe_and_attach(sc->sc_bus.bdev);
- }
- if (err) {
- device_printf(self, "USB init failed err=%d\n", err);
- goto error;
- }
- return (0);
-
-error:
- ehci_pci_detach(self);
- return (ENXIO);
-}
-
-static int
-ehci_pci_detach(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- device_t bdev;
-
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(self);
-
- pci_disable_busmaster(self);
-
- /*
- * disable interrupts that might have been switched on in ehci_init
- */
- if (sc->sc_io_res) {
- EWRITE4(sc, EHCI_USBINTR, 0);
- }
- if (sc->sc_irq_res && sc->sc_intr_hdl) {
- /*
- * only call ehci_detach() after ehci_init()
- */
- ehci_detach(sc);
-
- int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
-
- if (err)
- /* XXX or should we panic? */
- device_printf(self, "Could not tear down irq, %d\n",
- err);
- sc->sc_intr_hdl = NULL;
- }
- if (sc->sc_irq_res) {
- bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
- sc->sc_irq_res = NULL;
- }
- if (sc->sc_io_res) {
- bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM,
- sc->sc_io_res);
- sc->sc_io_res = NULL;
- }
- usb2_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
-
- return (0);
-}
-
-static void
-ehci_pci_takecontroller(device_t self)
-{
- ehci_softc_t *sc = device_get_softc(self);
- uint32_t cparams;
- uint32_t eec;
- uint16_t to;
- uint8_t eecp;
- uint8_t bios_sem;
-
- cparams = EREAD4(sc, EHCI_HCCPARAMS);
-
- /* Synchronise with the BIOS if it owns the controller. */
- for (eecp = EHCI_HCC_EECP(cparams); eecp != 0;
- eecp = EHCI_EECP_NEXT(eec)) {
- eec = pci_read_config(self, eecp, 4);
- if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) {
- continue;
- }
- bios_sem = pci_read_config(self, eecp +
- EHCI_LEGSUP_BIOS_SEM, 1);
- if (bios_sem == 0) {
- continue;
- }
- device_printf(sc->sc_bus.bdev, "waiting for BIOS "
- "to give up control\n");
- pci_write_config(self, eecp +
- EHCI_LEGSUP_OS_SEM, 1, 1);
- to = 500;
- while (1) {
- bios_sem = pci_read_config(self, eecp +
- EHCI_LEGSUP_BIOS_SEM, 1);
- if (bios_sem == 0)
- break;
-
- if (--to == 0) {
- device_printf(sc->sc_bus.bdev,
- "timed out waiting for BIOS\n");
- break;
- }
- usb2_pause_mtx(NULL, hz / 100); /* wait 10ms */
- }
- }
-}
-
-static driver_t ehci_driver =
-{
- .name = "ehci",
- .methods = (device_method_t[]){
- /* device interface */
- DEVMETHOD(device_probe, ehci_pci_probe),
- DEVMETHOD(device_attach, ehci_pci_attach),
- DEVMETHOD(device_detach, ehci_pci_detach),
- DEVMETHOD(device_suspend, ehci_pci_suspend),
- DEVMETHOD(device_resume, ehci_pci_resume),
- DEVMETHOD(device_shutdown, ehci_pci_shutdown),
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
- },
- .size = sizeof(struct ehci_softc),
-};
-
-static devclass_t ehci_devclass;
-
-DRIVER_MODULE(ehci, pci, ehci_driver, ehci_devclass, 0, 0);
-DRIVER_MODULE(ehci, cardbus, ehci_driver, ehci_devclass, 0, 0);
-MODULE_DEPEND(ehci, usb2_controller, 1, 1, 1);
-MODULE_DEPEND(ehci, usb2_core, 1, 1, 1);
diff --git a/sys/dev/usb2/controller/musb2_otg.c b/sys/dev/usb2/controller/musb2_otg.c
deleted file mode 100644
index fd6b6d3..0000000
--- a/sys/dev/usb2/controller/musb2_otg.c
+++ /dev/null
@@ -1,2875 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-/*
- * Thanks to Mentor Graphics for providing a reference driver for this
- * USB chip at their homepage.
- */
-
-/*
- * This file contains the driver for the Mentor Graphics Inventra USB
- * 2.0 High Speed Dual-Role controller.
- *
- * NOTE: The current implementation only supports Device Side Mode!
- */
-
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_defs.h>
-
-#define USB_DEBUG_VAR musbotgdebug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_transfer.h>
-#include <dev/usb2/core/usb2_device.h>
-#include <dev/usb2/core/usb2_hub.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/musb2_otg.h>
-
-#define MUSBOTG_INTR_ENDPT 1
-
-#define MUSBOTG_BUS2SC(bus) \
- ((struct musbotg_softc *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((struct musbotg_softc *)0)->sc_bus))))
-
-#define MUSBOTG_PC2SC(pc) \
- MUSBOTG_BUS2SC((pc)->tag_parent->info->bus)
-
-#if USB_DEBUG
-static int musbotgdebug = 0;
-
-SYSCTL_NODE(_hw_usb2, OID_AUTO, musbotg, CTLFLAG_RW, 0, "USB musbotg");
-SYSCTL_INT(_hw_usb2_musbotg, OID_AUTO, debug, CTLFLAG_RW,
- &musbotgdebug, 0, "Debug level");
-#endif
-
-/* prototypes */
-
-struct usb2_bus_methods musbotg_bus_methods;
-struct usb2_pipe_methods musbotg_device_bulk_methods;
-struct usb2_pipe_methods musbotg_device_ctrl_methods;
-struct usb2_pipe_methods musbotg_device_intr_methods;
-struct usb2_pipe_methods musbotg_device_isoc_methods;
-struct usb2_pipe_methods musbotg_root_ctrl_methods;
-struct usb2_pipe_methods musbotg_root_intr_methods;
-
-static musbotg_cmd_t musbotg_setup_rx;
-static musbotg_cmd_t musbotg_setup_data_rx;
-static musbotg_cmd_t musbotg_setup_data_tx;
-static musbotg_cmd_t musbotg_setup_status;
-static musbotg_cmd_t musbotg_data_rx;
-static musbotg_cmd_t musbotg_data_tx;
-static void musbotg_device_done(struct usb2_xfer *, usb2_error_t);
-static void musbotg_do_poll(struct usb2_bus *);
-static void musbotg_root_ctrl_poll(struct musbotg_softc *);
-static void musbotg_standard_done(struct usb2_xfer *);
-static void musbotg_interrupt_poll(struct musbotg_softc *);
-
-static usb2_sw_transfer_func_t musbotg_root_intr_done;
-static usb2_sw_transfer_func_t musbotg_root_ctrl_done;
-
-/*
- * Here is a configuration that the chip supports.
- */
-static const struct usb2_hw_ep_profile musbotg_ep_profile[1] = {
-
- [0] = {
- .max_in_frame_size = 64,/* fixed */
- .max_out_frame_size = 64, /* fixed */
- .is_simplex = 1,
- .support_control = 1,
- }
-};
-
-static void
-musbotg_get_hw_ep_profile(struct usb2_device *udev,
- const struct usb2_hw_ep_profile **ppf, uint8_t ep_addr)
-{
- struct musbotg_softc *sc;
-
- sc = MUSBOTG_BUS2SC(udev->bus);
-
- if (ep_addr == 0) {
- /* control endpoint */
- *ppf = musbotg_ep_profile;
- } else if (ep_addr <= sc->sc_ep_max) {
- /* other endpoints */
- *ppf = sc->sc_hw_ep_profile + ep_addr;
- } else {
- *ppf = NULL;
- }
-}
-
-static void
-musbotg_clocks_on(struct musbotg_softc *sc)
-{
- if (sc->sc_flags.clocks_off &&
- sc->sc_flags.port_powered) {
-
- DPRINTFN(4, "\n");
-
- if (sc->sc_clocks_on) {
- (sc->sc_clocks_on) (sc->sc_clocks_arg);
- }
- sc->sc_flags.clocks_off = 0;
-
- /* XXX enable Transceiver */
- }
-}
-
-static void
-musbotg_clocks_off(struct musbotg_softc *sc)
-{
- if (!sc->sc_flags.clocks_off) {
-
- DPRINTFN(4, "\n");
-
- /* XXX disable Transceiver */
-
- if (sc->sc_clocks_off) {
- (sc->sc_clocks_off) (sc->sc_clocks_arg);
- }
- sc->sc_flags.clocks_off = 1;
- }
-}
-
-static void
-musbotg_pull_common(struct musbotg_softc *sc, uint8_t on)
-{
- uint8_t temp;
-
- temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
- if (on)
- temp |= MUSB2_MASK_SOFTC;
- else
- temp &= ~MUSB2_MASK_SOFTC;
-
- MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
-}
-
-static void
-musbotg_pull_up(struct musbotg_softc *sc)
-{
- /* pullup D+, if possible */
-
- if (!sc->sc_flags.d_pulled_up &&
- sc->sc_flags.port_powered) {
- sc->sc_flags.d_pulled_up = 1;
- musbotg_pull_common(sc, 1);
- }
-}
-
-static void
-musbotg_pull_down(struct musbotg_softc *sc)
-{
- /* pulldown D+, if possible */
-
- if (sc->sc_flags.d_pulled_up) {
- sc->sc_flags.d_pulled_up = 0;
- musbotg_pull_common(sc, 0);
- }
-}
-
-static void
-musbotg_wakeup_peer(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
- uint8_t temp;
- uint8_t use_polling;
-
- if (!(sc->sc_flags.status_suspend)) {
- return;
- }
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
- temp |= MUSB2_MASK_RESUME;
- MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
-
- /* wait 8 milliseconds */
- if (use_polling) {
- /* polling */
- DELAY(8000);
- } else {
- /* Wait for reset to complete. */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 125);
- }
-
- temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
- temp &= ~MUSB2_MASK_RESUME;
- MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
-}
-
-static void
-musbotg_set_address(struct musbotg_softc *sc, uint8_t addr)
-{
- DPRINTFN(4, "addr=%d\n", addr);
- addr &= 0x7F;
- MUSB2_WRITE_1(sc, MUSB2_REG_FADDR, addr);
-}
-
-static uint8_t
-musbotg_setup_rx(struct musbotg_td *td)
-{
- struct musbotg_softc *sc;
- struct usb2_device_request req;
- uint16_t count;
- uint8_t csr;
-
- /* get pointer to softc */
- sc = MUSBOTG_PC2SC(td->pc);
-
- /* select endpoint 0 */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
-
- /* read out FIFO status */
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
-
- DPRINTFN(4, "csr=0x%02x\n", csr);
-
- /*
- * NOTE: If DATAEND is set we should not call the
- * callback, hence the status stage is not complete.
- */
- if (csr & MUSB2_MASK_CSR0L_DATAEND) {
- /* wait for interrupt */
- goto not_complete;
- }
- if (csr & MUSB2_MASK_CSR0L_SENTSTALL) {
- /* clear SENTSTALL */
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
- /* get latest status */
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
- /* update EP0 state */
- sc->sc_ep0_busy = 0;
- }
- if (csr & MUSB2_MASK_CSR0L_SETUPEND) {
- /* clear SETUPEND */
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSR0L_SETUPEND_CLR);
- /* get latest status */
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
- /* update EP0 state */
- sc->sc_ep0_busy = 0;
- }
- if (sc->sc_ep0_busy) {
- /* abort any ongoing transfer */
- if (!td->did_stall) {
- DPRINTFN(4, "stalling\n");
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSR0L_SENDSTALL);
- td->did_stall = 1;
- }
- goto not_complete;
- }
- if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY)) {
- goto not_complete;
- }
- /* get the packet byte count */
- count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
-
- /* verify data length */
- if (count != td->remainder) {
- DPRINTFN(0, "Invalid SETUP packet "
- "length, %d bytes\n", count);
- goto not_complete;
- }
- if (count != sizeof(req)) {
- DPRINTFN(0, "Unsupported SETUP packet "
- "length, %d bytes\n", count);
- goto not_complete;
- }
- /* receive data */
- bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(0), (void *)&req, sizeof(req));
-
- /* copy data into real buffer */
- usb2_copy_in(td->pc, 0, &req, sizeof(req));
-
- td->offset = sizeof(req);
- td->remainder = 0;
-
- /* set pending command */
- sc->sc_ep0_cmd = MUSB2_MASK_CSR0L_RXPKTRDY_CLR;
-
- /* we need set stall or dataend after this */
- sc->sc_ep0_busy = 1;
-
- /* sneak peek the set address */
- if ((req.bmRequestType == UT_WRITE_DEVICE) &&
- (req.bRequest == UR_SET_ADDRESS)) {
- sc->sc_dv_addr = req.wValue[0] & 0x7F;
- } else {
- sc->sc_dv_addr = 0xFF;
- }
- return (0); /* complete */
-
-not_complete:
- return (1); /* not complete */
-}
-
-/* Control endpoint only data handling functions (RX/TX/SYNC) */
-
-static uint8_t
-musbotg_setup_data_rx(struct musbotg_td *td)
-{
- struct usb2_page_search buf_res;
- struct musbotg_softc *sc;
- uint16_t count;
- uint8_t csr;
- uint8_t got_short;
-
- /* get pointer to softc */
- sc = MUSBOTG_PC2SC(td->pc);
-
- /* select endpoint 0 */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
-
- /* check if a command is pending */
- if (sc->sc_ep0_cmd) {
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, sc->sc_ep0_cmd);
- sc->sc_ep0_cmd = 0;
- }
- /* read out FIFO status */
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
-
- DPRINTFN(4, "csr=0x%02x\n", csr);
-
- got_short = 0;
-
- if (csr & (MUSB2_MASK_CSR0L_SETUPEND |
- MUSB2_MASK_CSR0L_SENTSTALL)) {
- if (td->remainder == 0) {
- /*
- * We are actually complete and have
- * received the next SETUP
- */
- DPRINTFN(4, "faking complete\n");
- return (0); /* complete */
- }
- /*
- * USB Host Aborted the transfer.
- */
- td->error = 1;
- return (0); /* complete */
- }
- if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY)) {
- return (1); /* not complete */
- }
- /* get the packet byte count */
- count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
-
- /* verify the packet byte count */
- if (count != td->max_frame_size) {
- if (count < td->max_frame_size) {
- /* we have a short packet */
- td->short_pkt = 1;
- got_short = 1;
- } else {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- }
- /* verify the packet byte count */
- if (count > td->remainder) {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- while (count > 0) {
- uint32_t temp;
-
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* check for unaligned memory address */
- if (USB_P2U(buf_res.buffer) & 3) {
-
- temp = count & ~3;
-
- if (temp) {
- /* receive data 4 bytes at a time */
- bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(0), sc->sc_bounce_buf,
- temp / 4);
- }
- temp = count & 3;
- if (temp) {
- /* receive data 1 byte at a time */
- bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(0),
- (void *)(&sc->sc_bounce_buf[count / 4]), temp);
- }
- usb2_copy_in(td->pc, td->offset,
- sc->sc_bounce_buf, count);
-
- /* update offset and remainder */
- td->offset += count;
- td->remainder -= count;
- break;
- }
- /* check if we can optimise */
- if (buf_res.length >= 4) {
-
- /* receive data 4 bytes at a time */
- bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(0), buf_res.buffer,
- buf_res.length / 4);
-
- temp = buf_res.length & ~3;
-
- /* update counters */
- count -= temp;
- td->offset += temp;
- td->remainder -= temp;
- continue;
- }
- /* receive data */
- bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(0), buf_res.buffer, buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* check if we are complete */
- if ((td->remainder == 0) || got_short) {
- if (td->short_pkt) {
- /* we are complete */
- sc->sc_ep0_cmd = MUSB2_MASK_CSR0L_RXPKTRDY_CLR;
- return (0);
- }
- /* else need to receive a zero length packet */
- }
- /* write command - need more data */
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
- return (1); /* not complete */
-}
-
-static uint8_t
-musbotg_setup_data_tx(struct musbotg_td *td)
-{
- struct usb2_page_search buf_res;
- struct musbotg_softc *sc;
- uint16_t count;
- uint8_t csr;
-
- /* get pointer to softc */
- sc = MUSBOTG_PC2SC(td->pc);
-
- /* select endpoint 0 */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
-
- /* check if a command is pending */
- if (sc->sc_ep0_cmd) {
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, sc->sc_ep0_cmd);
- sc->sc_ep0_cmd = 0;
- }
- /* read out FIFO status */
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
-
- DPRINTFN(4, "csr=0x%02x\n", csr);
-
- if (csr & (MUSB2_MASK_CSR0L_SETUPEND |
- MUSB2_MASK_CSR0L_SENTSTALL)) {
- /*
- * The current transfer was aborted
- * by the USB Host
- */
- td->error = 1;
- return (0); /* complete */
- }
- if (csr & MUSB2_MASK_CSR0L_TXPKTRDY) {
- return (1); /* not complete */
- }
- count = td->max_frame_size;
- if (td->remainder < count) {
- /* we have a short packet */
- td->short_pkt = 1;
- count = td->remainder;
- }
- while (count > 0) {
- uint32_t temp;
-
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* check for unaligned memory address */
- if (USB_P2U(buf_res.buffer) & 3) {
-
- usb2_copy_out(td->pc, td->offset,
- sc->sc_bounce_buf, count);
-
- temp = count & ~3;
-
- if (temp) {
- /* transmit data 4 bytes at a time */
- bus_space_write_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(0), sc->sc_bounce_buf,
- temp / 4);
- }
- temp = count & 3;
- if (temp) {
- /* receive data 1 byte at a time */
- bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(0),
- ((void *)&sc->sc_bounce_buf[count / 4]), temp);
- }
- /* update offset and remainder */
- td->offset += count;
- td->remainder -= count;
- break;
- }
- /* check if we can optimise */
- if (buf_res.length >= 4) {
-
- /* transmit data 4 bytes at a time */
- bus_space_write_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(0), buf_res.buffer,
- buf_res.length / 4);
-
- temp = buf_res.length & ~3;
-
- /* update counters */
- count -= temp;
- td->offset += temp;
- td->remainder -= temp;
- continue;
- }
- /* transmit data */
- bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(0), buf_res.buffer, buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* check remainder */
- if (td->remainder == 0) {
- if (td->short_pkt) {
- sc->sc_ep0_cmd = MUSB2_MASK_CSR0L_TXPKTRDY;
- return (0); /* complete */
- }
- /* else we need to transmit a short packet */
- }
- /* write command */
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSR0L_TXPKTRDY);
-
- return (1); /* not complete */
-}
-
-static uint8_t
-musbotg_setup_status(struct musbotg_td *td)
-{
- struct musbotg_softc *sc;
- uint8_t csr;
-
- /* get pointer to softc */
- sc = MUSBOTG_PC2SC(td->pc);
-
- /* select endpoint 0 */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
-
- if (sc->sc_ep0_busy) {
- sc->sc_ep0_busy = 0;
- sc->sc_ep0_cmd |= MUSB2_MASK_CSR0L_DATAEND;
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, sc->sc_ep0_cmd);
- sc->sc_ep0_cmd = 0;
- }
- /* read out FIFO status */
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
-
- DPRINTFN(4, "csr=0x%02x\n", csr);
-
- if (csr & MUSB2_MASK_CSR0L_DATAEND) {
- /* wait for interrupt */
- return (1); /* not complete */
- }
- if (sc->sc_dv_addr != 0xFF) {
- /* write function address */
- musbotg_set_address(sc, sc->sc_dv_addr);
- }
- return (0); /* complete */
-}
-
-static uint8_t
-musbotg_data_rx(struct musbotg_td *td)
-{
- struct usb2_page_search buf_res;
- struct musbotg_softc *sc;
- uint16_t count;
- uint8_t csr;
- uint8_t to;
- uint8_t got_short;
-
- to = 8; /* don't loop forever! */
- got_short = 0;
-
- /* get pointer to softc */
- sc = MUSBOTG_PC2SC(td->pc);
-
- /* select endpoint */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->ep_no);
-
-repeat:
- /* read out FIFO status */
- csr = MUSB2_READ_1(sc, MUSB2_REG_RXCSRL);
-
- DPRINTFN(4, "csr=0x%02x\n", csr);
-
- /* clear overrun */
- if (csr & MUSB2_MASK_CSRL_RXOVERRUN) {
- /* make sure we don't clear "RXPKTRDY" */
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL,
- MUSB2_MASK_CSRL_RXPKTRDY);
- }
- /* check status */
- if (!(csr & MUSB2_MASK_CSRL_RXPKTRDY)) {
- return (1); /* not complete */
- }
- /* get the packet byte count */
- count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
-
- DPRINTFN(4, "count=0x%04x\n", count);
-
- /*
- * Check for short or invalid packet:
- */
- if (count != td->max_frame_size) {
- if (count < td->max_frame_size) {
- /* we have a short packet */
- td->short_pkt = 1;
- got_short = 1;
- } else {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- }
- /* verify the packet byte count */
- if (count > td->remainder) {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- while (count > 0) {
- uint32_t temp;
-
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* check for unaligned memory address */
- if (USB_P2U(buf_res.buffer) & 3) {
-
- temp = count & ~3;
-
- if (temp) {
- /* receive data 4 bytes at a time */
- bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), sc->sc_bounce_buf,
- temp / 4);
- }
- temp = count & 3;
- if (temp) {
- /* receive data 1 byte at a time */
- bus_space_read_multi_1(sc->sc_io_tag,
- sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->ep_no),
- ((void *)&sc->sc_bounce_buf[count / 4]), temp);
- }
- usb2_copy_in(td->pc, td->offset,
- sc->sc_bounce_buf, count);
-
- /* update offset and remainder */
- td->offset += count;
- td->remainder -= count;
- break;
- }
- /* check if we can optimise */
- if (buf_res.length >= 4) {
-
- /* receive data 4 bytes at a time */
- bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
- buf_res.length / 4);
-
- temp = buf_res.length & ~3;
-
- /* update counters */
- count -= temp;
- td->offset += temp;
- td->remainder -= temp;
- continue;
- }
- /* receive data */
- bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
- buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* clear status bits */
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL, 0);
-
- /* check if we are complete */
- if ((td->remainder == 0) || got_short) {
- if (td->short_pkt) {
- /* we are complete */
- return (0);
- }
- /* else need to receive a zero length packet */
- }
- if (--to) {
- goto repeat;
- }
- return (1); /* not complete */
-}
-
-static uint8_t
-musbotg_data_tx(struct musbotg_td *td)
-{
- struct usb2_page_search buf_res;
- struct musbotg_softc *sc;
- uint16_t count;
- uint8_t csr;
- uint8_t to;
-
- to = 8; /* don't loop forever! */
-
- /* get pointer to softc */
- sc = MUSBOTG_PC2SC(td->pc);
-
- /* select endpoint */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->ep_no);
-
-repeat:
-
- /* read out FIFO status */
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
-
- DPRINTFN(4, "csr=0x%02x\n", csr);
-
- if (csr & (MUSB2_MASK_CSRL_TXINCOMP |
- MUSB2_MASK_CSRL_TXUNDERRUN)) {
- /* clear status bits */
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
- }
- if (csr & MUSB2_MASK_CSRL_TXPKTRDY) {
- return (1); /* not complete */
- }
- /* check for short packet */
- count = td->max_frame_size;
- if (td->remainder < count) {
- /* we have a short packet */
- td->short_pkt = 1;
- count = td->remainder;
- }
- while (count > 0) {
- uint32_t temp;
-
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* check for unaligned memory address */
- if (USB_P2U(buf_res.buffer) & 3) {
-
- usb2_copy_out(td->pc, td->offset,
- sc->sc_bounce_buf, count);
-
- temp = count & ~3;
-
- if (temp) {
- /* transmit data 4 bytes at a time */
- bus_space_write_multi_4(sc->sc_io_tag,
- sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->ep_no),
- sc->sc_bounce_buf, temp / 4);
- }
- temp = count & 3;
- if (temp) {
- /* receive data 1 byte at a time */
- bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no),
- ((void *)&sc->sc_bounce_buf[count / 4]), temp);
- }
- /* update offset and remainder */
- td->offset += count;
- td->remainder -= count;
- break;
- }
- /* check if we can optimise */
- if (buf_res.length >= 4) {
-
- /* transmit data 4 bytes at a time */
- bus_space_write_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
- buf_res.length / 4);
-
- temp = buf_res.length & ~3;
-
- /* update counters */
- count -= temp;
- td->offset += temp;
- td->remainder -= temp;
- continue;
- }
- /* transmit data */
- bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
- buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* write command */
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSRL_TXPKTRDY);
-
- /* check remainder */
- if (td->remainder == 0) {
- if (td->short_pkt) {
- return (0); /* complete */
- }
- /* else we need to transmit a short packet */
- }
- if (--to) {
- goto repeat;
- }
- return (1); /* not complete */
-}
-
-static uint8_t
-musbotg_xfer_do_fifo(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc;
- struct musbotg_td *td;
-
- DPRINTFN(8, "\n");
-
- td = xfer->td_transfer_cache;
- while (1) {
- if ((td->func) (td)) {
- /* operation in progress */
- break;
- }
- if (((void *)td) == xfer->td_transfer_last) {
- goto done;
- }
- if (td->error) {
- goto done;
- } else if (td->remainder > 0) {
- /*
- * We had a short transfer. If there is no alternate
- * next, stop processing !
- */
- if (!td->alt_next) {
- goto done;
- }
- }
- /*
- * Fetch the next transfer descriptor and transfer
- * some flags to the next transfer descriptor
- */
- td = td->obj_next;
- xfer->td_transfer_cache = td;
- }
- return (1); /* not complete */
-
-done:
- sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- /* compute all actual lengths */
-
- musbotg_standard_done(xfer);
-
- return (0); /* complete */
-}
-
-static void
-musbotg_interrupt_poll(struct musbotg_softc *sc)
-{
- struct usb2_xfer *xfer;
-
-repeat:
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- if (!musbotg_xfer_do_fifo(xfer)) {
- /* queue has been modified */
- goto repeat;
- }
- }
-}
-
-void
-musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on)
-{
- DPRINTFN(4, "vbus = %u\n", is_on);
-
- USB_BUS_LOCK(&sc->sc_bus);
- if (is_on) {
- if (!sc->sc_flags.status_vbus) {
- sc->sc_flags.status_vbus = 1;
-
- /* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &musbotg_root_intr_done);
- }
- } else {
- if (sc->sc_flags.status_vbus) {
- sc->sc_flags.status_vbus = 0;
- sc->sc_flags.status_bus_reset = 0;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- /* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &musbotg_root_intr_done);
- }
- }
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-void
-musbotg_interrupt(struct musbotg_softc *sc)
-{
- uint16_t rx_status;
- uint16_t tx_status;
- uint8_t usb_status;
- uint8_t temp;
- uint8_t to = 2;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
-repeat:
-
- /* read all interrupt registers */
- usb_status = MUSB2_READ_1(sc, MUSB2_REG_INTUSB);
-
- /* read all FIFO interrupts */
- rx_status = MUSB2_READ_2(sc, MUSB2_REG_INTRX);
- tx_status = MUSB2_READ_2(sc, MUSB2_REG_INTTX);
-
- /* check for any bus state change interrupts */
-
- if (usb_status & (MUSB2_MASK_IRESET |
- MUSB2_MASK_IRESUME | MUSB2_MASK_ISUSP)) {
-
- DPRINTFN(4, "real bus interrupt 0x%08x\n", usb_status);
-
- if (usb_status & MUSB2_MASK_IRESET) {
-
- /* set correct state */
- sc->sc_flags.status_bus_reset = 1;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- /* determine line speed */
- temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
- if (temp & MUSB2_MASK_HSMODE)
- sc->sc_flags.status_high_speed = 1;
- else
- sc->sc_flags.status_high_speed = 0;
-
- /*
- * After reset all interrupts are on and we need to
- * turn them off!
- */
- temp = MUSB2_MASK_IRESET;
- /* disable resume interrupt */
- temp &= ~MUSB2_MASK_IRESUME;
- /* enable suspend interrupt */
- temp |= MUSB2_MASK_ISUSP;
- MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, temp);
- /* disable TX and RX interrupts */
- MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, 0);
- MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, 0);
- }
- /*
- * If RXRSM and RXSUSP is set at the same time we interpret
- * that like RESUME. Resume is set when there is at least 3
- * milliseconds of inactivity on the USB BUS.
- */
- if (usb_status & MUSB2_MASK_IRESUME) {
- if (sc->sc_flags.status_suspend) {
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 1;
-
- temp = MUSB2_READ_1(sc, MUSB2_REG_INTUSBE);
- /* disable resume interrupt */
- temp &= ~MUSB2_MASK_IRESUME;
- /* enable suspend interrupt */
- temp |= MUSB2_MASK_ISUSP;
- MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, temp);
- }
- } else if (usb_status & MUSB2_MASK_ISUSP) {
- if (!sc->sc_flags.status_suspend) {
- sc->sc_flags.status_suspend = 1;
- sc->sc_flags.change_suspend = 1;
-
- temp = MUSB2_READ_1(sc, MUSB2_REG_INTUSBE);
- /* disable suspend interrupt */
- temp &= ~MUSB2_MASK_ISUSP;
- /* enable resume interrupt */
- temp |= MUSB2_MASK_IRESUME;
- MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, temp);
- }
- }
- /* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &musbotg_root_intr_done);
- }
- /* check for any endpoint interrupts */
-
- if (rx_status || tx_status) {
- DPRINTFN(4, "real endpoint interrupt "
- "rx=0x%04x, tx=0x%04x\n", rx_status, tx_status);
- }
- /* poll one time regardless of FIFO status */
-
- musbotg_interrupt_poll(sc);
-
- if (--to)
- goto repeat;
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-static void
-musbotg_setup_standard_chain_sub(struct musbotg_std_temp *temp)
-{
- struct musbotg_td *td;
-
- /* get current Transfer Descriptor */
- td = temp->td_next;
- temp->td = td;
-
- /* prepare for next TD */
- temp->td_next = td->obj_next;
-
- /* fill out the Transfer Descriptor */
- td->func = temp->func;
- td->pc = temp->pc;
- td->offset = temp->offset;
- td->remainder = temp->len;
- td->error = 0;
- td->did_stall = 0;
- td->short_pkt = temp->short_pkt;
- td->alt_next = temp->setup_alt_next;
-}
-
-static void
-musbotg_setup_standard_chain(struct usb2_xfer *xfer)
-{
- struct musbotg_std_temp temp;
- struct musbotg_softc *sc;
- struct musbotg_td *td;
- uint32_t x;
- uint8_t ep_no;
-
- DPRINTFN(8, "addr=%d endpt=%d sumlen=%d speed=%d\n",
- xfer->address, UE_GET_ADDR(xfer->endpoint),
- xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
-
- temp.max_frame_size = xfer->max_frame_size;
-
- td = xfer->td_start[0];
- xfer->td_transfer_first = td;
- xfer->td_transfer_cache = td;
-
- /* setup temp */
-
- temp.td = NULL;
- temp.td_next = xfer->td_start[0];
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.offset = 0;
-
- sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
- ep_no = (xfer->endpoint & UE_ADDR);
-
- /* check if we should prepend a setup message */
-
- if (xfer->flags_int.control_xfr) {
- if (xfer->flags_int.control_hdr) {
-
- temp.func = &musbotg_setup_rx;
- temp.len = xfer->frlengths[0];
- temp.pc = xfer->frbuffers + 0;
- temp.short_pkt = temp.len ? 1 : 0;
-
- musbotg_setup_standard_chain_sub(&temp);
- }
- x = 1;
- } else {
- x = 0;
- }
-
- if (x != xfer->nframes) {
- if (xfer->endpoint & UE_DIR_IN) {
- if (xfer->flags_int.control_xfr)
- temp.func = &musbotg_setup_data_tx;
- else
- temp.func = &musbotg_data_tx;
- } else {
- if (xfer->flags_int.control_xfr)
- temp.func = &musbotg_setup_data_rx;
- else
- temp.func = &musbotg_data_rx;
- }
-
- /* setup "pc" pointer */
- temp.pc = xfer->frbuffers + x;
- }
- while (x != xfer->nframes) {
-
- /* DATA0 / DATA1 message */
-
- temp.len = xfer->frlengths[x];
-
- x++;
-
- if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
- }
- if (temp.len == 0) {
-
- /* make sure that we send an USB packet */
-
- temp.short_pkt = 0;
-
- } else {
-
- /* regular data transfer */
-
- temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1;
- }
-
- musbotg_setup_standard_chain_sub(&temp);
-
- if (xfer->flags_int.isochronous_xfr) {
- temp.offset += temp.len;
- } else {
- /* get next Page Cache pointer */
- temp.pc = xfer->frbuffers + x;
- }
- }
-
- /* always setup a valid "pc" pointer for status and sync */
- temp.pc = xfer->frbuffers + 0;
-
- /* check if we should append a status stage */
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- /*
- * Send a DATA1 message and invert the current
- * endpoint direction.
- */
- temp.func = &musbotg_setup_status;
- temp.len = 0;
- temp.short_pkt = 0;
-
- musbotg_setup_standard_chain_sub(&temp);
- }
- /* must have at least one frame! */
- td = temp.td;
- xfer->td_transfer_last = td;
-}
-
-static void
-musbotg_timeout(void *arg)
-{
- struct usb2_xfer *xfer = arg;
-
- DPRINTFN(1, "xfer=%p\n", xfer);
-
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- /* transfer is transferred */
- musbotg_device_done(xfer, USB_ERR_TIMEOUT);
-}
-
-static void
-musbotg_ep_int_set(struct usb2_xfer *xfer, uint8_t on)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
- uint16_t temp;
- uint8_t ep_no = xfer->endpoint & UE_ADDR;
-
- /*
- * Only enable the endpoint interrupt when we are
- * actually waiting for data, hence we are dealing
- * with level triggered interrupts !
- */
- if (ep_no == 0) {
- temp = MUSB2_READ_2(sc, MUSB2_REG_INTTXE);
- if (on)
- temp |= MUSB2_MASK_EPINT(0);
- else
- temp &= ~MUSB2_MASK_EPINT(0);
-
- MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, temp);
- } else {
- if (USB_GET_DATA_ISREAD(xfer)) {
- temp = MUSB2_READ_2(sc, MUSB2_REG_INTRXE);
- if (on)
- temp |= MUSB2_MASK_EPINT(ep_no);
- else
- temp &= ~MUSB2_MASK_EPINT(ep_no);
- MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, temp);
-
- } else {
- temp = MUSB2_READ_2(sc, MUSB2_REG_INTTXE);
- if (on)
- temp |= MUSB2_MASK_EPINT(ep_no);
- else
- temp &= ~MUSB2_MASK_EPINT(ep_no);
- MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, temp);
- }
- }
-}
-
-static void
-musbotg_start_standard_chain(struct usb2_xfer *xfer)
-{
- DPRINTFN(8, "\n");
-
- /* poll one time */
- if (musbotg_xfer_do_fifo(xfer)) {
-
- musbotg_ep_int_set(xfer, 1);
-
- DPRINTFN(14, "enabled interrupts on endpoint\n");
-
- /* put transfer on interrupt queue */
- usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
-
- /* start timeout, if any */
- if (xfer->timeout != 0) {
- usb2_transfer_timeout_ms(xfer,
- &musbotg_timeout, xfer->timeout);
- }
- }
-}
-
-static void
-musbotg_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- DPRINTFN(8, "\n");
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- musbotg_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
- /* set port bit */
- sc->sc_hub_idata[0] = 0x02; /* we only have one port */
-
-done:
- return;
-}
-
-static usb2_error_t
-musbotg_standard_done_sub(struct usb2_xfer *xfer)
-{
- struct musbotg_td *td;
- uint32_t len;
- uint8_t error;
-
- DPRINTFN(8, "\n");
-
- td = xfer->td_transfer_cache;
-
- do {
- len = td->remainder;
-
- if (xfer->aframes != xfer->nframes) {
- /*
- * Verify the length and subtract
- * the remainder from "frlengths[]":
- */
- if (len > xfer->frlengths[xfer->aframes]) {
- td->error = 1;
- } else {
- xfer->frlengths[xfer->aframes] -= len;
- }
- }
- /* Check for transfer error */
- if (td->error) {
- /* the transfer is finished */
- error = 1;
- td = NULL;
- break;
- }
- /* Check for short transfer */
- if (len > 0) {
- if (xfer->flags_int.short_frames_ok) {
- /* follow alt next */
- if (td->alt_next) {
- td = td->obj_next;
- } else {
- td = NULL;
- }
- } else {
- /* the transfer is finished */
- td = NULL;
- }
- error = 0;
- break;
- }
- td = td->obj_next;
-
- /* this USB frame is complete */
- error = 0;
- break;
-
- } while (0);
-
- /* update transfer cache */
-
- xfer->td_transfer_cache = td;
-
- return (error ?
- USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION);
-}
-
-static void
-musbotg_standard_done(struct usb2_xfer *xfer)
-{
- usb2_error_t err = 0;
-
- DPRINTFN(12, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
- /* reset scanner */
-
- xfer->td_transfer_cache = xfer->td_transfer_first;
-
- if (xfer->flags_int.control_xfr) {
-
- if (xfer->flags_int.control_hdr) {
-
- err = musbotg_standard_done_sub(xfer);
- }
- xfer->aframes = 1;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
- while (xfer->aframes != xfer->nframes) {
-
- err = musbotg_standard_done_sub(xfer);
- xfer->aframes++;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- err = musbotg_standard_done_sub(xfer);
- }
-done:
- musbotg_device_done(xfer, err);
-}
-
-/*------------------------------------------------------------------------*
- * musbotg_device_done
- *
- * NOTE: this function can be called more than one time on the
- * same USB transfer!
- *------------------------------------------------------------------------*/
-static void
-musbotg_device_done(struct usb2_xfer *xfer, usb2_error_t error)
-{
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
- xfer, xfer->pipe, error);
-
- if (xfer->flags_int.usb2_mode == USB_MODE_DEVICE) {
-
- musbotg_ep_int_set(xfer, 0);
-
- DPRINTFN(14, "disabled interrupts on endpoint\n");
- }
- /* dequeue transfer and start next transfer */
- usb2_transfer_done(xfer, error);
-}
-
-static void
-musbotg_set_stall(struct usb2_device *udev, struct usb2_xfer *xfer,
- struct usb2_pipe *pipe)
-{
- struct musbotg_softc *sc;
- uint8_t ep_no;
-
- USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
-
- DPRINTFN(4, "pipe=%p\n", pipe);
-
- if (xfer) {
- /* cancel any ongoing transfers */
- musbotg_device_done(xfer, USB_ERR_STALLED);
- }
- /* set FORCESTALL */
- sc = MUSBOTG_BUS2SC(udev->bus);
-
- ep_no = (pipe->edesc->bEndpointAddress & UE_ADDR);
-
- /* select endpoint */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, ep_no);
-
- if (pipe->edesc->bEndpointAddress & UE_DIR_IN) {
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSRL_TXSENDSTALL);
- } else {
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL,
- MUSB2_MASK_CSRL_RXSENDSTALL);
- }
-}
-
-static void
-musbotg_clear_stall_sub(struct musbotg_softc *sc, uint16_t wMaxPacket,
- uint8_t ep_no, uint8_t ep_type, uint8_t ep_dir)
-{
- uint16_t mps;
- uint16_t temp;
- uint8_t csr;
-
- if (ep_type == UE_CONTROL) {
- /* clearing stall is not needed */
- return;
- }
- /* select endpoint */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, ep_no);
-
- /* compute max frame size */
- mps = wMaxPacket & 0x7FF;
- switch ((wMaxPacket >> 11) & 3) {
- case 1:
- mps *= 2;
- break;
- case 2:
- mps *= 3;
- break;
- default:
- break;
- }
-
- if (ep_dir == UE_DIR_IN) {
-
- temp = 0;
-
- /* Configure endpoint */
- switch (ep_type) {
- case UE_INTERRUPT:
- MUSB2_WRITE_1(sc, MUSB2_REG_TXMAXP, wMaxPacket);
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH,
- MUSB2_MASK_CSRH_TXMODE | temp);
- break;
- case UE_ISOCHRONOUS:
- MUSB2_WRITE_1(sc, MUSB2_REG_TXMAXP, wMaxPacket);
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH,
- MUSB2_MASK_CSRH_TXMODE |
- MUSB2_MASK_CSRH_TXISO | temp);
- break;
- case UE_BULK:
- MUSB2_WRITE_1(sc, MUSB2_REG_TXMAXP, wMaxPacket);
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH,
- MUSB2_MASK_CSRH_TXMODE | temp);
- break;
- default:
- break;
- }
-
- /* Need to flush twice in case of double bufring */
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
- if (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSRL_TXFFLUSH);
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
- if (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSRL_TXFFLUSH);
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
- }
- }
- /* reset data toggle */
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSRL_TXDT_CLR);
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
-
- /* set double/single buffering */
- temp = MUSB2_READ_2(sc, MUSB2_REG_TXDBDIS);
- if (mps <= (sc->sc_hw_ep_profile[ep_no].
- max_in_frame_size / 2)) {
- /* double buffer */
- temp &= ~(1 << ep_no);
- } else {
- /* single buffer */
- temp |= (1 << ep_no);
- }
- MUSB2_WRITE_2(sc, MUSB2_REG_TXDBDIS, temp);
-
- /* clear sent stall */
- if (csr & MUSB2_MASK_CSRL_TXSENTSTALL) {
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
- csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
- }
- } else {
-
- temp = 0;
-
- /* Configure endpoint */
- switch (ep_type) {
- case UE_INTERRUPT:
- MUSB2_WRITE_1(sc, MUSB2_REG_RXMAXP, wMaxPacket);
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRH,
- MUSB2_MASK_CSRH_RXNYET | temp);
- break;
- case UE_ISOCHRONOUS:
- MUSB2_WRITE_1(sc, MUSB2_REG_RXMAXP, wMaxPacket);
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRH,
- MUSB2_MASK_CSRH_RXNYET |
- MUSB2_MASK_CSRH_RXISO | temp);
- break;
- case UE_BULK:
- MUSB2_WRITE_1(sc, MUSB2_REG_RXMAXP, wMaxPacket);
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRH, temp);
- break;
- default:
- break;
- }
-
- /* Need to flush twice in case of double bufring */
- csr = MUSB2_READ_1(sc, MUSB2_REG_RXCSRL);
- if (csr & MUSB2_MASK_CSRL_RXPKTRDY) {
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL,
- MUSB2_MASK_CSRL_RXFFLUSH);
- csr = MUSB2_READ_1(sc, MUSB2_REG_RXCSRL);
- if (csr & MUSB2_MASK_CSRL_RXPKTRDY) {
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL,
- MUSB2_MASK_CSRL_RXFFLUSH);
- csr = MUSB2_READ_1(sc, MUSB2_REG_RXCSRL);
- }
- }
- /* reset data toggle */
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL,
- MUSB2_MASK_CSRL_RXDT_CLR);
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL, 0);
- csr = MUSB2_READ_1(sc, MUSB2_REG_RXCSRL);
-
- /* set double/single buffering */
- temp = MUSB2_READ_2(sc, MUSB2_REG_RXDBDIS);
- if (mps <= (sc->sc_hw_ep_profile[ep_no].
- max_out_frame_size / 2)) {
- /* double buffer */
- temp &= ~(1 << ep_no);
- } else {
- /* single buffer */
- temp |= (1 << ep_no);
- }
- MUSB2_WRITE_2(sc, MUSB2_REG_RXDBDIS, temp);
-
- /* clear sent stall */
- if (csr & MUSB2_MASK_CSRL_RXSENTSTALL) {
- MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL, 0);
- }
- }
-}
-
-static void
-musbotg_clear_stall(struct usb2_device *udev, struct usb2_pipe *pipe)
-{
- struct musbotg_softc *sc;
- struct usb2_endpoint_descriptor *ed;
-
- DPRINTFN(4, "pipe=%p\n", pipe);
-
- USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
-
- /* check mode */
- if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
- /* get softc */
- sc = MUSBOTG_BUS2SC(udev->bus);
-
- /* get endpoint descriptor */
- ed = pipe->edesc;
-
- /* reset endpoint */
- musbotg_clear_stall_sub(sc,
- UGETW(ed->wMaxPacketSize),
- (ed->bEndpointAddress & UE_ADDR),
- (ed->bmAttributes & UE_XFERTYPE),
- (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT)));
-}
-
-usb2_error_t
-musbotg_init(struct musbotg_softc *sc)
-{
- struct usb2_hw_ep_profile *pf;
- uint8_t nrx;
- uint8_t ntx;
- uint8_t temp;
- uint8_t fsize;
- uint8_t frx;
- uint8_t ftx;
-
- DPRINTFN(1, "start\n");
-
- /* set up the bus structure */
- sc->sc_bus.usbrev = USB_REV_2_0;
- sc->sc_bus.methods = &musbotg_bus_methods;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* turn on clocks */
-
- if (sc->sc_clocks_on) {
- (sc->sc_clocks_on) (sc->sc_clocks_arg);
- }
- /* wait a little for things to stabilise */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
-
- /* disable all interrupts */
-
- MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, 0);
- MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, 0);
- MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, 0);
-
- /* disable pullup */
-
- musbotg_pull_common(sc, 0);
-
- /* wait a little bit (10ms) */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100);
-
- /* disable double packet buffering */
- MUSB2_WRITE_2(sc, MUSB2_REG_RXDBDIS, 0xFFFF);
- MUSB2_WRITE_2(sc, MUSB2_REG_TXDBDIS, 0xFFFF);
-
- /* enable HighSpeed and ISO Update flags */
-
- MUSB2_WRITE_1(sc, MUSB2_REG_POWER,
- MUSB2_MASK_HSENAB | MUSB2_MASK_ISOUPD);
-
- /* clear Session bit, if set */
-
- temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
- temp &= ~MUSB2_MASK_SESS;
- MUSB2_WRITE_1(sc, MUSB2_REG_DEVCTL, temp);
-
- DPRINTF("DEVCTL=0x%02x\n", temp);
-
- /* disable testmode */
-
- MUSB2_WRITE_1(sc, MUSB2_REG_TESTMODE, 0);
-
- /* set default value */
-
- MUSB2_WRITE_1(sc, MUSB2_REG_MISC, 0);
-
- /* select endpoint index 0 */
-
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
-
- /* read out number of endpoints */
-
- nrx =
- (MUSB2_READ_1(sc, MUSB2_REG_EPINFO) / 16);
-
- ntx =
- (MUSB2_READ_1(sc, MUSB2_REG_EPINFO) % 16);
-
- /* these numbers exclude the control endpoint */
-
- DPRINTFN(2, "RX/TX endpoints: %u/%u\n", nrx, ntx);
-
- sc->sc_ep_max = (nrx > ntx) ? nrx : ntx;
- if (sc->sc_ep_max == 0) {
- DPRINTFN(2, "ERROR: Looks like the clocks are off!\n");
- }
- /* read out configuration data */
-
- sc->sc_conf_data = MUSB2_READ_1(sc, MUSB2_REG_CONFDATA);
-
- DPRINTFN(2, "Config Data: 0x%02x\n",
- sc->sc_conf_data);
-
- DPRINTFN(2, "HW version: 0x%04x\n",
- MUSB2_READ_1(sc, MUSB2_REG_HWVERS));
-
- /* initialise endpoint profiles */
-
- for (temp = 1; temp <= sc->sc_ep_max; temp++) {
- pf = sc->sc_hw_ep_profile + temp;
-
- /* select endpoint */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, temp);
-
- fsize = MUSB2_READ_1(sc, MUSB2_REG_FSIZE);
- frx = (fsize & MUSB2_MASK_RX_FSIZE) / 16;;
- ftx = (fsize & MUSB2_MASK_TX_FSIZE);
-
- DPRINTF("Endpoint %u FIFO size: IN=%u, OUT=%u\n",
- temp, pf->max_in_frame_size,
- pf->max_out_frame_size);
-
- if (frx && ftx && (temp <= nrx) && (temp <= ntx)) {
- pf->max_in_frame_size = 1 << ftx;
- pf->max_out_frame_size = 1 << frx;
- pf->is_simplex = 0; /* duplex */
- pf->support_multi_buffer = 1;
- pf->support_bulk = 1;
- pf->support_interrupt = 1;
- pf->support_isochronous = 1;
- pf->support_in = 1;
- pf->support_out = 1;
- } else if (frx && (temp <= nrx)) {
- pf->max_out_frame_size = 1 << frx;
- pf->is_simplex = 1; /* simplex */
- pf->support_multi_buffer = 1;
- pf->support_bulk = 1;
- pf->support_interrupt = 1;
- pf->support_isochronous = 1;
- pf->support_out = 1;
- } else if (ftx && (temp <= ntx)) {
- pf->max_in_frame_size = 1 << ftx;
- pf->is_simplex = 1; /* simplex */
- pf->support_multi_buffer = 1;
- pf->support_bulk = 1;
- pf->support_interrupt = 1;
- pf->support_isochronous = 1;
- pf->support_in = 1;
- }
- }
-
- /* turn on default interrupts */
-
- MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE,
- MUSB2_MASK_IRESET);
-
- musbotg_clocks_off(sc);
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- /* catch any lost interrupts */
-
- musbotg_do_poll(&sc->sc_bus);
-
- return (0); /* success */
-}
-
-void
-musbotg_uninit(struct musbotg_softc *sc)
-{
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* disable all interrupts */
- MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, 0);
- MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, 0);
- MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, 0);
-
- sc->sc_flags.port_powered = 0;
- sc->sc_flags.status_vbus = 0;
- sc->sc_flags.status_bus_reset = 0;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- musbotg_pull_down(sc);
- musbotg_clocks_off(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-void
-musbotg_suspend(struct musbotg_softc *sc)
-{
- return;
-}
-
-void
-musbotg_resume(struct musbotg_softc *sc)
-{
- return;
-}
-
-static void
-musbotg_do_poll(struct usb2_bus *bus)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(bus);
-
- USB_BUS_LOCK(&sc->sc_bus);
- musbotg_interrupt_poll(sc);
- musbotg_root_ctrl_poll(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-/*------------------------------------------------------------------------*
- * musbotg bulk support
- *------------------------------------------------------------------------*/
-static void
-musbotg_device_bulk_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_device_bulk_close(struct usb2_xfer *xfer)
-{
- musbotg_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-musbotg_device_bulk_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_device_bulk_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- musbotg_setup_standard_chain(xfer);
- musbotg_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods musbotg_device_bulk_methods =
-{
- .open = musbotg_device_bulk_open,
- .close = musbotg_device_bulk_close,
- .enter = musbotg_device_bulk_enter,
- .start = musbotg_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * musbotg control support
- *------------------------------------------------------------------------*/
-static void
-musbotg_device_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_device_ctrl_close(struct usb2_xfer *xfer)
-{
- musbotg_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-musbotg_device_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_device_ctrl_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- musbotg_setup_standard_chain(xfer);
- musbotg_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods musbotg_device_ctrl_methods =
-{
- .open = musbotg_device_ctrl_open,
- .close = musbotg_device_ctrl_close,
- .enter = musbotg_device_ctrl_enter,
- .start = musbotg_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * musbotg interrupt support
- *------------------------------------------------------------------------*/
-static void
-musbotg_device_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_device_intr_close(struct usb2_xfer *xfer)
-{
- musbotg_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-musbotg_device_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_device_intr_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- musbotg_setup_standard_chain(xfer);
- musbotg_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods musbotg_device_intr_methods =
-{
- .open = musbotg_device_intr_open,
- .close = musbotg_device_intr_close,
- .enter = musbotg_device_intr_enter,
- .start = musbotg_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * musbotg full speed isochronous support
- *------------------------------------------------------------------------*/
-static void
-musbotg_device_isoc_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_device_isoc_close(struct usb2_xfer *xfer)
-{
- musbotg_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-musbotg_device_isoc_enter(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
- uint32_t temp;
- uint32_t nframes;
- uint32_t fs_frames;
-
- DPRINTFN(5, "xfer=%p next=%d nframes=%d\n",
- xfer, xfer->pipe->isoc_next, xfer->nframes);
-
- /* get the current frame index */
-
- nframes = MUSB2_READ_2(sc, MUSB2_REG_FRAME);
-
- /*
- * check if the frame index is within the window where the frames
- * will be inserted
- */
- temp = (nframes - xfer->pipe->isoc_next) & MUSB2_MASK_FRAME;
-
- if (usb2_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) {
- fs_frames = (xfer->nframes + 7) / 8;
- } else {
- fs_frames = xfer->nframes;
- }
-
- if ((xfer->pipe->is_synced == 0) ||
- (temp < fs_frames)) {
- /*
- * If there is data underflow or the pipe queue is
- * empty we schedule the transfer a few frames ahead
- * of the current frame position. Else two isochronous
- * transfers might overlap.
- */
- xfer->pipe->isoc_next = (nframes + 3) & MUSB2_MASK_FRAME;
- xfer->pipe->is_synced = 1;
- DPRINTFN(2, "start next=%d\n", xfer->pipe->isoc_next);
- }
- /*
- * compute how many milliseconds the insertion is ahead of the
- * current frame position:
- */
- temp = (xfer->pipe->isoc_next - nframes) & MUSB2_MASK_FRAME;
-
- /*
- * pre-compute when the isochronous transfer will be finished:
- */
- xfer->isoc_time_complete =
- usb2_isoc_time_expand(&sc->sc_bus, nframes) + temp +
- fs_frames;
-
- /* compute frame number for next insertion */
- xfer->pipe->isoc_next += fs_frames;
-
- /* setup TDs */
- musbotg_setup_standard_chain(xfer);
-}
-
-static void
-musbotg_device_isoc_start(struct usb2_xfer *xfer)
-{
- /* start TD chain */
- musbotg_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods musbotg_device_isoc_methods =
-{
- .open = musbotg_device_isoc_open,
- .close = musbotg_device_isoc_close,
- .enter = musbotg_device_isoc_enter,
- .start = musbotg_device_isoc_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * musbotg root control support
- *------------------------------------------------------------------------*
- * simulate a hardware HUB by handling
- * all the necessary requests
- *------------------------------------------------------------------------*/
-static void
-musbotg_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_root_ctrl_close(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- musbotg_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/*
- * USB descriptors for the virtual Root HUB:
- */
-
-static const struct usb2_device_descriptor musbotg_devd = {
- .bLength = sizeof(struct usb2_device_descriptor),
- .bDescriptorType = UDESC_DEVICE,
- .bcdUSB = {0x00, 0x02},
- .bDeviceClass = UDCLASS_HUB,
- .bDeviceSubClass = UDSUBCLASS_HUB,
- .bDeviceProtocol = UDPROTO_HSHUBSTT,
- .bMaxPacketSize = 64,
- .bcdDevice = {0x00, 0x01},
- .iManufacturer = 1,
- .iProduct = 2,
- .bNumConfigurations = 1,
-};
-
-static const struct usb2_device_qualifier musbotg_odevd = {
- .bLength = sizeof(struct usb2_device_qualifier),
- .bDescriptorType = UDESC_DEVICE_QUALIFIER,
- .bcdUSB = {0x00, 0x02},
- .bDeviceClass = UDCLASS_HUB,
- .bDeviceSubClass = UDSUBCLASS_HUB,
- .bDeviceProtocol = UDPROTO_FSHUB,
- .bMaxPacketSize0 = 0,
- .bNumConfigurations = 0,
-};
-
-static const struct musbotg_config_desc musbotg_confd = {
- .confd = {
- .bLength = sizeof(struct usb2_config_descriptor),
- .bDescriptorType = UDESC_CONFIG,
- .wTotalLength[0] = sizeof(musbotg_confd),
- .bNumInterface = 1,
- .bConfigurationValue = 1,
- .iConfiguration = 0,
- .bmAttributes = UC_SELF_POWERED,
- .bMaxPower = 0,
- },
- .ifcd = {
- .bLength = sizeof(struct usb2_interface_descriptor),
- .bDescriptorType = UDESC_INTERFACE,
- .bNumEndpoints = 1,
- .bInterfaceClass = UICLASS_HUB,
- .bInterfaceSubClass = UISUBCLASS_HUB,
- .bInterfaceProtocol = UIPROTO_HSHUBSTT,
- },
-
- .endpd = {
- .bLength = sizeof(struct usb2_endpoint_descriptor),
- .bDescriptorType = UDESC_ENDPOINT,
- .bEndpointAddress = (UE_DIR_IN | MUSBOTG_INTR_ENDPT),
- .bmAttributes = UE_INTERRUPT,
- .wMaxPacketSize[0] = 8,
- .bInterval = 255,
- },
-};
-
-static const struct usb2_hub_descriptor_min musbotg_hubd = {
- .bDescLength = sizeof(musbotg_hubd),
- .bDescriptorType = UDESC_HUB,
- .bNbrPorts = 1,
- .wHubCharacteristics[0] =
- (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) & 0xFF,
- .wHubCharacteristics[1] =
- (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 16,
- .bPwrOn2PwrGood = 50,
- .bHubContrCurrent = 0,
- .DeviceRemovable = {0}, /* port is removable */
-};
-
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
-#define STRING_VENDOR \
- 'M', 0, 'e', 0, 'n', 0, 't', 0, 'o', 0, 'r', 0, ' ', 0, \
- 'G', 0, 'r', 0, 'a', 0, 'p', 0, 'h', 0, 'i', 0, 'c', 0, 's', 0
-
-#define STRING_PRODUCT \
- 'O', 0, 'T', 0, 'G', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
-
-USB_MAKE_STRING_DESC(STRING_LANG, musbotg_langtab);
-USB_MAKE_STRING_DESC(STRING_VENDOR, musbotg_vendor);
-USB_MAKE_STRING_DESC(STRING_PRODUCT, musbotg_product);
-
-static void
-musbotg_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_root_ctrl_start(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-musbotg_root_ctrl_task(struct usb2_bus *bus)
-{
- musbotg_root_ctrl_poll(MUSBOTG_BUS2SC(bus));
-}
-
-static void
-musbotg_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
- uint16_t value;
- uint16_t index;
- uint8_t use_polling;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- musbotg_device_done(xfer, std->err);
- }
- goto done;
- }
- /* buffer reset */
- std->ptr = USB_ADD_BYTES(&sc->sc_hub_temp, 0);
- std->len = 0;
-
- value = UGETW(std->req.wValue);
- index = UGETW(std->req.wIndex);
-
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- /* demultiplex the control request */
-
- switch (std->req.bmRequestType) {
- case UT_READ_DEVICE:
- switch (std->req.bRequest) {
- case UR_GET_DESCRIPTOR:
- goto tr_handle_get_descriptor;
- case UR_GET_CONFIG:
- goto tr_handle_get_config;
- case UR_GET_STATUS:
- goto tr_handle_get_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_DEVICE:
- switch (std->req.bRequest) {
- case UR_SET_ADDRESS:
- goto tr_handle_set_address;
- case UR_SET_CONFIG:
- goto tr_handle_set_config;
- case UR_CLEAR_FEATURE:
- goto tr_valid; /* nop */
- case UR_SET_DESCRIPTOR:
- goto tr_valid; /* nop */
- case UR_SET_FEATURE:
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_ENDPOINT:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- switch (UGETW(std->req.wValue)) {
- case UF_ENDPOINT_HALT:
- goto tr_handle_clear_halt;
- case UF_DEVICE_REMOTE_WAKEUP:
- goto tr_handle_clear_wakeup;
- default:
- goto tr_stalled;
- }
- break;
- case UR_SET_FEATURE:
- switch (UGETW(std->req.wValue)) {
- case UF_ENDPOINT_HALT:
- goto tr_handle_set_halt;
- case UF_DEVICE_REMOTE_WAKEUP:
- goto tr_handle_set_wakeup;
- default:
- goto tr_stalled;
- }
- break;
- case UR_SYNCH_FRAME:
- goto tr_valid; /* nop */
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_ENDPOINT:
- switch (std->req.bRequest) {
- case UR_GET_STATUS:
- goto tr_handle_get_ep_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_INTERFACE:
- switch (std->req.bRequest) {
- case UR_SET_INTERFACE:
- goto tr_handle_set_interface;
- case UR_CLEAR_FEATURE:
- goto tr_valid; /* nop */
- case UR_SET_FEATURE:
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_INTERFACE:
- switch (std->req.bRequest) {
- case UR_GET_INTERFACE:
- goto tr_handle_get_interface;
- case UR_GET_STATUS:
- goto tr_handle_get_iface_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_CLASS_INTERFACE:
- case UT_WRITE_VENDOR_INTERFACE:
- /* XXX forward */
- break;
-
- case UT_READ_CLASS_INTERFACE:
- case UT_READ_VENDOR_INTERFACE:
- /* XXX forward */
- break;
-
- case UT_WRITE_CLASS_DEVICE:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- goto tr_valid;
- case UR_SET_DESCRIPTOR:
- case UR_SET_FEATURE:
- break;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_CLASS_OTHER:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- goto tr_handle_clear_port_feature;
- case UR_SET_FEATURE:
- goto tr_handle_set_port_feature;
- case UR_CLEAR_TT_BUFFER:
- case UR_RESET_TT:
- case UR_STOP_TT:
- goto tr_valid;
-
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_CLASS_OTHER:
- switch (std->req.bRequest) {
- case UR_GET_TT_STATE:
- goto tr_handle_get_tt_state;
- case UR_GET_STATUS:
- goto tr_handle_get_port_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_CLASS_DEVICE:
- switch (std->req.bRequest) {
- case UR_GET_DESCRIPTOR:
- goto tr_handle_get_class_descriptor;
- case UR_GET_STATUS:
- goto tr_handle_get_class_status;
-
- default:
- goto tr_stalled;
- }
- break;
- default:
- goto tr_stalled;
- }
- goto tr_valid;
-
-tr_handle_get_descriptor:
- switch (value >> 8) {
- case UDESC_DEVICE:
- if (value & 0xff) {
- goto tr_stalled;
- }
- std->len = sizeof(musbotg_devd);
- std->ptr = USB_ADD_BYTES(&musbotg_devd, 0);
- goto tr_valid;
- case UDESC_CONFIG:
- if (value & 0xff) {
- goto tr_stalled;
- }
- std->len = sizeof(musbotg_confd);
- std->ptr = USB_ADD_BYTES(&musbotg_confd, 0);
- goto tr_valid;
- case UDESC_STRING:
- switch (value & 0xff) {
- case 0: /* Language table */
- std->len = sizeof(musbotg_langtab);
- std->ptr = USB_ADD_BYTES(&musbotg_langtab, 0);
- goto tr_valid;
-
- case 1: /* Vendor */
- std->len = sizeof(musbotg_vendor);
- std->ptr = USB_ADD_BYTES(&musbotg_vendor, 0);
- goto tr_valid;
-
- case 2: /* Product */
- std->len = sizeof(musbotg_product);
- std->ptr = USB_ADD_BYTES(&musbotg_product, 0);
- goto tr_valid;
- default:
- break;
- }
- break;
- default:
- goto tr_stalled;
- }
- goto tr_stalled;
-
-tr_handle_get_config:
- std->len = 1;
- sc->sc_hub_temp.wValue[0] = sc->sc_conf;
- goto tr_valid;
-
-tr_handle_get_status:
- std->len = 2;
- USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED);
- goto tr_valid;
-
-tr_handle_set_address:
- if (value & 0xFF00) {
- goto tr_stalled;
- }
- sc->sc_rt_addr = value;
- goto tr_valid;
-
-tr_handle_set_config:
- if (value >= 2) {
- goto tr_stalled;
- }
- sc->sc_conf = value;
- goto tr_valid;
-
-tr_handle_get_interface:
- std->len = 1;
- sc->sc_hub_temp.wValue[0] = 0;
- goto tr_valid;
-
-tr_handle_get_tt_state:
-tr_handle_get_class_status:
-tr_handle_get_iface_status:
-tr_handle_get_ep_status:
- std->len = 2;
- USETW(sc->sc_hub_temp.wValue, 0);
- goto tr_valid;
-
-tr_handle_set_halt:
-tr_handle_set_interface:
-tr_handle_set_wakeup:
-tr_handle_clear_wakeup:
-tr_handle_clear_halt:
- goto tr_valid;
-
-tr_handle_clear_port_feature:
- if (index != 1) {
- goto tr_stalled;
- }
- DPRINTFN(8, "UR_CLEAR_PORT_FEATURE on port %d\n", index);
-
- switch (value) {
- case UHF_PORT_SUSPEND:
- musbotg_wakeup_peer(xfer);
- break;
-
- case UHF_PORT_ENABLE:
- sc->sc_flags.port_enabled = 0;
- break;
-
- case UHF_PORT_TEST:
- case UHF_PORT_INDICATOR:
- case UHF_C_PORT_ENABLE:
- case UHF_C_PORT_OVER_CURRENT:
- case UHF_C_PORT_RESET:
- /* nops */
- break;
- case UHF_PORT_POWER:
- sc->sc_flags.port_powered = 0;
- musbotg_pull_down(sc);
- musbotg_clocks_off(sc);
- break;
- case UHF_C_PORT_CONNECTION:
- sc->sc_flags.change_connect = 0;
- break;
- case UHF_C_PORT_SUSPEND:
- sc->sc_flags.change_suspend = 0;
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- goto tr_valid;
-
-tr_handle_set_port_feature:
- if (index != 1) {
- goto tr_stalled;
- }
- DPRINTFN(8, "UR_SET_PORT_FEATURE\n");
-
- switch (value) {
- case UHF_PORT_ENABLE:
- sc->sc_flags.port_enabled = 1;
- break;
- case UHF_PORT_SUSPEND:
- case UHF_PORT_RESET:
- case UHF_PORT_TEST:
- case UHF_PORT_INDICATOR:
- /* nops */
- break;
- case UHF_PORT_POWER:
- sc->sc_flags.port_powered = 1;
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- goto tr_valid;
-
-tr_handle_get_port_status:
-
- DPRINTFN(8, "UR_GET_PORT_STATUS\n");
-
- if (index != 1) {
- goto tr_stalled;
- }
- if (sc->sc_flags.status_vbus) {
- musbotg_clocks_on(sc);
- musbotg_pull_up(sc);
- } else {
- musbotg_pull_down(sc);
- musbotg_clocks_off(sc);
- }
-
- /* Select Device Side Mode */
- value = UPS_PORT_MODE_DEVICE;
-
- if (sc->sc_flags.status_high_speed) {
- value |= UPS_HIGH_SPEED;
- }
- if (sc->sc_flags.port_powered) {
- value |= UPS_PORT_POWER;
- }
- if (sc->sc_flags.port_enabled) {
- value |= UPS_PORT_ENABLED;
- }
- if (sc->sc_flags.status_vbus &&
- sc->sc_flags.status_bus_reset) {
- value |= UPS_CURRENT_CONNECT_STATUS;
- }
- if (sc->sc_flags.status_suspend) {
- value |= UPS_SUSPEND;
- }
- USETW(sc->sc_hub_temp.ps.wPortStatus, value);
-
- value = 0;
-
- if (sc->sc_flags.change_connect) {
- value |= UPS_C_CONNECT_STATUS;
-
- if (sc->sc_flags.status_vbus &&
- sc->sc_flags.status_bus_reset) {
- /* reset EP0 state */
- sc->sc_ep0_busy = 0;
- sc->sc_ep0_cmd = 0;
- }
- }
- if (sc->sc_flags.change_suspend) {
- value |= UPS_C_SUSPEND;
- }
- USETW(sc->sc_hub_temp.ps.wPortChange, value);
- std->len = sizeof(sc->sc_hub_temp.ps);
- goto tr_valid;
-
-tr_handle_get_class_descriptor:
- if (value & 0xFF) {
- goto tr_stalled;
- }
- std->ptr = USB_ADD_BYTES(&musbotg_hubd, 0);
- std->len = sizeof(musbotg_hubd);
- goto tr_valid;
-
-tr_stalled:
- std->err = USB_ERR_STALLED;
-tr_valid:
-done:
- return;
-}
-
-static void
-musbotg_root_ctrl_poll(struct musbotg_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &musbotg_root_ctrl_done);
-}
-
-struct usb2_pipe_methods musbotg_root_ctrl_methods =
-{
- .open = musbotg_root_ctrl_open,
- .close = musbotg_root_ctrl_close,
- .enter = musbotg_root_ctrl_enter,
- .start = musbotg_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * musbotg root interrupt support
- *------------------------------------------------------------------------*/
-static void
-musbotg_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_root_intr_close(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- musbotg_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-musbotg_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_root_intr_start(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods musbotg_root_intr_methods =
-{
- .open = musbotg_root_intr_open,
- .close = musbotg_root_intr_close,
- .enter = musbotg_root_intr_enter,
- .start = musbotg_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
-musbotg_xfer_setup(struct usb2_setup_params *parm)
-{
- const struct usb2_hw_ep_profile *pf;
- struct musbotg_softc *sc;
- struct usb2_xfer *xfer;
- void *last_obj;
- uint32_t ntd;
- uint32_t n;
- uint8_t ep_no;
-
- sc = MUSBOTG_BUS2SC(parm->udev->bus);
- xfer = parm->curr_xfer;
-
- /*
- * NOTE: This driver does not use any of the parameters that
- * are computed from the following values. Just set some
- * reasonable dummies:
- */
- parm->hc_max_packet_size = 0x400;
- parm->hc_max_frame_size = 0x400;
-
- if ((parm->methods == &musbotg_device_isoc_methods) ||
- (parm->methods == &musbotg_device_intr_methods))
- parm->hc_max_packet_count = 3;
- else
- parm->hc_max_packet_count = 1;
-
- usb2_transfer_setup_sub(parm);
-
- /*
- * compute maximum number of TDs
- */
- if (parm->methods == &musbotg_device_ctrl_methods) {
-
- ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC */ ;
-
- } else if (parm->methods == &musbotg_device_bulk_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &musbotg_device_intr_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &musbotg_device_isoc_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else {
-
- ntd = 0;
- }
-
- /*
- * check if "usb2_transfer_setup_sub" set an error
- */
- if (parm->err) {
- return;
- }
- /*
- * allocate transfer descriptors
- */
- last_obj = NULL;
-
- /*
- * get profile stuff
- */
- if (ntd) {
-
- ep_no = xfer->endpoint & UE_ADDR;
- musbotg_get_hw_ep_profile(parm->udev, &pf, ep_no);
-
- if (pf == NULL) {
- /* should not happen */
- parm->err = USB_ERR_INVAL;
- return;
- }
- } else {
- ep_no = 0;
- pf = NULL;
- }
-
- /* align data */
- parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
-
- for (n = 0; n != ntd; n++) {
-
- struct musbotg_td *td;
-
- if (parm->buf) {
-
- td = USB_ADD_BYTES(parm->buf, parm->size[0]);
-
- /* init TD */
- td->max_frame_size = xfer->max_frame_size;
- td->ep_no = ep_no;
- td->obj_next = last_obj;
-
- last_obj = td;
- }
- parm->size[0] += sizeof(*td);
- }
-
- xfer->td_start[0] = last_obj;
-}
-
-static void
-musbotg_xfer_unsetup(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
- struct usb2_pipe *pipe)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(udev->bus);
-
- DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
- pipe, udev->address,
- edesc->bEndpointAddress, udev->flags.usb2_mode,
- sc->sc_rt_addr);
-
- if (udev->device_index == sc->sc_rt_addr) {
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &musbotg_root_ctrl_methods;
- break;
- case UE_DIR_IN | MUSBOTG_INTR_ENDPT:
- pipe->methods = &musbotg_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
-
- if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
- if ((udev->speed != USB_SPEED_FULL) &&
- (udev->speed != USB_SPEED_HIGH)) {
- /* not supported */
- return;
- }
- switch (edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- pipe->methods = &musbotg_device_ctrl_methods;
- break;
- case UE_INTERRUPT:
- pipe->methods = &musbotg_device_intr_methods;
- break;
- case UE_ISOCHRONOUS:
- pipe->methods = &musbotg_device_isoc_methods;
- break;
- case UE_BULK:
- pipe->methods = &musbotg_device_bulk_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- }
-}
-
-struct usb2_bus_methods musbotg_bus_methods =
-{
- .pipe_init = &musbotg_pipe_init,
- .xfer_setup = &musbotg_xfer_setup,
- .xfer_unsetup = &musbotg_xfer_unsetup,
- .do_poll = &musbotg_do_poll,
- .get_hw_ep_profile = &musbotg_get_hw_ep_profile,
- .set_stall = &musbotg_set_stall,
- .clear_stall = &musbotg_clear_stall,
- .roothub_exec = &musbotg_root_ctrl_task,
-};
diff --git a/sys/dev/usb2/controller/musb2_otg.h b/sys/dev/usb2/controller/musb2_otg.h
deleted file mode 100644
index 0d880e1..0000000
--- a/sys/dev/usb2/controller/musb2_otg.h
+++ /dev/null
@@ -1,407 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-/*
- * This header file defines the registers of the Mentor Graphics
- * USB OnTheGo Inventra chip.
- */
-
-#ifndef _MUSB2_OTG_H_
-#define _MUSB2_OTG_H_
-
-#define MUSB2_MAX_DEVICES (USB_MIN_DEVICES + 1)
-
-/* Common registers */
-
-#define MUSB2_REG_FADDR 0x0000 /* function address register */
-#define MUSB2_MASK_FADDR 0x7F
-
-#define MUSB2_REG_POWER 0x0001 /* power register */
-#define MUSB2_MASK_SUSPM_ENA 0x01
-#define MUSB2_MASK_SUSPMODE 0x02
-#define MUSB2_MASK_RESUME 0x04
-#define MUSB2_MASK_RESET 0x08
-#define MUSB2_MASK_HSMODE 0x10
-#define MUSB2_MASK_HSENAB 0x20
-#define MUSB2_MASK_SOFTC 0x40
-#define MUSB2_MASK_ISOUPD 0x80
-
-/* Endpoint interrupt handling */
-
-#define MUSB2_REG_INTTX 0x0002 /* transmit interrupt register */
-#define MUSB2_REG_INTRX 0x0004 /* receive interrupt register */
-#define MUSB2_REG_INTTXE 0x0006 /* transmit interrupt enable register */
-#define MUSB2_REG_INTRXE 0x0008 /* receive interrupt enable register */
-#define MUSB2_MASK_EPINT(epn) (1 << (epn)) /* epn = [0..15] */
-
-/* Common interrupt handling */
-
-#define MUSB2_REG_INTUSB 0x000A /* USB interrupt register */
-#define MUSB2_MASK_ISUSP 0x01
-#define MUSB2_MASK_IRESUME 0x02
-#define MUSB2_MASK_IRESET 0x04
-#define MUSB2_MASK_IBABBLE 0x04
-#define MUSB2_MASK_ISOF 0x08
-#define MUSB2_MASK_ICONN 0x10
-#define MUSB2_MASK_IDISC 0x20
-#define MUSB2_MASK_ISESSRQ 0x40
-#define MUSB2_MASK_IVBUSERR 0x80
-
-#define MUSB2_REG_INTUSBE 0x000B /* USB interrupt enable register */
-#define MUSB2_REG_FRAME 0x000C /* USB frame register */
-#define MUSB2_MASK_FRAME 0x3FF /* 0..1023 */
-
-#define MUSB2_REG_EPINDEX 0x000E /* endpoint index register */
-#define MUSB2_MASK_EPINDEX 0x0F
-
-#define MUSB2_REG_TESTMODE 0x000F /* test mode register */
-#define MUSB2_MASK_TSE0_NAK 0x01
-#define MUSB2_MASK_TJ 0x02
-#define MUSB2_MASK_TK 0x04
-#define MUSB2_MASK_TPACKET 0x08
-#define MUSB2_MASK_TFORCE_HS 0x10
-#define MUSB2_MASK_TFORCE_LS 0x20
-#define MUSB2_MASK_TFIFO_ACC 0x40
-#define MUSB2_MASK_TFORCE_HC 0x80
-
-#define MUSB2_REG_INDEXED_CSR 0x0010 /* EP control status register offset */
-
-#define MUSB2_REG_TXMAXP (0x0000 + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_REG_RXMAXP (0x0004 + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_MASK_PKTSIZE 0x03FF /* in bytes, should be even */
-#define MUSB2_MASK_PKTMULT 0xFC00 /* HS packet multiplier: 0..2 */
-
-#define MUSB2_REG_TXCSRL (0x0002 + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_MASK_CSRL_TXPKTRDY 0x01
-#define MUSB2_MASK_CSRL_TXFIFONEMPTY 0x02
-#define MUSB2_MASK_CSRL_TXUNDERRUN 0x04 /* Device Mode */
-#define MUSB2_MASK_CSRL_TXERROR 0x04 /* Host Mode */
-#define MUSB2_MASK_CSRL_TXFFLUSH 0x08
-#define MUSB2_MASK_CSRL_TXSENDSTALL 0x10/* Device Mode */
-#define MUSB2_MASK_CSRL_TXSETUPPKT 0x10 /* Host Mode */
-#define MUSB2_MASK_CSRL_TXSENTSTALL 0x20/* Device Mode */
-#define MUSB2_MASK_CSRL_TXSTALLED 0x20 /* Host Mode */
-#define MUSB2_MASK_CSRL_TXDT_CLR 0x40
-#define MUSB2_MASK_CSRL_TXINCOMP 0x80
-
-/* Device Side Mode */
-#define MUSB2_MASK_CSR0L_RXPKTRDY 0x01
-#define MUSB2_MASK_CSR0L_TXPKTRDY 0x02
-#define MUSB2_MASK_CSR0L_SENTSTALL 0x04
-#define MUSB2_MASK_CSR0L_DATAEND 0x08
-#define MUSB2_MASK_CSR0L_SETUPEND 0x10
-#define MUSB2_MASK_CSR0L_SENDSTALL 0x20
-#define MUSB2_MASK_CSR0L_RXPKTRDY_CLR 0x40
-#define MUSB2_MASK_CSR0L_SETUPEND_CLR 0x80
-
-/* Host Side Mode */
-#define MUSB2_MASK_CSR0L_RXSTALL 0x04
-#define MUSB2_MASK_CSR0L_SETUPPKT 0x08
-#define MUSB2_MASK_CSR0L_ERROR 0x10
-#define MUSB2_MASK_CSR0L_REQPKT 0x20
-#define MUSB2_MASK_CSR0L_STATUSPKT 0x40
-#define MUSB2_MASK_CSR0L_NAKTIMO 0x80
-
-#define MUSB2_REG_TXCSRH (0x0003 + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_MASK_CSRH_TXDT_VAL 0x01 /* Host Mode */
-#define MUSB2_MASK_CSRH_TXDT_WR 0x02 /* Host Mode */
-#define MUSB2_MASK_CSRH_TXDMAREQMODE 0x04
-#define MUSB2_MASK_CSRH_TXDT_SWITCH 0x08
-#define MUSB2_MASK_CSRH_TXDMAREQENA 0x10
-#define MUSB2_MASK_CSRH_RXMODE 0x00
-#define MUSB2_MASK_CSRH_TXMODE 0x20
-#define MUSB2_MASK_CSRH_TXISO 0x40 /* Device Mode */
-#define MUSB2_MASK_CSRH_TXAUTOSET 0x80
-
-#define MUSB2_MASK_CSR0H_FFLUSH 0x01 /* Device Side flush FIFO */
-#define MUSB2_MASK_CSR0H_DT 0x02 /* Host Side data toggle */
-#define MUSB2_MASK_CSR0H_DT_SET 0x04 /* Host Side */
-#define MUSB2_MASK_CSR0H_PING_DIS 0x08 /* Host Side */
-
-#define MUSB2_REG_RXCSRL (0x0006 + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_MASK_CSRL_RXPKTRDY 0x01
-#define MUSB2_MASK_CSRL_RXFIFOFULL 0x02
-#define MUSB2_MASK_CSRL_RXOVERRUN 0x04
-#define MUSB2_MASK_CSRL_RXDATAERR 0x08
-#define MUSB2_MASK_CSRL_RXFFLUSH 0x10
-#define MUSB2_MASK_CSRL_RXSENDSTALL 0x20/* Device Mode */
-#define MUSB2_MASK_CSRL_RXREQPKT 0x20 /* Host Mode */
-#define MUSB2_MASK_CSRL_RXSENTSTALL 0x40/* Device Mode */
-#define MUSB2_MASK_CSRL_RXSTALL 0x40 /* Host Mode */
-#define MUSB2_MASK_CSRL_RXDT_CLR 0x80
-
-#define MUSB2_REG_RXCSRH (0x0007 + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_MASK_CSRH_RXINCOMP 0x01
-#define MUSB2_MASK_CSRH_RXDT_VAL 0x02 /* Host Mode */
-#define MUSB2_MASK_CSRH_RXDT_SET 0x04 /* Host Mode */
-#define MUSB2_MASK_CSRH_RXDMAREQMODE 0x08
-#define MUSB2_MASK_CSRH_RXNYET 0x10
-#define MUSB2_MASK_CSRH_RXDMAREQENA 0x20
-#define MUSB2_MASK_CSRH_RXISO 0x40 /* Device Mode */
-#define MUSB2_MASK_CSRH_RXAUTOREQ 0x40 /* Host Mode */
-#define MUSB2_MASK_CSRH_RXAUTOCLEAR 0x80
-
-#define MUSB2_REG_RXCOUNT (0x0008 + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_MASK_RXCOUNT 0xFFFF
-
-#define MUSB2_REG_TXTI (0x000A + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_REG_RXTI (0x000C + MUSB2_REG_INDEXED_CSR)
-
-/* Host Mode */
-#define MUSB2_MASK_TI_SPEED 0xC0
-#define MUSB2_MASK_TI_SPEED_LO 0xC0
-#define MUSB2_MASK_TI_SPEED_FS 0x80
-#define MUSB2_MASK_TI_SPEED_HS 0x40
-#define MUSB2_MASK_TI_PROTO_CTRL 0x00
-#define MUSB2_MASK_TI_PROTO_ISOC 0x10
-#define MUSB2_MASK_TI_PROTO_BULK 0x20
-#define MUSB2_MASK_TI_PROTO_INTR 0x30
-#define MUSB2_MASK_TI_EP_NUM 0x0F
-
-#define MUSB2_REG_TXNAKLIMIT (0x000B /* EPN=0 */ + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_REG_RXNAKLIMIT (0x000D /* EPN=0 */ + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_MASK_NAKLIMIT 0xFF
-
-#define MUSB2_REG_FSIZE (0x000F + MUSB2_REG_INDEXED_CSR)
-#define MUSB2_MASK_RX_FSIZE 0xF0 /* 3..13, 2**n bytes */
-#define MUSB2_MASK_TX_FSIZE 0x0F /* 3..13, 2**n bytes */
-
-#define MUSB2_REG_EPFIFO(n) (0x0020 + (4*(n)))
-
-#define MUSB2_REG_CONFDATA 0x000F /* EPN=0 */
-#define MUSB2_MASK_CD_UTMI_DW 0x01
-#define MUSB2_MASK_CD_SOFTCONE 0x02
-#define MUSB2_MASK_CD_DYNFIFOSZ 0x04
-#define MUSB2_MASK_CD_HBTXE 0x08
-#define MUSB2_MASK_CD_HBRXE 0x10
-#define MUSB2_MASK_CD_BIGEND 0x20
-#define MUSB2_MASK_CD_MPTXE 0x40
-#define MUSB2_MASK_CD_MPRXE 0x80
-
-/* Various registers */
-
-#define MUSB2_REG_DEVCTL 0x0060
-#define MUSB2_MASK_SESS 0x01
-#define MUSB2_MASK_HOSTREQ 0x02
-#define MUSB2_MASK_HOSTMD 0x04
-#define MUSB2_MASK_VBUS0 0x08
-#define MUSB2_MASK_VBUS1 0x10
-#define MUSB2_MASK_LSDEV 0x20
-#define MUSB2_MASK_FSDEV 0x40
-#define MUSB2_MASK_BDEV 0x80
-
-#define MUSB2_REG_MISC 0x0061
-#define MUSB2_MASK_RXEDMA 0x01
-#define MUSB2_MASK_TXEDMA 0x02
-
-#define MUSB2_REG_TXFIFOSZ 0x0062
-#define MUSB2_REG_RXFIFOSZ 0x0063
-#define MUSB2_MASK_FIFODB 0x10 /* set if double buffering, r/w */
-#define MUSB2_MASK_FIFOSZ 0x0F
-#define MUSB2_VAL_FIFOSZ_8 0
-#define MUSB2_VAL_FIFOSZ_16 1
-#define MUSB2_VAL_FIFOSZ_32 2
-#define MUSB2_VAL_FIFOSZ_64 3
-#define MUSB2_VAL_FIFOSZ_128 4
-#define MUSB2_VAL_FIFOSZ_256 5
-#define MUSB2_VAL_FIFOSZ_512 6
-#define MUSB2_VAL_FIFOSZ_1024 7
-#define MUSB2_VAL_FIFOSZ_2048 8
-#define MUSB2_VAL_FIFOSZ_4096 9
-
-#define MUSB2_REG_TXFIFOADD 0x0064
-#define MUSB2_REG_RXFIFOADD 0x0066
-#define MUSB2_MASK_FIFOADD 0xFFF /* unit is 8-bytes */
-
-#define MUSB2_REG_VSTATUS 0x0068
-#define MUSB2_REG_VCONTROL 0x0068
-#define MUSB2_REG_HWVERS 0x006C
-#define MUSB2_REG_ULPI_BASE 0x0070
-
-#define MUSB2_REG_EPINFO 0x0078
-#define MUSB2_MASK_NRXEP 0xF0
-#define MUSB2_MASK_NTXEP 0x0F
-
-#define MUSB2_REG_RAMINFO 0x0079
-#define MUSB2_REG_LINKINFO 0x007A
-
-#define MUSB2_REG_VPLEN 0x007B
-#define MUSB2_MASK_VPLEN 0xFF
-
-#define MUSB2_REG_HS_EOF1 0x007C
-#define MUSB2_REG_FS_EOF1 0x007D
-#define MUSB2_REG_LS_EOF1 0x007E
-#define MUSB2_REG_SOFT_RST 0x007F
-#define MUSB2_MASK_SRST 0x01
-#define MUSB2_MASK_SRSTX 0x02
-
-#define MUSB2_REG_RQPKTCOUNT(n) (0x0300 + (4*(n))
-#define MUSB2_REG_RXDBDIS 0x0340
-#define MUSB2_REG_TXDBDIS 0x0342
-#define MUSB2_MASK_DB(n) (1 << (n)) /* disable double buffer, n = [0..15] */
-
-#define MUSB2_REG_CHIRPTO 0x0344
-#define MUSB2_REG_HSRESUM 0x0346
-
-/* Host Mode only registers */
-
-#define MUSB2_REG_TXFADDR(n) (0x0080 + (8*(n)))
-#define MUSB2_REG_TXHADDR(n) (0x0082 + (8*(n)))
-#define MUSB2_REG_TXHUBPORT(n) (0x0083 + (8*(n)))
-#define MUSB2_REG_RXFADDR(n) (0x0084 + (8*(n)))
-#define MUSB2_REG_RXHADDR(n) (0x0086 + (8*(n)))
-#define MUSB2_REG_RXHPORT(n) (0x0087 + (8*(n)))
-
-#define MUSB2_EP_MAX 16 /* maximum number of endpoints */
-
-#define MUSB2_READ_2(sc, reg) \
- bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
-
-#define MUSB2_WRITE_2(sc, reg, data) \
- bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
-
-#define MUSB2_READ_1(sc, reg) \
- bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
-
-#define MUSB2_WRITE_1(sc, reg, data) \
- bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
-
-struct musbotg_td;
-struct musbotg_softc;
-
-typedef uint8_t (musbotg_cmd_t)(struct musbotg_td *td);
-
-struct musbotg_dma {
- struct musbotg_softc *sc;
- uint32_t dma_chan;
- uint8_t busy:1;
- uint8_t complete:1;
- uint8_t error:1;
-};
-
-struct musbotg_td {
- struct musbotg_td *obj_next;
- musbotg_cmd_t *func;
- struct usb2_page_cache *pc;
- uint32_t offset;
- uint32_t remainder;
- uint16_t max_frame_size; /* packet_size * mult */
- uint8_t ep_no;
- uint8_t error:1;
- uint8_t alt_next:1;
- uint8_t short_pkt:1;
- uint8_t support_multi_buffer:1;
- uint8_t did_stall:1;
- uint8_t dma_enabled:1;
-};
-
-struct musbotg_std_temp {
- musbotg_cmd_t *func;
- struct usb2_page_cache *pc;
- struct musbotg_td *td;
- struct musbotg_td *td_next;
- uint32_t len;
- uint32_t offset;
- uint16_t max_frame_size;
- uint8_t short_pkt;
- /*
- * short_pkt = 0: transfer should be short terminated
- * short_pkt = 1: transfer should not be short terminated
- */
- uint8_t setup_alt_next;
-};
-
-struct musbotg_config_desc {
- struct usb2_config_descriptor confd;
- struct usb2_interface_descriptor ifcd;
- struct usb2_endpoint_descriptor endpd;
-} __packed;
-
-union musbotg_hub_temp {
- uWord wValue;
- struct usb2_port_status ps;
-};
-
-struct musbotg_flags {
- uint8_t change_connect:1;
- uint8_t change_suspend:1;
- uint8_t status_suspend:1; /* set if suspended */
- uint8_t status_vbus:1; /* set if present */
- uint8_t status_bus_reset:1; /* set if reset complete */
- uint8_t status_high_speed:1; /* set if High Speed is selected */
- uint8_t remote_wakeup:1;
- uint8_t self_powered:1;
- uint8_t clocks_off:1;
- uint8_t port_powered:1;
- uint8_t port_enabled:1;
- uint8_t d_pulled_up:1;
-};
-
-struct musbotg_softc {
- struct usb2_bus sc_bus;
- union musbotg_hub_temp sc_hub_temp;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
- struct usb2_hw_ep_profile sc_hw_ep_profile[16];
-
- struct usb2_device *sc_devices[MUSB2_MAX_DEVICES];
- struct resource *sc_io_res;
- struct resource *sc_irq_res;
- void *sc_intr_hdl;
- bus_size_t sc_io_size;
- bus_space_tag_t sc_io_tag;
- bus_space_handle_t sc_io_hdl;
-
- void (*sc_clocks_on) (void *arg);
- void (*sc_clocks_off) (void *arg);
- void *sc_clocks_arg;
-
- uint32_t sc_bounce_buf[(1024 * 3) / 4]; /* bounce buffer */
-
- uint8_t sc_ep_max; /* maximum number of RX and TX
- * endpoints supported */
- uint8_t sc_rt_addr; /* root HUB address */
- uint8_t sc_dv_addr; /* device address */
- uint8_t sc_conf; /* root HUB config */
- uint8_t sc_ep0_busy; /* set if ep0 is busy */
- uint8_t sc_ep0_cmd; /* pending commands */
- uint8_t sc_conf_data; /* copy of hardware register */
-
- uint8_t sc_hub_idata[1];
-
- struct musbotg_flags sc_flags;
-};
-
-/* prototypes */
-
-usb2_error_t musbotg_init(struct musbotg_softc *sc);
-void musbotg_uninit(struct musbotg_softc *sc);
-void musbotg_suspend(struct musbotg_softc *sc);
-void musbotg_resume(struct musbotg_softc *sc);
-void musbotg_interrupt(struct musbotg_softc *sc);
-void musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on);
-
-#endif /* _MUSB2_OTG_H_ */
diff --git a/sys/dev/usb2/controller/musb2_otg_atmelarm.c b/sys/dev/usb2/controller/musb2_otg_atmelarm.c
deleted file mode 100644
index 6477c97..0000000
--- a/sys/dev/usb2/controller/musb2_otg_atmelarm.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/musb2_otg.h>
-
-#include <sys/rman.h>
-
-static device_probe_t musbotg_probe;
-static device_attach_t musbotg_attach;
-static device_detach_t musbotg_detach;
-static device_shutdown_t musbotg_shutdown;
-
-struct musbotg_super_softc {
- struct musbotg_softc sc_otg; /* must be first */
-};
-
-static void
-musbotg_vbus_poll(struct musbotg_super_softc *sc)
-{
- uint8_t vbus_val = 1; /* fake VBUS on - TODO */
-
- /* just forward it */
- musbotg_vbus_interrupt(&sc->sc_otg, vbus_val);
-}
-
-static void
-musbotg_clocks_on(void *arg)
-{
-#if 0
- struct musbotg_super_softc *sc = arg;
-
-#endif
-}
-
-static void
-musbotg_clocks_off(void *arg)
-{
-#if 0
- struct musbotg_super_softc *sc = arg;
-
-#endif
-}
-
-static int
-musbotg_probe(device_t dev)
-{
- device_set_desc(dev, "MUSB OTG integrated USB controller");
- return (0);
-}
-
-static int
-musbotg_attach(device_t dev)
-{
- struct musbotg_super_softc *sc = device_get_softc(dev);
- int err;
- int rid;
-
- /* setup MUSB OTG USB controller interface softc */
- sc->sc_otg.sc_clocks_on = &musbotg_clocks_on;
- sc->sc_otg.sc_clocks_off = &musbotg_clocks_off;
- sc->sc_otg.sc_clocks_arg = sc;
-
- /* initialise some bus fields */
- sc->sc_otg.sc_bus.parent = dev;
- sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
- sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES;
-
- /* get all DMA memory */
- if (usb2_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
- USB_GET_DMA_TAG(dev), NULL)) {
- return (ENOMEM);
- }
- rid = 0;
- sc->sc_otg.sc_io_res =
- bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
-
- if (!(sc->sc_otg.sc_io_res)) {
- err = ENOMEM;
- goto error;
- }
- sc->sc_otg.sc_io_tag = rman_get_bustag(sc->sc_otg.sc_io_res);
- sc->sc_otg.sc_io_hdl = rman_get_bushandle(sc->sc_otg.sc_io_res);
- sc->sc_otg.sc_io_size = rman_get_size(sc->sc_otg.sc_io_res);
-
- rid = 0;
- sc->sc_otg.sc_irq_res =
- bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
- if (!(sc->sc_otg.sc_irq_res)) {
- goto error;
- }
- sc->sc_otg.sc_bus.bdev = device_add_child(dev, "usbus", -1);
- if (!(sc->sc_otg.sc_bus.bdev)) {
- goto error;
- }
- device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus);
-
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
-#else
- err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
-#endif
- if (err) {
- sc->sc_otg.sc_intr_hdl = NULL;
- goto error;
- }
- err = musbotg_init(&sc->sc_otg);
- if (!err) {
- err = device_probe_and_attach(sc->sc_otg.sc_bus.bdev);
- }
- if (err) {
- goto error;
- } else {
- /* poll VBUS one time */
- musbotg_vbus_poll(sc);
- }
- return (0);
-
-error:
- musbotg_detach(dev);
- return (ENXIO);
-}
-
-static int
-musbotg_detach(device_t dev)
-{
- struct musbotg_super_softc *sc = device_get_softc(dev);
- device_t bdev;
- int err;
-
- if (sc->sc_otg.sc_bus.bdev) {
- bdev = sc->sc_otg.sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(dev);
-
- if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) {
- /*
- * only call musbotg_uninit() after musbotg_init()
- */
- musbotg_uninit(&sc->sc_otg);
-
- err = bus_teardown_intr(dev, sc->sc_otg.sc_irq_res,
- sc->sc_otg.sc_intr_hdl);
- sc->sc_otg.sc_intr_hdl = NULL;
- }
- /* free IRQ channel, if any */
- if (sc->sc_otg.sc_irq_res) {
- bus_release_resource(dev, SYS_RES_IRQ, 0,
- sc->sc_otg.sc_irq_res);
- sc->sc_otg.sc_irq_res = NULL;
- }
- /* free memory resource, if any */
- if (sc->sc_otg.sc_io_res) {
- bus_release_resource(dev, SYS_RES_MEMORY, 0,
- sc->sc_otg.sc_io_res);
- sc->sc_otg.sc_io_res = NULL;
- }
- usb2_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL);
-
- return (0);
-}
-
-static int
-musbotg_shutdown(device_t dev)
-{
- struct musbotg_super_softc *sc = device_get_softc(dev);
- int err;
-
- err = bus_generic_shutdown(dev);
- if (err)
- return (err);
-
- musbotg_uninit(&sc->sc_otg);
-
- return (0);
-}
-
-static device_method_t musbotg_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, musbotg_probe),
- DEVMETHOD(device_attach, musbotg_attach),
- DEVMETHOD(device_detach, musbotg_detach),
- DEVMETHOD(device_shutdown, musbotg_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
-};
-
-static driver_t musbotg_driver = {
- "musbotg",
- musbotg_methods,
- sizeof(struct musbotg_super_softc),
-};
-
-static devclass_t musbotg_devclass;
-
-DRIVER_MODULE(musbotg, atmelarm, musbotg_driver, musbotg_devclass, 0, 0);
-MODULE_DEPEND(musbotg, usb2_controller, 1, 1, 1);
-MODULE_DEPEND(musbotg, usb2_core, 1, 1, 1);
diff --git a/sys/dev/usb2/controller/ohci2.c b/sys/dev/usb2/controller/ohci2.c
deleted file mode 100644
index 4c65ea7..0000000
--- a/sys/dev/usb2/controller/ohci2.c
+++ /dev/null
@@ -1,2862 +0,0 @@
-/*-
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
- * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
- * Copyright (c) 1998 Lennart Augustsson. 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.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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$");
-
-/*
- * USB Open Host Controller driver.
- *
- * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html
- * USB spec: http://www.usb.org/developers/docs/usbspec.zip
- */
-
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_defs.h>
-
-#define USB_DEBUG_VAR ohcidebug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_transfer.h>
-#include <dev/usb2/core/usb2_device.h>
-#include <dev/usb2/core/usb2_hub.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/ohci2.h>
-
-#define OHCI_BUS2SC(bus) ((ohci_softc_t *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((ohci_softc_t *)0)->sc_bus))))
-
-#if USB_DEBUG
-static int ohcidebug = 0;
-
-SYSCTL_NODE(_hw_usb2, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci");
-SYSCTL_INT(_hw_usb2_ohci, OID_AUTO, debug, CTLFLAG_RW,
- &ohcidebug, 0, "ohci debug level");
-static void ohci_dumpregs(ohci_softc_t *);
-static void ohci_dump_tds(ohci_td_t *);
-static uint8_t ohci_dump_td(ohci_td_t *);
-static void ohci_dump_ed(ohci_ed_t *);
-static uint8_t ohci_dump_itd(ohci_itd_t *);
-static void ohci_dump_itds(ohci_itd_t *);
-
-#endif
-
-#define OBARR(sc) bus_space_barrier((sc)->sc_io_tag, (sc)->sc_io_hdl, 0, (sc)->sc_io_size, \
- BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
-#define OWRITE1(sc, r, x) \
- do { OBARR(sc); bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (r), (x)); } while (0)
-#define OWRITE2(sc, r, x) \
- do { OBARR(sc); bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (r), (x)); } while (0)
-#define OWRITE4(sc, r, x) \
- do { OBARR(sc); bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (r), (x)); } while (0)
-#define OREAD1(sc, r) (OBARR(sc), bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (r)))
-#define OREAD2(sc, r) (OBARR(sc), bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (r)))
-#define OREAD4(sc, r) (OBARR(sc), bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (r)))
-
-#define OHCI_INTR_ENDPT 1
-
-extern struct usb2_bus_methods ohci_bus_methods;
-extern struct usb2_pipe_methods ohci_device_bulk_methods;
-extern struct usb2_pipe_methods ohci_device_ctrl_methods;
-extern struct usb2_pipe_methods ohci_device_intr_methods;
-extern struct usb2_pipe_methods ohci_device_isoc_methods;
-extern struct usb2_pipe_methods ohci_root_ctrl_methods;
-extern struct usb2_pipe_methods ohci_root_intr_methods;
-
-static void ohci_root_ctrl_poll(struct ohci_softc *sc);
-static void ohci_do_poll(struct usb2_bus *bus);
-static void ohci_device_done(struct usb2_xfer *xfer, usb2_error_t error);
-
-static usb2_sw_transfer_func_t ohci_root_intr_done;
-static usb2_sw_transfer_func_t ohci_root_ctrl_done;
-static void ohci_timeout(void *arg);
-static uint8_t ohci_check_transfer(struct usb2_xfer *xfer);
-
-struct ohci_std_temp {
- struct usb2_page_cache *pc;
- ohci_td_t *td;
- ohci_td_t *td_next;
- uint32_t average;
- uint32_t td_flags;
- uint32_t len;
- uint16_t max_frame_size;
- uint8_t shortpkt;
- uint8_t setup_alt_next;
- uint8_t short_frames_ok;
-};
-
-static struct ohci_hcca *
-ohci_get_hcca(ohci_softc_t *sc)
-{
- usb2_pc_cpu_invalidate(&sc->sc_hw.hcca_pc);
- return (sc->sc_hcca_p);
-}
-
-void
-ohci_iterate_hw_softc(struct usb2_bus *bus, usb2_bus_mem_sub_cb_t *cb)
-{
- struct ohci_softc *sc = OHCI_BUS2SC(bus);
- uint32_t i;
-
- cb(bus, &sc->sc_hw.hcca_pc, &sc->sc_hw.hcca_pg,
- sizeof(ohci_hcca_t), OHCI_HCCA_ALIGN);
-
- cb(bus, &sc->sc_hw.ctrl_start_pc, &sc->sc_hw.ctrl_start_pg,
- sizeof(ohci_ed_t), OHCI_ED_ALIGN);
-
- cb(bus, &sc->sc_hw.bulk_start_pc, &sc->sc_hw.bulk_start_pg,
- sizeof(ohci_ed_t), OHCI_ED_ALIGN);
-
- cb(bus, &sc->sc_hw.isoc_start_pc, &sc->sc_hw.isoc_start_pg,
- sizeof(ohci_ed_t), OHCI_ED_ALIGN);
-
- for (i = 0; i != OHCI_NO_EDS; i++) {
- cb(bus, sc->sc_hw.intr_start_pc + i, sc->sc_hw.intr_start_pg + i,
- sizeof(ohci_ed_t), OHCI_ED_ALIGN);
- }
-}
-
-static usb2_error_t
-ohci_controller_init(ohci_softc_t *sc)
-{
- struct usb2_page_search buf_res;
- uint32_t i;
- uint32_t ctl;
- uint32_t ival;
- uint32_t hcr;
- uint32_t fm;
- uint32_t per;
- uint32_t desca;
-
- /* Determine in what context we are running. */
- ctl = OREAD4(sc, OHCI_CONTROL);
- if (ctl & OHCI_IR) {
- /* SMM active, request change */
- DPRINTF("SMM active, request owner change\n");
- OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_OCR);
- for (i = 0; (i < 100) && (ctl & OHCI_IR); i++) {
- usb2_pause_mtx(NULL, hz / 1000);
- ctl = OREAD4(sc, OHCI_CONTROL);
- }
- if (ctl & OHCI_IR) {
- device_printf(sc->sc_bus.bdev,
- "SMM does not respond, resetting\n");
- OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
- goto reset;
- }
- } else {
- DPRINTF("cold started\n");
-reset:
- /* controller was cold started */
- usb2_pause_mtx(NULL,
- USB_MS_TO_TICKS(USB_BUS_RESET_DELAY));
- }
-
- /*
- * This reset should not be necessary according to the OHCI spec, but
- * without it some controllers do not start.
- */
- DPRINTF("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev));
- OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
-
- usb2_pause_mtx(NULL,
- USB_MS_TO_TICKS(USB_BUS_RESET_DELAY));
-
- /* we now own the host controller and the bus has been reset */
- ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL));
-
- OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_HCR); /* Reset HC */
- /* nominal time for a reset is 10 us */
- for (i = 0; i < 10; i++) {
- DELAY(10);
- hcr = OREAD4(sc, OHCI_COMMAND_STATUS) & OHCI_HCR;
- if (!hcr) {
- break;
- }
- }
- if (hcr) {
- device_printf(sc->sc_bus.bdev, "reset timeout\n");
- return (USB_ERR_IOERROR);
- }
-#if USB_DEBUG
- if (ohcidebug > 15) {
- ohci_dumpregs(sc);
- }
-#endif
-
- /* The controller is now in SUSPEND state, we have 2ms to finish. */
-
- /* set up HC registers */
- usb2_get_page(&sc->sc_hw.hcca_pc, 0, &buf_res);
- OWRITE4(sc, OHCI_HCCA, buf_res.physaddr);
-
- usb2_get_page(&sc->sc_hw.ctrl_start_pc, 0, &buf_res);
- OWRITE4(sc, OHCI_CONTROL_HEAD_ED, buf_res.physaddr);
-
- usb2_get_page(&sc->sc_hw.bulk_start_pc, 0, &buf_res);
- OWRITE4(sc, OHCI_BULK_HEAD_ED, buf_res.physaddr);
-
- /* disable all interrupts and then switch on all desired interrupts */
- OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
- OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE);
- /* switch on desired functional features */
- ctl = OREAD4(sc, OHCI_CONTROL);
- ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR);
- ctl |= OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE |
- OHCI_RATIO_1_4 | OHCI_HCFS_OPERATIONAL;
- /* And finally start it! */
- OWRITE4(sc, OHCI_CONTROL, ctl);
-
- /*
- * The controller is now OPERATIONAL. Set a some final
- * registers that should be set earlier, but that the
- * controller ignores when in the SUSPEND state.
- */
- fm = (OREAD4(sc, OHCI_FM_INTERVAL) & OHCI_FIT) ^ OHCI_FIT;
- fm |= OHCI_FSMPS(ival) | ival;
- OWRITE4(sc, OHCI_FM_INTERVAL, fm);
- per = OHCI_PERIODIC(ival); /* 90% periodic */
- OWRITE4(sc, OHCI_PERIODIC_START, per);
-
- /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */
- desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
- OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP);
- OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
- usb2_pause_mtx(NULL,
- USB_MS_TO_TICKS(OHCI_ENABLE_POWER_DELAY));
- OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca);
-
- /*
- * The AMD756 requires a delay before re-reading the register,
- * otherwise it will occasionally report 0 ports.
- */
- sc->sc_noport = 0;
- for (i = 0; (i < 10) && (sc->sc_noport == 0); i++) {
- usb2_pause_mtx(NULL,
- USB_MS_TO_TICKS(OHCI_READ_DESC_DELAY));
- sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
- }
-
-#if USB_DEBUG
- if (ohcidebug > 5) {
- ohci_dumpregs(sc);
- }
-#endif
- return (USB_ERR_NORMAL_COMPLETION);
-}
-
-static struct ohci_ed *
-ohci_init_ed(struct usb2_page_cache *pc)
-{
- struct usb2_page_search buf_res;
- struct ohci_ed *ed;
-
- usb2_get_page(pc, 0, &buf_res);
-
- ed = buf_res.buffer;
-
- ed->ed_self = htole32(buf_res.physaddr);
- ed->ed_flags = htole32(OHCI_ED_SKIP);
- ed->page_cache = pc;
-
- return (ed);
-}
-
-usb2_error_t
-ohci_init(ohci_softc_t *sc)
-{
- struct usb2_page_search buf_res;
- uint16_t i;
- uint16_t bit;
- uint16_t x;
- uint16_t y;
-
- DPRINTF("start\n");
-
- sc->sc_eintrs = OHCI_NORMAL_INTRS;
-
- /*
- * Setup all ED's
- */
-
- sc->sc_ctrl_p_last =
- ohci_init_ed(&sc->sc_hw.ctrl_start_pc);
-
- sc->sc_bulk_p_last =
- ohci_init_ed(&sc->sc_hw.bulk_start_pc);
-
- sc->sc_isoc_p_last =
- ohci_init_ed(&sc->sc_hw.isoc_start_pc);
-
- for (i = 0; i != OHCI_NO_EDS; i++) {
- sc->sc_intr_p_last[i] =
- ohci_init_ed(sc->sc_hw.intr_start_pc + i);
- }
-
- /*
- * the QHs are arranged to give poll intervals that are
- * powers of 2 times 1ms
- */
- bit = OHCI_NO_EDS / 2;
- while (bit) {
- x = bit;
- while (x & bit) {
- ohci_ed_t *ed_x;
- ohci_ed_t *ed_y;
-
- y = (x ^ bit) | (bit / 2);
-
- /*
- * the next QH has half the poll interval
- */
- ed_x = sc->sc_intr_p_last[x];
- ed_y = sc->sc_intr_p_last[y];
-
- ed_x->next = NULL;
- ed_x->ed_next = ed_y->ed_self;
-
- x++;
- }
- bit >>= 1;
- }
-
- if (1) {
-
- ohci_ed_t *ed_int;
- ohci_ed_t *ed_isc;
-
- ed_int = sc->sc_intr_p_last[0];
- ed_isc = sc->sc_isoc_p_last;
-
- /* the last (1ms) QH */
- ed_int->next = ed_isc;
- ed_int->ed_next = ed_isc->ed_self;
- }
- usb2_get_page(&sc->sc_hw.hcca_pc, 0, &buf_res);
-
- sc->sc_hcca_p = buf_res.buffer;
-
- /*
- * Fill HCCA interrupt table. The bit reversal is to get
- * the tree set up properly to spread the interrupts.
- */
- for (i = 0; i != OHCI_NO_INTRS; i++) {
- sc->sc_hcca_p->hcca_interrupt_table[i] =
- sc->sc_intr_p_last[i | (OHCI_NO_EDS / 2)]->ed_self;
- }
- /* flush all cache into memory */
-
- usb2_bus_mem_flush_all(&sc->sc_bus, &ohci_iterate_hw_softc);
-
- /* set up the bus struct */
- sc->sc_bus.methods = &ohci_bus_methods;
-
- usb2_callout_init_mtx(&sc->sc_tmo_rhsc, &sc->sc_bus.bus_mtx, 0);
-
-#if USB_DEBUG
- if (ohcidebug > 15) {
- for (i = 0; i != OHCI_NO_EDS; i++) {
- printf("ed#%d ", i);
- ohci_dump_ed(sc->sc_intr_p_last[i]);
- }
- printf("iso ");
- ohci_dump_ed(sc->sc_isoc_p_last);
- }
-#endif
-
- sc->sc_bus.usbrev = USB_REV_1_0;
-
- if (ohci_controller_init(sc)) {
- return (USB_ERR_INVAL);
- } else {
- /* catch any lost interrupts */
- ohci_do_poll(&sc->sc_bus);
- return (USB_ERR_NORMAL_COMPLETION);
- }
-}
-
-/*
- * shut down the controller when the system is going down
- */
-void
-ohci_detach(struct ohci_softc *sc)
-{
- USB_BUS_LOCK(&sc->sc_bus);
-
- usb2_callout_stop(&sc->sc_tmo_rhsc);
-
- OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
- OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- /* XXX let stray task complete */
- usb2_pause_mtx(NULL, hz / 20);
-
- usb2_callout_drain(&sc->sc_tmo_rhsc);
-}
-
-/* NOTE: suspend/resume is called from
- * interrupt context and cannot sleep!
- */
-void
-ohci_suspend(ohci_softc_t *sc)
-{
- uint32_t ctl;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
-#if USB_DEBUG
- DPRINTF("\n");
- if (ohcidebug > 2) {
- ohci_dumpregs(sc);
- }
-#endif
-
- ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK;
- if (sc->sc_control == 0) {
- /*
- * Preserve register values, in case that APM BIOS
- * does not recover them.
- */
- sc->sc_control = ctl;
- sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE);
- }
- ctl |= OHCI_HCFS_SUSPEND;
- OWRITE4(sc, OHCI_CONTROL, ctl);
-
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_WAIT));
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-void
-ohci_resume(ohci_softc_t *sc)
-{
- uint32_t ctl;
-
-#if USB_DEBUG
- DPRINTF("\n");
- if (ohcidebug > 2) {
- ohci_dumpregs(sc);
- }
-#endif
- /* some broken BIOSes never initialize the Controller chip */
- ohci_controller_init(sc);
-
- USB_BUS_LOCK(&sc->sc_bus);
- if (sc->sc_intre) {
- OWRITE4(sc, OHCI_INTERRUPT_ENABLE,
- sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE));
- }
- if (sc->sc_control)
- ctl = sc->sc_control;
- else
- ctl = OREAD4(sc, OHCI_CONTROL);
- ctl |= OHCI_HCFS_RESUME;
- OWRITE4(sc, OHCI_CONTROL, ctl);
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_DELAY));
- ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL;
- OWRITE4(sc, OHCI_CONTROL, ctl);
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_RECOVERY));
- sc->sc_control = sc->sc_intre = 0;
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- /* catch any lost interrupts */
- ohci_do_poll(&sc->sc_bus);
-}
-
-#if USB_DEBUG
-static void
-ohci_dumpregs(ohci_softc_t *sc)
-{
- struct ohci_hcca *hcca;
-
- DPRINTF("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n",
- OREAD4(sc, OHCI_REVISION),
- OREAD4(sc, OHCI_CONTROL),
- OREAD4(sc, OHCI_COMMAND_STATUS));
- DPRINTF(" intrstat=0x%08x intre=0x%08x intrd=0x%08x\n",
- OREAD4(sc, OHCI_INTERRUPT_STATUS),
- OREAD4(sc, OHCI_INTERRUPT_ENABLE),
- OREAD4(sc, OHCI_INTERRUPT_DISABLE));
- DPRINTF(" hcca=0x%08x percur=0x%08x ctrlhd=0x%08x\n",
- OREAD4(sc, OHCI_HCCA),
- OREAD4(sc, OHCI_PERIOD_CURRENT_ED),
- OREAD4(sc, OHCI_CONTROL_HEAD_ED));
- DPRINTF(" ctrlcur=0x%08x bulkhd=0x%08x bulkcur=0x%08x\n",
- OREAD4(sc, OHCI_CONTROL_CURRENT_ED),
- OREAD4(sc, OHCI_BULK_HEAD_ED),
- OREAD4(sc, OHCI_BULK_CURRENT_ED));
- DPRINTF(" done=0x%08x fmival=0x%08x fmrem=0x%08x\n",
- OREAD4(sc, OHCI_DONE_HEAD),
- OREAD4(sc, OHCI_FM_INTERVAL),
- OREAD4(sc, OHCI_FM_REMAINING));
- DPRINTF(" fmnum=0x%08x perst=0x%08x lsthrs=0x%08x\n",
- OREAD4(sc, OHCI_FM_NUMBER),
- OREAD4(sc, OHCI_PERIODIC_START),
- OREAD4(sc, OHCI_LS_THRESHOLD));
- DPRINTF(" desca=0x%08x descb=0x%08x stat=0x%08x\n",
- OREAD4(sc, OHCI_RH_DESCRIPTOR_A),
- OREAD4(sc, OHCI_RH_DESCRIPTOR_B),
- OREAD4(sc, OHCI_RH_STATUS));
- DPRINTF(" port1=0x%08x port2=0x%08x\n",
- OREAD4(sc, OHCI_RH_PORT_STATUS(1)),
- OREAD4(sc, OHCI_RH_PORT_STATUS(2)));
-
- hcca = ohci_get_hcca(sc);
-
- DPRINTF(" HCCA: frame_number=0x%04x done_head=0x%08x\n",
- le32toh(hcca->hcca_frame_number),
- le32toh(hcca->hcca_done_head));
-}
-static void
-ohci_dump_tds(ohci_td_t *std)
-{
- for (; std; std = std->obj_next) {
- if (ohci_dump_td(std)) {
- break;
- }
- }
-}
-
-static uint8_t
-ohci_dump_td(ohci_td_t *std)
-{
- uint32_t td_flags;
- uint8_t temp;
-
- usb2_pc_cpu_invalidate(std->page_cache);
-
- td_flags = le32toh(std->td_flags);
- temp = (std->td_next == 0);
-
- printf("TD(%p) at 0x%08x: %s%s%s%s%s delay=%d ec=%d "
- "cc=%d\ncbp=0x%08x next=0x%08x be=0x%08x\n",
- std, le32toh(std->td_self),
- (td_flags & OHCI_TD_R) ? "-R" : "",
- (td_flags & OHCI_TD_OUT) ? "-OUT" : "",
- (td_flags & OHCI_TD_IN) ? "-IN" : "",
- ((td_flags & OHCI_TD_TOGGLE_MASK) == OHCI_TD_TOGGLE_1) ? "-TOG1" : "",
- ((td_flags & OHCI_TD_TOGGLE_MASK) == OHCI_TD_TOGGLE_0) ? "-TOG0" : "",
- OHCI_TD_GET_DI(td_flags),
- OHCI_TD_GET_EC(td_flags),
- OHCI_TD_GET_CC(td_flags),
- le32toh(std->td_cbp),
- le32toh(std->td_next),
- le32toh(std->td_be));
-
- return (temp);
-}
-
-static uint8_t
-ohci_dump_itd(ohci_itd_t *sitd)
-{
- uint32_t itd_flags;
- uint16_t i;
- uint8_t temp;
-
- usb2_pc_cpu_invalidate(sitd->page_cache);
-
- itd_flags = le32toh(sitd->itd_flags);
- temp = (sitd->itd_next == 0);
-
- printf("ITD(%p) at 0x%08x: sf=%d di=%d fc=%d cc=%d\n"
- "bp0=0x%08x next=0x%08x be=0x%08x\n",
- sitd, le32toh(sitd->itd_self),
- OHCI_ITD_GET_SF(itd_flags),
- OHCI_ITD_GET_DI(itd_flags),
- OHCI_ITD_GET_FC(itd_flags),
- OHCI_ITD_GET_CC(itd_flags),
- le32toh(sitd->itd_bp0),
- le32toh(sitd->itd_next),
- le32toh(sitd->itd_be));
- for (i = 0; i < OHCI_ITD_NOFFSET; i++) {
- printf("offs[%d]=0x%04x ", i,
- (uint32_t)le16toh(sitd->itd_offset[i]));
- }
- printf("\n");
-
- return (temp);
-}
-
-static void
-ohci_dump_itds(ohci_itd_t *sitd)
-{
- for (; sitd; sitd = sitd->obj_next) {
- if (ohci_dump_itd(sitd)) {
- break;
- }
- }
-}
-
-static void
-ohci_dump_ed(ohci_ed_t *sed)
-{
- uint32_t ed_flags;
- uint32_t ed_headp;
-
- usb2_pc_cpu_invalidate(sed->page_cache);
-
- ed_flags = le32toh(sed->ed_flags);
- ed_headp = le32toh(sed->ed_headp);
-
- printf("ED(%p) at 0x%08x: addr=%d endpt=%d maxp=%d flags=%s%s%s%s%s\n"
- "tailp=0x%08x headflags=%s%s headp=0x%08x nexted=0x%08x\n",
- sed, le32toh(sed->ed_self),
- OHCI_ED_GET_FA(ed_flags),
- OHCI_ED_GET_EN(ed_flags),
- OHCI_ED_GET_MAXP(ed_flags),
- (ed_flags & OHCI_ED_DIR_OUT) ? "-OUT" : "",
- (ed_flags & OHCI_ED_DIR_IN) ? "-IN" : "",
- (ed_flags & OHCI_ED_SPEED) ? "-LOWSPEED" : "",
- (ed_flags & OHCI_ED_SKIP) ? "-SKIP" : "",
- (ed_flags & OHCI_ED_FORMAT_ISO) ? "-ISO" : "",
- le32toh(sed->ed_tailp),
- (ed_headp & OHCI_HALTED) ? "-HALTED" : "",
- (ed_headp & OHCI_TOGGLECARRY) ? "-CARRY" : "",
- le32toh(sed->ed_headp),
- le32toh(sed->ed_next));
-}
-
-#endif
-
-static void
-ohci_transfer_intr_enqueue(struct usb2_xfer *xfer)
-{
- /* check for early completion */
- if (ohci_check_transfer(xfer)) {
- return;
- }
- /* put transfer on interrupt queue */
- usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
-
- /* start timeout, if any */
- if (xfer->timeout != 0) {
- usb2_transfer_timeout_ms(xfer, &ohci_timeout, xfer->timeout);
- }
-}
-
-#define OHCI_APPEND_QH(sed,last) (last) = _ohci_append_qh(sed,last)
-static ohci_ed_t *
-_ohci_append_qh(ohci_ed_t *sed, ohci_ed_t *last)
-{
- DPRINTFN(11, "%p to %p\n", sed, last);
-
- if (sed->prev != NULL) {
- /* should not happen */
- DPRINTFN(0, "ED already linked!\n");
- return (last);
- }
- /* (sc->sc_bus.bus_mtx) must be locked */
-
- sed->next = last->next;
- sed->ed_next = last->ed_next;
- sed->ed_tailp = 0;
-
- sed->prev = last;
-
- usb2_pc_cpu_flush(sed->page_cache);
-
- /*
- * the last->next->prev is never followed: sed->next->prev = sed;
- */
-
- last->next = sed;
- last->ed_next = sed->ed_self;
-
- usb2_pc_cpu_flush(last->page_cache);
-
- return (sed);
-}
-
-#define OHCI_REMOVE_QH(sed,last) (last) = _ohci_remove_qh(sed,last)
-static ohci_ed_t *
-_ohci_remove_qh(ohci_ed_t *sed, ohci_ed_t *last)
-{
- DPRINTFN(11, "%p from %p\n", sed, last);
-
- /* (sc->sc_bus.bus_mtx) must be locked */
-
- /* only remove if not removed from a queue */
- if (sed->prev) {
-
- sed->prev->next = sed->next;
- sed->prev->ed_next = sed->ed_next;
-
- usb2_pc_cpu_flush(sed->prev->page_cache);
-
- if (sed->next) {
- sed->next->prev = sed->prev;
- usb2_pc_cpu_flush(sed->next->page_cache);
- }
- last = ((last == sed) ? sed->prev : last);
-
- sed->prev = 0;
-
- usb2_pc_cpu_flush(sed->page_cache);
- }
- return (last);
-}
-
-static void
-ohci_isoc_done(struct usb2_xfer *xfer)
-{
- uint8_t nframes;
- uint32_t *plen = xfer->frlengths;
- volatile uint16_t *olen;
- uint16_t len = 0;
- ohci_itd_t *td = xfer->td_transfer_first;
-
- while (1) {
- if (td == NULL) {
- panic("%s:%d: out of TD's\n",
- __FUNCTION__, __LINE__);
- }
-#if USB_DEBUG
- if (ohcidebug > 5) {
- DPRINTF("isoc TD\n");
- ohci_dump_itd(td);
- }
-#endif
- usb2_pc_cpu_invalidate(td->page_cache);
-
- nframes = td->frames;
- olen = &td->itd_offset[0];
-
- if (nframes > 8) {
- nframes = 8;
- }
- while (nframes--) {
- len = le16toh(*olen);
-
- if ((len >> 12) == OHCI_CC_NOT_ACCESSED) {
- len = 0;
- } else {
- len &= ((1 << 12) - 1);
- }
-
- if (len > *plen) {
- len = 0;/* invalid length */
- }
- *plen = len;
- plen++;
- olen++;
- }
-
- if (((void *)td) == xfer->td_transfer_last) {
- break;
- }
- td = td->obj_next;
- }
-
- xfer->aframes = xfer->nframes;
- ohci_device_done(xfer, USB_ERR_NORMAL_COMPLETION);
-}
-
-#if USB_DEBUG
-static const char *const
- ohci_cc_strs[] =
-{
- "NO_ERROR",
- "CRC",
- "BIT_STUFFING",
- "DATA_TOGGLE_MISMATCH",
-
- "STALL",
- "DEVICE_NOT_RESPONDING",
- "PID_CHECK_FAILURE",
- "UNEXPECTED_PID",
-
- "DATA_OVERRUN",
- "DATA_UNDERRUN",
- "BUFFER_OVERRUN",
- "BUFFER_UNDERRUN",
-
- "reserved",
- "reserved",
- "NOT_ACCESSED",
- "NOT_ACCESSED"
-};
-
-#endif
-
-static usb2_error_t
-ohci_non_isoc_done_sub(struct usb2_xfer *xfer)
-{
- ohci_td_t *td;
- ohci_td_t *td_alt_next;
- uint32_t temp;
- uint32_t phy_start;
- uint32_t phy_end;
- uint32_t td_flags;
- uint16_t cc;
-
- td = xfer->td_transfer_cache;
- td_alt_next = td->alt_next;
- td_flags = 0;
-
- if (xfer->aframes != xfer->nframes) {
- xfer->frlengths[xfer->aframes] = 0;
- }
- while (1) {
-
- usb2_pc_cpu_invalidate(td->page_cache);
- phy_start = le32toh(td->td_cbp);
- td_flags = le32toh(td->td_flags);
- cc = OHCI_TD_GET_CC(td_flags);
-
- if (phy_start) {
- /*
- * short transfer - compute the number of remaining
- * bytes in the hardware buffer:
- */
- phy_end = le32toh(td->td_be);
- temp = (OHCI_PAGE(phy_start ^ phy_end) ?
- (OHCI_PAGE_SIZE + 1) : 0x0001);
- temp += OHCI_PAGE_OFFSET(phy_end);
- temp -= OHCI_PAGE_OFFSET(phy_start);
-
- if (temp > td->len) {
- /* guard against corruption */
- cc = OHCI_CC_STALL;
- } else if (xfer->aframes != xfer->nframes) {
- /*
- * Sum up total transfer length
- * in "frlengths[]":
- */
- xfer->frlengths[xfer->aframes] += td->len - temp;
- }
- } else {
- if (xfer->aframes != xfer->nframes) {
- /* transfer was complete */
- xfer->frlengths[xfer->aframes] += td->len;
- }
- }
- /* Check for last transfer */
- if (((void *)td) == xfer->td_transfer_last) {
- td = NULL;
- break;
- }
- /* Check transfer status */
- if (cc) {
- /* the transfer is finished */
- td = NULL;
- break;
- }
- /* Check for short transfer */
- if (phy_start) {
- if (xfer->flags_int.short_frames_ok) {
- /* follow alt next */
- td = td->alt_next;
- } else {
- /* the transfer is finished */
- td = NULL;
- }
- break;
- }
- td = td->obj_next;
-
- if (td->alt_next != td_alt_next) {
- /* this USB frame is complete */
- break;
- }
- }
-
- /* update transfer cache */
-
- xfer->td_transfer_cache = td;
-
- DPRINTFN(16, "error cc=%d (%s)\n",
- cc, ohci_cc_strs[cc]);
-
- return ((cc == 0) ? USB_ERR_NORMAL_COMPLETION :
- (cc == OHCI_CC_STALL) ? USB_ERR_STALLED : USB_ERR_IOERROR);
-}
-
-static void
-ohci_non_isoc_done(struct usb2_xfer *xfer)
-{
- usb2_error_t err = 0;
-
- DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
-#if USB_DEBUG
- if (ohcidebug > 10) {
- ohci_dump_tds(xfer->td_transfer_first);
- }
-#endif
-
- /* reset scanner */
-
- xfer->td_transfer_cache = xfer->td_transfer_first;
-
- if (xfer->flags_int.control_xfr) {
-
- if (xfer->flags_int.control_hdr) {
-
- err = ohci_non_isoc_done_sub(xfer);
- }
- xfer->aframes = 1;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
- while (xfer->aframes != xfer->nframes) {
-
- err = ohci_non_isoc_done_sub(xfer);
- xfer->aframes++;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- err = ohci_non_isoc_done_sub(xfer);
- }
-done:
- ohci_device_done(xfer, err);
-}
-
-/*------------------------------------------------------------------------*
- * ohci_check_transfer_sub
- *------------------------------------------------------------------------*/
-static void
-ohci_check_transfer_sub(struct usb2_xfer *xfer)
-{
- ohci_td_t *td;
- ohci_ed_t *ed;
- uint32_t phy_start;
- uint32_t td_flags;
- uint32_t td_next;
- uint16_t cc;
-
- td = xfer->td_transfer_cache;
-
- while (1) {
-
- usb2_pc_cpu_invalidate(td->page_cache);
- phy_start = le32toh(td->td_cbp);
- td_flags = le32toh(td->td_flags);
- td_next = le32toh(td->td_next);
-
- /* Check for last transfer */
- if (((void *)td) == xfer->td_transfer_last) {
- /* the transfer is finished */
- td = NULL;
- break;
- }
- /* Check transfer status */
- cc = OHCI_TD_GET_CC(td_flags);
- if (cc) {
- /* the transfer is finished */
- td = NULL;
- break;
- }
- /*
- * Check if we reached the last packet
- * or if there is a short packet:
- */
-
- if (((td_next & (~0xF)) == OHCI_TD_NEXT_END) || phy_start) {
- /* follow alt next */
- td = td->alt_next;
- break;
- }
- td = td->obj_next;
- }
-
- /* update transfer cache */
-
- xfer->td_transfer_cache = td;
-
- if (td) {
-
- ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- ed->ed_headp = td->td_self;
- usb2_pc_cpu_flush(ed->page_cache);
-
- DPRINTFN(13, "xfer=%p following alt next\n", xfer);
- }
-}
-
-/*------------------------------------------------------------------------*
- * ohci_check_transfer
- *
- * Return values:
- * 0: USB transfer is not finished
- * Else: USB transfer is finished
- *------------------------------------------------------------------------*/
-static uint8_t
-ohci_check_transfer(struct usb2_xfer *xfer)
-{
- ohci_ed_t *ed;
- uint32_t ed_flags;
- uint32_t ed_headp;
- uint32_t ed_tailp;
-
- DPRINTFN(13, "xfer=%p checking transfer\n", xfer);
-
- ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- usb2_pc_cpu_invalidate(ed->page_cache);
- ed_flags = le32toh(ed->ed_flags);
- ed_headp = le32toh(ed->ed_headp);
- ed_tailp = le32toh(ed->ed_tailp);
-
- if ((ed_flags & OHCI_ED_SKIP) ||
- (ed_headp & OHCI_HALTED) ||
- (((ed_headp ^ ed_tailp) & (~0xF)) == 0)) {
- if (xfer->pipe->methods == &ohci_device_isoc_methods) {
- /* isochronous transfer */
- ohci_isoc_done(xfer);
- } else {
- if (xfer->flags_int.short_frames_ok) {
- ohci_check_transfer_sub(xfer);
- if (xfer->td_transfer_cache) {
- /* not finished yet */
- return (0);
- }
- }
- /* store data-toggle */
- if (ed_headp & OHCI_TOGGLECARRY) {
- xfer->pipe->toggle_next = 1;
- } else {
- xfer->pipe->toggle_next = 0;
- }
-
- /* non-isochronous transfer */
- ohci_non_isoc_done(xfer);
- }
- return (1);
- }
- DPRINTFN(13, "xfer=%p is still active\n", xfer);
- return (0);
-}
-
-static void
-ohci_rhsc_enable(ohci_softc_t *sc)
-{
- DPRINTFN(5, "\n");
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- sc->sc_eintrs |= OHCI_RHSC;
- OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC);
-
- /* acknowledge any RHSC interrupt */
- OWRITE4(sc, OHCI_INTERRUPT_STATUS, OHCI_RHSC);
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &ohci_root_intr_done);
-}
-
-static void
-ohci_interrupt_poll(ohci_softc_t *sc)
-{
- struct usb2_xfer *xfer;
-
-repeat:
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- /*
- * check if transfer is transferred
- */
- if (ohci_check_transfer(xfer)) {
- /* queue has been modified */
- goto repeat;
- }
- }
-}
-
-/*------------------------------------------------------------------------*
- * ohci_interrupt - OHCI interrupt handler
- *
- * NOTE: Do not access "sc->sc_bus.bdev" inside the interrupt handler,
- * hence the interrupt handler will be setup before "sc->sc_bus.bdev"
- * is present !
- *------------------------------------------------------------------------*/
-void
-ohci_interrupt(ohci_softc_t *sc)
-{
- struct ohci_hcca *hcca;
- uint32_t status;
- uint32_t done;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- hcca = ohci_get_hcca(sc);
-
- DPRINTFN(16, "real interrupt\n");
-
-#if USB_DEBUG
- if (ohcidebug > 15) {
- ohci_dumpregs(sc);
- }
-#endif
-
- done = le32toh(hcca->hcca_done_head);
-
- /*
- * The LSb of done is used to inform the HC Driver that an interrupt
- * condition exists for both the Done list and for another event
- * recorded in HcInterruptStatus. On an interrupt from the HC, the
- * HC Driver checks the HccaDoneHead Value. If this value is 0, then
- * the interrupt was caused by other than the HccaDoneHead update
- * and the HcInterruptStatus register needs to be accessed to
- * determine that exact interrupt cause. If HccaDoneHead is nonzero,
- * then a Done list update interrupt is indicated and if the LSb of
- * done is nonzero, then an additional interrupt event is indicated
- * and HcInterruptStatus should be checked to determine its cause.
- */
- if (done != 0) {
- status = 0;
-
- if (done & ~OHCI_DONE_INTRS) {
- status |= OHCI_WDH;
- }
- if (done & OHCI_DONE_INTRS) {
- status |= OREAD4(sc, OHCI_INTERRUPT_STATUS);
- }
- hcca->hcca_done_head = 0;
-
- usb2_pc_cpu_flush(&sc->sc_hw.hcca_pc);
- } else {
- status = OREAD4(sc, OHCI_INTERRUPT_STATUS) & ~OHCI_WDH;
- }
-
- status &= ~OHCI_MIE;
- if (status == 0) {
- /*
- * nothing to be done (PCI shared
- * interrupt)
- */
- goto done;
- }
- OWRITE4(sc, OHCI_INTERRUPT_STATUS, status); /* Acknowledge */
-
- status &= sc->sc_eintrs;
- if (status == 0) {
- goto done;
- }
- if (status & (OHCI_SO | OHCI_RD | OHCI_UE | OHCI_RHSC)) {
-#if 0
- if (status & OHCI_SO) {
- /* XXX do what */
- }
-#endif
- if (status & OHCI_RD) {
- printf("%s: resume detect\n", __FUNCTION__);
- /* XXX process resume detect */
- }
- if (status & OHCI_UE) {
- printf("%s: unrecoverable error, "
- "controller halted\n", __FUNCTION__);
- OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
- /* XXX what else */
- }
- if (status & OHCI_RHSC) {
- /*
- * Disable RHSC interrupt for now, because it will be
- * on until the port has been reset.
- */
- sc->sc_eintrs &= ~OHCI_RHSC;
- OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_RHSC);
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &ohci_root_intr_done);
-
- /* do not allow RHSC interrupts > 1 per second */
- usb2_callout_reset(&sc->sc_tmo_rhsc, hz,
- (void *)&ohci_rhsc_enable, sc);
- }
- }
- status &= ~(OHCI_RHSC | OHCI_WDH | OHCI_SO);
- if (status != 0) {
- /* Block unprocessed interrupts. XXX */
- OWRITE4(sc, OHCI_INTERRUPT_DISABLE, status);
- sc->sc_eintrs &= ~status;
- printf("%s: blocking intrs 0x%x\n",
- __FUNCTION__, status);
- }
- /* poll all the USB transfers */
- ohci_interrupt_poll(sc);
-
-done:
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-/*
- * called when a request does not complete
- */
-static void
-ohci_timeout(void *arg)
-{
- struct usb2_xfer *xfer = arg;
-
- DPRINTF("xfer=%p\n", xfer);
-
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- /* transfer is transferred */
- ohci_device_done(xfer, USB_ERR_TIMEOUT);
-}
-
-static void
-ohci_do_poll(struct usb2_bus *bus)
-{
- struct ohci_softc *sc = OHCI_BUS2SC(bus);
-
- USB_BUS_LOCK(&sc->sc_bus);
- ohci_interrupt_poll(sc);
- ohci_root_ctrl_poll(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-static void
-ohci_setup_standard_chain_sub(struct ohci_std_temp *temp)
-{
- struct usb2_page_search buf_res;
- ohci_td_t *td;
- ohci_td_t *td_next;
- ohci_td_t *td_alt_next;
- uint32_t buf_offset;
- uint32_t average;
- uint32_t len_old;
- uint8_t shortpkt_old;
- uint8_t precompute;
-
- td_alt_next = NULL;
- buf_offset = 0;
- shortpkt_old = temp->shortpkt;
- len_old = temp->len;
- precompute = 1;
-
- /* software is used to detect short incoming transfers */
-
- if ((temp->td_flags & htole32(OHCI_TD_DP_MASK)) == htole32(OHCI_TD_IN)) {
- temp->td_flags |= htole32(OHCI_TD_R);
- } else {
- temp->td_flags &= ~htole32(OHCI_TD_R);
- }
-
-restart:
-
- td = temp->td;
- td_next = temp->td_next;
-
- while (1) {
-
- if (temp->len == 0) {
-
- if (temp->shortpkt) {
- break;
- }
- /* send a Zero Length Packet, ZLP, last */
-
- temp->shortpkt = 1;
- average = 0;
-
- } else {
-
- average = temp->average;
-
- if (temp->len < average) {
- if (temp->len % temp->max_frame_size) {
- temp->shortpkt = 1;
- }
- average = temp->len;
- }
- }
-
- if (td_next == NULL) {
- panic("%s: out of OHCI transfer descriptors!", __FUNCTION__);
- }
- /* get next TD */
-
- td = td_next;
- td_next = td->obj_next;
-
- /* check if we are pre-computing */
-
- if (precompute) {
-
- /* update remaining length */
-
- temp->len -= average;
-
- continue;
- }
- /* fill out current TD */
- td->td_flags = temp->td_flags;
-
- /* the next TD uses TOGGLE_CARRY */
- temp->td_flags &= ~htole32(OHCI_TD_TOGGLE_MASK);
-
- if (average == 0) {
-
- td->td_cbp = 0;
- td->td_be = ~0;
- td->len = 0;
-
- } else {
-
- usb2_get_page(temp->pc, buf_offset, &buf_res);
- td->td_cbp = htole32(buf_res.physaddr);
- buf_offset += (average - 1);
-
- usb2_get_page(temp->pc, buf_offset, &buf_res);
- td->td_be = htole32(buf_res.physaddr);
- buf_offset++;
-
- td->len = average;
-
- /* update remaining length */
-
- temp->len -= average;
- }
-
- if ((td_next == td_alt_next) && temp->setup_alt_next) {
- /* we need to receive these frames one by one ! */
- td->td_flags &= htole32(~OHCI_TD_INTR_MASK);
- td->td_flags |= htole32(OHCI_TD_SET_DI(1));
- td->td_next = htole32(OHCI_TD_NEXT_END);
- } else {
- if (td_next) {
- /* link the current TD with the next one */
- td->td_next = td_next->td_self;
- }
- }
-
- td->alt_next = td_alt_next;
-
- usb2_pc_cpu_flush(td->page_cache);
- }
-
- if (precompute) {
- precompute = 0;
-
- /* setup alt next pointer, if any */
- if (temp->short_frames_ok) {
- if (temp->setup_alt_next) {
- td_alt_next = td_next;
- }
- } else {
- /* we use this field internally */
- td_alt_next = td_next;
- }
-
- /* restore */
- temp->shortpkt = shortpkt_old;
- temp->len = len_old;
- goto restart;
- }
- temp->td = td;
- temp->td_next = td_next;
-}
-
-static void
-ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
-{
- struct ohci_std_temp temp;
- struct usb2_pipe_methods *methods;
- ohci_ed_t *ed;
- ohci_td_t *td;
- uint32_t ed_flags;
- uint32_t x;
-
- DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
- xfer->address, UE_GET_ADDR(xfer->endpoint),
- xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
-
- temp.average = xfer->max_usb2_frame_size;
- temp.max_frame_size = xfer->max_frame_size;
-
- /* toggle the DMA set we are using */
- xfer->flags_int.curr_dma_set ^= 1;
-
- /* get next DMA set */
- td = xfer->td_start[xfer->flags_int.curr_dma_set];
-
- xfer->td_transfer_first = td;
- xfer->td_transfer_cache = td;
-
- temp.td = NULL;
- temp.td_next = td;
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.short_frames_ok = xfer->flags_int.short_frames_ok;
-
- methods = xfer->pipe->methods;
-
- /* check if we should prepend a setup message */
-
- if (xfer->flags_int.control_xfr) {
- if (xfer->flags_int.control_hdr) {
-
- temp.td_flags = htole32(OHCI_TD_SETUP | OHCI_TD_NOCC |
- OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
-
- temp.len = xfer->frlengths[0];
- temp.pc = xfer->frbuffers + 0;
- temp.shortpkt = temp.len ? 1 : 0;
-
- ohci_setup_standard_chain_sub(&temp);
-
- /*
- * XXX assume that the setup message is
- * contained within one USB packet:
- */
- xfer->pipe->toggle_next = 1;
- }
- x = 1;
- } else {
- x = 0;
- }
- temp.td_flags = htole32(OHCI_TD_NOCC | OHCI_TD_NOINTR);
-
- /* set data toggle */
-
- if (xfer->pipe->toggle_next) {
- temp.td_flags |= htole32(OHCI_TD_TOGGLE_1);
- } else {
- temp.td_flags |= htole32(OHCI_TD_TOGGLE_0);
- }
-
- /* set endpoint direction */
-
- if (UE_GET_DIR(xfer->endpoint) == UE_DIR_IN) {
- temp.td_flags |= htole32(OHCI_TD_IN);
- } else {
- temp.td_flags |= htole32(OHCI_TD_OUT);
- }
-
- while (x != xfer->nframes) {
-
- /* DATA0 / DATA1 message */
-
- temp.len = xfer->frlengths[x];
- temp.pc = xfer->frbuffers + x;
-
- x++;
-
- if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
- }
- if (temp.len == 0) {
-
- /* make sure that we send an USB packet */
-
- temp.shortpkt = 0;
-
- } else {
-
- /* regular data transfer */
-
- temp.shortpkt = (xfer->flags.force_short_xfer) ? 0 : 1;
- }
-
- ohci_setup_standard_chain_sub(&temp);
- }
-
- /* check if we should append a status stage */
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- /*
- * Send a DATA1 message and invert the current endpoint
- * direction.
- */
-
- /* set endpoint direction and data toggle */
-
- if (UE_GET_DIR(xfer->endpoint) == UE_DIR_IN) {
- temp.td_flags = htole32(OHCI_TD_OUT |
- OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
- } else {
- temp.td_flags = htole32(OHCI_TD_IN |
- OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
- }
-
- temp.len = 0;
- temp.pc = NULL;
- temp.shortpkt = 0;
-
- ohci_setup_standard_chain_sub(&temp);
- }
- td = temp.td;
-
- td->td_next = htole32(OHCI_TD_NEXT_END);
- td->td_flags &= ~htole32(OHCI_TD_INTR_MASK);
- td->td_flags |= htole32(OHCI_TD_SET_DI(1));
-
- usb2_pc_cpu_flush(td->page_cache);
-
- /* must have at least one frame! */
-
- xfer->td_transfer_last = td;
-
-#if USB_DEBUG
- if (ohcidebug > 8) {
- DPRINTF("nexttog=%d; data before transfer:\n",
- xfer->pipe->toggle_next);
- ohci_dump_tds(xfer->td_transfer_first);
- }
-#endif
-
- ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- ed_flags = (OHCI_ED_SET_FA(xfer->address) |
- OHCI_ED_SET_EN(UE_GET_ADDR(xfer->endpoint)) |
- OHCI_ED_SET_MAXP(xfer->max_frame_size));
-
- ed_flags |= (OHCI_ED_FORMAT_GEN | OHCI_ED_DIR_TD);
-
- if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
- ed_flags |= OHCI_ED_SPEED;
- }
- ed->ed_flags = htole32(ed_flags);
-
- td = xfer->td_transfer_first;
-
- ed->ed_headp = td->td_self;
-
- if (xfer->xroot->udev->pwr_save.suspended == 0) {
- /* the append function will flush the endpoint descriptor */
- OHCI_APPEND_QH(ed, *ed_last);
-
- if (methods == &ohci_device_bulk_methods) {
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
- }
- if (methods == &ohci_device_ctrl_methods) {
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
- }
- } else {
- usb2_pc_cpu_flush(ed->page_cache);
- }
-}
-
-static void
-ohci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
- uint32_t hstatus;
- uint16_t i;
- uint16_t m;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- ohci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
- /* clear any old interrupt data */
- bzero(sc->sc_hub_idata, sizeof(sc->sc_hub_idata));
-
- hstatus = OREAD4(sc, OHCI_RH_STATUS);
- DPRINTF("sc=%p xfer=%p hstatus=0x%08x\n",
- sc, xfer, hstatus);
-
- /* set bits */
- m = (sc->sc_noport + 1);
- if (m > (8 * sizeof(sc->sc_hub_idata))) {
- m = (8 * sizeof(sc->sc_hub_idata));
- }
- for (i = 1; i < m; i++) {
- /* pick out CHANGE bits from the status register */
- if (OREAD4(sc, OHCI_RH_PORT_STATUS(i)) >> 16) {
- sc->sc_hub_idata[i / 8] |= 1 << (i % 8);
- DPRINTF("port %d changed\n", i);
- }
- }
-done:
- return;
-}
-
-/* NOTE: "done" can be run two times in a row,
- * from close and from interrupt
- */
-static void
-ohci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
-{
- struct usb2_pipe_methods *methods = xfer->pipe->methods;
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
- ohci_ed_t *ed;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
-
- DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
- xfer, xfer->pipe, error);
-
- ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
- if (ed) {
- usb2_pc_cpu_invalidate(ed->page_cache);
- }
- if (methods == &ohci_device_bulk_methods) {
- OHCI_REMOVE_QH(ed, sc->sc_bulk_p_last);
- }
- if (methods == &ohci_device_ctrl_methods) {
- OHCI_REMOVE_QH(ed, sc->sc_ctrl_p_last);
- }
- if (methods == &ohci_device_intr_methods) {
- OHCI_REMOVE_QH(ed, sc->sc_intr_p_last[xfer->qh_pos]);
- }
- if (methods == &ohci_device_isoc_methods) {
- OHCI_REMOVE_QH(ed, sc->sc_isoc_p_last);
- }
- xfer->td_transfer_first = NULL;
- xfer->td_transfer_last = NULL;
-
- /* dequeue transfer and start next transfer */
- usb2_transfer_done(xfer, error);
-}
-
-/*------------------------------------------------------------------------*
- * ohci bulk support
- *------------------------------------------------------------------------*/
-static void
-ohci_device_bulk_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_device_bulk_close(struct usb2_xfer *xfer)
-{
- ohci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ohci_device_bulk_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_device_bulk_start(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- /* setup TD's and QH */
- ohci_setup_standard_chain(xfer, &sc->sc_bulk_p_last);
-
- /* put transfer on interrupt queue */
- ohci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods ohci_device_bulk_methods =
-{
- .open = ohci_device_bulk_open,
- .close = ohci_device_bulk_close,
- .enter = ohci_device_bulk_enter,
- .start = ohci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * ohci control support
- *------------------------------------------------------------------------*/
-static void
-ohci_device_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_device_ctrl_close(struct usb2_xfer *xfer)
-{
- ohci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ohci_device_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_device_ctrl_start(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- /* setup TD's and QH */
- ohci_setup_standard_chain(xfer, &sc->sc_ctrl_p_last);
-
- /* put transfer on interrupt queue */
- ohci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods ohci_device_ctrl_methods =
-{
- .open = ohci_device_ctrl_open,
- .close = ohci_device_ctrl_close,
- .enter = ohci_device_ctrl_enter,
- .start = ohci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * ohci interrupt support
- *------------------------------------------------------------------------*/
-static void
-ohci_device_intr_open(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
- uint16_t best;
- uint16_t bit;
- uint16_t x;
-
- best = 0;
- bit = OHCI_NO_EDS / 2;
- while (bit) {
- if (xfer->interval >= bit) {
- x = bit;
- best = bit;
- while (x & bit) {
- if (sc->sc_intr_stat[x] <
- sc->sc_intr_stat[best]) {
- best = x;
- }
- x++;
- }
- break;
- }
- bit >>= 1;
- }
-
- sc->sc_intr_stat[best]++;
- xfer->qh_pos = best;
-
- DPRINTFN(3, "best=%d interval=%d\n",
- best, xfer->interval);
-}
-
-static void
-ohci_device_intr_close(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_intr_stat[xfer->qh_pos]--;
-
- ohci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ohci_device_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_device_intr_start(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- /* setup TD's and QH */
- ohci_setup_standard_chain(xfer, &sc->sc_intr_p_last[xfer->qh_pos]);
-
- /* put transfer on interrupt queue */
- ohci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods ohci_device_intr_methods =
-{
- .open = ohci_device_intr_open,
- .close = ohci_device_intr_close,
- .enter = ohci_device_intr_enter,
- .start = ohci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * ohci isochronous support
- *------------------------------------------------------------------------*/
-static void
-ohci_device_isoc_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_device_isoc_close(struct usb2_xfer *xfer)
-{
- /**/
- ohci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ohci_device_isoc_enter(struct usb2_xfer *xfer)
-{
- struct usb2_page_search buf_res;
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
- struct ohci_hcca *hcca;
- uint32_t buf_offset;
- uint32_t nframes;
- uint32_t ed_flags;
- uint32_t *plen;
- uint16_t itd_offset[OHCI_ITD_NOFFSET];
- uint16_t length;
- uint8_t ncur;
- ohci_itd_t *td;
- ohci_itd_t *td_last = NULL;
- ohci_ed_t *ed;
-
- hcca = ohci_get_hcca(sc);
-
- nframes = le32toh(hcca->hcca_frame_number);
-
- DPRINTFN(6, "xfer=%p isoc_next=%u nframes=%u hcca_fn=%u\n",
- xfer, xfer->pipe->isoc_next, xfer->nframes, nframes);
-
- if ((xfer->pipe->is_synced == 0) ||
- (((nframes - xfer->pipe->isoc_next) & 0xFFFF) < xfer->nframes) ||
- (((xfer->pipe->isoc_next - nframes) & 0xFFFF) >= 128)) {
- /*
- * If there is data underflow or the pipe queue is empty we
- * schedule the transfer a few frames ahead of the current
- * frame position. Else two isochronous transfers might
- * overlap.
- */
- xfer->pipe->isoc_next = (nframes + 3) & 0xFFFF;
- xfer->pipe->is_synced = 1;
- DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next);
- }
- /*
- * compute how many milliseconds the insertion is ahead of the
- * current frame position:
- */
- buf_offset = ((xfer->pipe->isoc_next - nframes) & 0xFFFF);
-
- /*
- * pre-compute when the isochronous transfer will be finished:
- */
- xfer->isoc_time_complete =
- (usb2_isoc_time_expand(&sc->sc_bus, nframes) + buf_offset +
- xfer->nframes);
-
- /* get the real number of frames */
-
- nframes = xfer->nframes;
-
- buf_offset = 0;
-
- plen = xfer->frlengths;
-
- /* toggle the DMA set we are using */
- xfer->flags_int.curr_dma_set ^= 1;
-
- /* get next DMA set */
- td = xfer->td_start[xfer->flags_int.curr_dma_set];
-
- xfer->td_transfer_first = td;
-
- ncur = 0;
- length = 0;
-
- while (nframes--) {
- if (td == NULL) {
- panic("%s:%d: out of TD's\n",
- __FUNCTION__, __LINE__);
- }
- itd_offset[ncur] = length;
- buf_offset += *plen;
- length += *plen;
- plen++;
- ncur++;
-
- if ( /* check if the ITD is full */
- (ncur == OHCI_ITD_NOFFSET) ||
- /* check if we have put more than 4K into the ITD */
- (length & 0xF000) ||
- /* check if it is the last frame */
- (nframes == 0)) {
-
- /* fill current ITD */
- td->itd_flags = htole32(
- OHCI_ITD_NOCC |
- OHCI_ITD_SET_SF(xfer->pipe->isoc_next) |
- OHCI_ITD_NOINTR |
- OHCI_ITD_SET_FC(ncur));
-
- td->frames = ncur;
- xfer->pipe->isoc_next += ncur;
-
- if (length == 0) {
- /* all zero */
- td->itd_bp0 = 0;
- td->itd_be = ~0;
-
- while (ncur--) {
- td->itd_offset[ncur] =
- htole16(OHCI_ITD_MK_OFFS(0));
- }
- } else {
- usb2_get_page(xfer->frbuffers, buf_offset - length, &buf_res);
- length = OHCI_PAGE_MASK(buf_res.physaddr);
- buf_res.physaddr =
- OHCI_PAGE(buf_res.physaddr);
- td->itd_bp0 = htole32(buf_res.physaddr);
- usb2_get_page(xfer->frbuffers, buf_offset - 1, &buf_res);
- td->itd_be = htole32(buf_res.physaddr);
-
- while (ncur--) {
- itd_offset[ncur] += length;
- itd_offset[ncur] =
- OHCI_ITD_MK_OFFS(itd_offset[ncur]);
- td->itd_offset[ncur] =
- htole16(itd_offset[ncur]);
- }
- }
- ncur = 0;
- length = 0;
- td_last = td;
- td = td->obj_next;
-
- if (td) {
- /* link the last TD with the next one */
- td_last->itd_next = td->itd_self;
- }
- usb2_pc_cpu_flush(td_last->page_cache);
- }
- }
-
- /* update the last TD */
- td_last->itd_flags &= ~htole32(OHCI_ITD_NOINTR);
- td_last->itd_flags |= htole32(OHCI_ITD_SET_DI(0));
- td_last->itd_next = 0;
-
- usb2_pc_cpu_flush(td_last->page_cache);
-
- xfer->td_transfer_last = td_last;
-
-#if USB_DEBUG
- if (ohcidebug > 8) {
- DPRINTF("data before transfer:\n");
- ohci_dump_itds(xfer->td_transfer_first);
- }
-#endif
- ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- if (UE_GET_DIR(xfer->endpoint) == UE_DIR_IN)
- ed_flags = (OHCI_ED_DIR_IN | OHCI_ED_FORMAT_ISO);
- else
- ed_flags = (OHCI_ED_DIR_OUT | OHCI_ED_FORMAT_ISO);
-
- ed_flags |= (OHCI_ED_SET_FA(xfer->address) |
- OHCI_ED_SET_EN(UE_GET_ADDR(xfer->endpoint)) |
- OHCI_ED_SET_MAXP(xfer->max_frame_size));
-
- if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
- ed_flags |= OHCI_ED_SPEED;
- }
- ed->ed_flags = htole32(ed_flags);
-
- td = xfer->td_transfer_first;
-
- ed->ed_headp = td->itd_self;
-
- /* isochronous transfers are not affected by suspend / resume */
- /* the append function will flush the endpoint descriptor */
-
- OHCI_APPEND_QH(ed, sc->sc_isoc_p_last);
-}
-
-static void
-ohci_device_isoc_start(struct usb2_xfer *xfer)
-{
- /* put transfer on interrupt queue */
- ohci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods ohci_device_isoc_methods =
-{
- .open = ohci_device_isoc_open,
- .close = ohci_device_isoc_close,
- .enter = ohci_device_isoc_enter,
- .start = ohci_device_isoc_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * ohci root control support
- *------------------------------------------------------------------------*
- * simulate a hardware hub by handling
- * all the necessary requests
- *------------------------------------------------------------------------*/
-
-static void
-ohci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- ohci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/* data structures and routines
- * to emulate the root hub:
- */
-static const
-struct usb2_device_descriptor ohci_devd =
-{
- sizeof(struct usb2_device_descriptor),
- UDESC_DEVICE, /* type */
- {0x00, 0x01}, /* USB version */
- UDCLASS_HUB, /* class */
- UDSUBCLASS_HUB, /* subclass */
- UDPROTO_FSHUB, /* protocol */
- 64, /* max packet */
- {0}, {0}, {0x00, 0x01}, /* device id */
- 1, 2, 0, /* string indicies */
- 1 /* # of configurations */
-};
-
-static const
-struct ohci_config_desc ohci_confd =
-{
- .confd = {
- .bLength = sizeof(struct usb2_config_descriptor),
- .bDescriptorType = UDESC_CONFIG,
- .wTotalLength[0] = sizeof(ohci_confd),
- .bNumInterface = 1,
- .bConfigurationValue = 1,
- .iConfiguration = 0,
- .bmAttributes = UC_SELF_POWERED,
- .bMaxPower = 0, /* max power */
- },
-
- .ifcd = {
- .bLength = sizeof(struct usb2_interface_descriptor),
- .bDescriptorType = UDESC_INTERFACE,
- .bNumEndpoints = 1,
- .bInterfaceClass = UICLASS_HUB,
- .bInterfaceSubClass = UISUBCLASS_HUB,
- .bInterfaceProtocol = UIPROTO_FSHUB,
- },
-
- .endpd = {
- .bLength = sizeof(struct usb2_endpoint_descriptor),
- .bDescriptorType = UDESC_ENDPOINT,
- .bEndpointAddress = UE_DIR_IN | OHCI_INTR_ENDPT,
- .bmAttributes = UE_INTERRUPT,
- .wMaxPacketSize[0] = 32,/* max packet (255 ports) */
- .bInterval = 255,
- },
-};
-
-static const
-struct usb2_hub_descriptor ohci_hubd =
-{
- 0, /* dynamic length */
- UDESC_HUB,
- 0,
- {0, 0},
- 0,
- 0,
- {0},
-};
-
-static void
-ohci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-ohci_root_ctrl_task(struct usb2_bus *bus)
-{
- ohci_root_ctrl_poll(OHCI_BUS2SC(bus));
-}
-
-static void
-ohci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
- char *ptr;
- uint32_t port;
- uint32_t v;
- uint16_t value;
- uint16_t index;
- uint8_t l;
- uint8_t use_polling;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- ohci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* buffer reset */
- std->ptr = sc->sc_hub_desc.temp;
- std->len = 0;
-
- value = UGETW(std->req.wValue);
- index = UGETW(std->req.wIndex);
-
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- DPRINTFN(3, "type=0x%02x request=0x%02x wLen=0x%04x "
- "wValue=0x%04x wIndex=0x%04x\n",
- std->req.bmRequestType, std->req.bRequest,
- UGETW(std->req.wLength), value, index);
-
-#define C(x,y) ((x) | ((y) << 8))
- switch (C(std->req.bRequest, std->req.bmRequestType)) {
- case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
- case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
- case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
- /*
- * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
- * for the integrated root hub.
- */
- break;
- case C(UR_GET_CONFIG, UT_READ_DEVICE):
- std->len = 1;
- sc->sc_hub_desc.temp[0] = sc->sc_conf;
- break;
- case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
- switch (value >> 8) {
- case UDESC_DEVICE:
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- std->len = sizeof(ohci_devd);
- sc->sc_hub_desc.devd = ohci_devd;
- break;
-
- case UDESC_CONFIG:
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- std->len = sizeof(ohci_confd);
- std->ptr = USB_ADD_BYTES(&ohci_confd, 0);
- break;
-
- case UDESC_STRING:
- switch (value & 0xff) {
- case 0: /* Language table */
- ptr = "\001";
- break;
-
- case 1: /* Vendor */
- ptr = sc->sc_vendor;
- break;
-
- case 2: /* Product */
- ptr = "OHCI root HUB";
- break;
-
- default:
- ptr = "";
- break;
- }
-
- std->len = usb2_make_str_desc
- (sc->sc_hub_desc.temp,
- sizeof(sc->sc_hub_desc.temp),
- ptr);
- break;
-
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- break;
- case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
- std->len = 1;
- sc->sc_hub_desc.temp[0] = 0;
- break;
- case C(UR_GET_STATUS, UT_READ_DEVICE):
- std->len = 2;
- USETW(sc->sc_hub_desc.stat.wStatus, UDS_SELF_POWERED);
- break;
- case C(UR_GET_STATUS, UT_READ_INTERFACE):
- case C(UR_GET_STATUS, UT_READ_ENDPOINT):
- std->len = 2;
- USETW(sc->sc_hub_desc.stat.wStatus, 0);
- break;
- case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
- if (value >= USB_MAX_DEVICES) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- sc->sc_addr = value;
- break;
- case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
- if ((value != 0) && (value != 1)) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- sc->sc_conf = value;
- break;
- case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
- break;
- case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
- case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
- case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
- std->err = USB_ERR_IOERROR;
- goto done;
- case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
- break;
- case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
- break;
- /* Hub requests */
- case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
- break;
- case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
- DPRINTFN(9, "UR_CLEAR_PORT_FEATURE "
- "port=%d feature=%d\n",
- index, value);
- if ((index < 1) ||
- (index > sc->sc_noport)) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- port = OHCI_RH_PORT_STATUS(index);
- switch (value) {
- case UHF_PORT_ENABLE:
- OWRITE4(sc, port, UPS_CURRENT_CONNECT_STATUS);
- break;
- case UHF_PORT_SUSPEND:
- OWRITE4(sc, port, UPS_OVERCURRENT_INDICATOR);
- break;
- case UHF_PORT_POWER:
- /* Yes, writing to the LOW_SPEED bit clears power. */
- OWRITE4(sc, port, UPS_LOW_SPEED);
- break;
- case UHF_C_PORT_CONNECTION:
- OWRITE4(sc, port, UPS_C_CONNECT_STATUS << 16);
- break;
- case UHF_C_PORT_ENABLE:
- OWRITE4(sc, port, UPS_C_PORT_ENABLED << 16);
- break;
- case UHF_C_PORT_SUSPEND:
- OWRITE4(sc, port, UPS_C_SUSPEND << 16);
- break;
- case UHF_C_PORT_OVER_CURRENT:
- OWRITE4(sc, port, UPS_C_OVERCURRENT_INDICATOR << 16);
- break;
- case UHF_C_PORT_RESET:
- OWRITE4(sc, port, UPS_C_PORT_RESET << 16);
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- switch (value) {
- case UHF_C_PORT_CONNECTION:
- case UHF_C_PORT_ENABLE:
- case UHF_C_PORT_SUSPEND:
- case UHF_C_PORT_OVER_CURRENT:
- case UHF_C_PORT_RESET:
- /* enable RHSC interrupt if condition is cleared. */
- if ((OREAD4(sc, port) >> 16) == 0)
- ohci_rhsc_enable(sc);
- break;
- default:
- break;
- }
- break;
- case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
-
- sc->sc_hub_desc.hubd = ohci_hubd;
- sc->sc_hub_desc.hubd.bNbrPorts = sc->sc_noport;
- USETW(sc->sc_hub_desc.hubd.wHubCharacteristics,
- (v & OHCI_NPS ? UHD_PWR_NO_SWITCH :
- v & OHCI_PSM ? UHD_PWR_GANGED : UHD_PWR_INDIVIDUAL)
- /* XXX overcurrent */
- );
- sc->sc_hub_desc.hubd.bPwrOn2PwrGood = OHCI_GET_POTPGT(v);
- v = OREAD4(sc, OHCI_RH_DESCRIPTOR_B);
-
- for (l = 0; l < sc->sc_noport; l++) {
- if (v & 1) {
- sc->sc_hub_desc.hubd.DeviceRemovable[l / 8] |= (1 << (l % 8));
- }
- v >>= 1;
- }
- sc->sc_hub_desc.hubd.bDescLength =
- 8 + ((sc->sc_noport + 7) / 8);
- std->len = sc->sc_hub_desc.hubd.bDescLength;
- break;
-
- case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
- std->len = 16;
- bzero(sc->sc_hub_desc.temp, 16);
- break;
- case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
- DPRINTFN(9, "get port status i=%d\n",
- index);
- if ((index < 1) ||
- (index > sc->sc_noport)) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- v = OREAD4(sc, OHCI_RH_PORT_STATUS(index));
- DPRINTFN(9, "port status=0x%04x\n", v);
- USETW(sc->sc_hub_desc.ps.wPortStatus, v);
- USETW(sc->sc_hub_desc.ps.wPortChange, v >> 16);
- std->len = sizeof(sc->sc_hub_desc.ps);
- break;
- case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
- std->err = USB_ERR_IOERROR;
- goto done;
- case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
- break;
- case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
- if ((index < 1) ||
- (index > sc->sc_noport)) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- port = OHCI_RH_PORT_STATUS(index);
- switch (value) {
- case UHF_PORT_ENABLE:
- OWRITE4(sc, port, UPS_PORT_ENABLED);
- break;
- case UHF_PORT_SUSPEND:
- OWRITE4(sc, port, UPS_SUSPEND);
- break;
- case UHF_PORT_RESET:
- DPRINTFN(6, "reset port %d\n", index);
- OWRITE4(sc, port, UPS_RESET);
- for (v = 0;; v++) {
- if (v < 12) {
- if (use_polling) {
- /* polling */
- DELAY(USB_PORT_ROOT_RESET_DELAY * 1000);
- } else {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_PORT_ROOT_RESET_DELAY));
- }
-
- if ((OREAD4(sc, port) & UPS_RESET) == 0) {
- break;
- }
- } else {
- std->err = USB_ERR_TIMEOUT;
- goto done;
- }
- }
- DPRINTFN(9, "ohci port %d reset, status = 0x%04x\n",
- index, OREAD4(sc, port));
- break;
- case UHF_PORT_POWER:
- DPRINTFN(3, "set port power %d\n", index);
- OWRITE4(sc, port, UPS_PORT_POWER);
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
-done:
- return;
-}
-
-static void
-ohci_root_ctrl_poll(struct ohci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &ohci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods ohci_root_ctrl_methods =
-{
- .open = ohci_root_ctrl_open,
- .close = ohci_root_ctrl_close,
- .enter = ohci_root_ctrl_enter,
- .start = ohci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * ohci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-ohci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_root_intr_close(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- ohci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ohci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_root_intr_start(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods ohci_root_intr_methods =
-{
- .open = ohci_root_intr_open,
- .close = ohci_root_intr_close,
- .enter = ohci_root_intr_enter,
- .start = ohci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
-ohci_xfer_setup(struct usb2_setup_params *parm)
-{
- struct usb2_page_search page_info;
- struct usb2_page_cache *pc;
- ohci_softc_t *sc;
- struct usb2_xfer *xfer;
- void *last_obj;
- uint32_t ntd;
- uint32_t nitd;
- uint32_t nqh;
- uint32_t n;
-
- sc = OHCI_BUS2SC(parm->udev->bus);
- xfer = parm->curr_xfer;
-
- parm->hc_max_packet_size = 0x500;
- parm->hc_max_packet_count = 1;
- parm->hc_max_frame_size = OHCI_PAGE_SIZE;
-
- /*
- * calculate ntd and nqh
- */
- if (parm->methods == &ohci_device_ctrl_methods) {
- xfer->flags_int.bdma_enable = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nitd = 0;
- ntd = ((2 * xfer->nframes) + 1 /* STATUS */
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
- nqh = 1;
-
- } else if (parm->methods == &ohci_device_bulk_methods) {
- xfer->flags_int.bdma_enable = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nitd = 0;
- ntd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
- nqh = 1;
-
- } else if (parm->methods == &ohci_device_intr_methods) {
- xfer->flags_int.bdma_enable = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nitd = 0;
- ntd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
- nqh = 1;
-
- } else if (parm->methods == &ohci_device_isoc_methods) {
- xfer->flags_int.bdma_enable = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nitd = ((xfer->max_data_length / OHCI_PAGE_SIZE) +
- ((xfer->nframes + OHCI_ITD_NOFFSET - 1) / OHCI_ITD_NOFFSET) +
- 1 /* EXTRA */ );
- ntd = 0;
- nqh = 1;
-
- } else {
-
- usb2_transfer_setup_sub(parm);
-
- nitd = 0;
- ntd = 0;
- nqh = 0;
- }
-
-alloc_dma_set:
-
- if (parm->err) {
- return;
- }
- last_obj = NULL;
-
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, sizeof(ohci_td_t),
- OHCI_TD_ALIGN, ntd)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- if (parm->buf) {
- for (n = 0; n != ntd; n++) {
- ohci_td_t *td;
-
- usb2_get_page(pc + n, 0, &page_info);
-
- td = page_info.buffer;
-
- /* init TD */
- td->td_self = htole32(page_info.physaddr);
- td->obj_next = last_obj;
- td->page_cache = pc + n;
-
- last_obj = td;
-
- usb2_pc_cpu_flush(pc + n);
- }
- }
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, sizeof(ohci_itd_t),
- OHCI_ITD_ALIGN, nitd)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- if (parm->buf) {
- for (n = 0; n != nitd; n++) {
- ohci_itd_t *itd;
-
- usb2_get_page(pc + n, 0, &page_info);
-
- itd = page_info.buffer;
-
- /* init TD */
- itd->itd_self = htole32(page_info.physaddr);
- itd->obj_next = last_obj;
- itd->page_cache = pc + n;
-
- last_obj = itd;
-
- usb2_pc_cpu_flush(pc + n);
- }
- }
- xfer->td_start[xfer->flags_int.curr_dma_set] = last_obj;
-
- last_obj = NULL;
-
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, sizeof(ohci_ed_t),
- OHCI_ED_ALIGN, nqh)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- if (parm->buf) {
- for (n = 0; n != nqh; n++) {
- ohci_ed_t *ed;
-
- usb2_get_page(pc + n, 0, &page_info);
-
- ed = page_info.buffer;
-
- /* init QH */
- ed->ed_self = htole32(page_info.physaddr);
- ed->obj_next = last_obj;
- ed->page_cache = pc + n;
-
- last_obj = ed;
-
- usb2_pc_cpu_flush(pc + n);
- }
- }
- xfer->qh_start[xfer->flags_int.curr_dma_set] = last_obj;
-
- if (!xfer->flags_int.curr_dma_set) {
- xfer->flags_int.curr_dma_set = 1;
- goto alloc_dma_set;
- }
-}
-
-static void
-ohci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
- struct usb2_pipe *pipe)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(udev->bus);
-
- DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
- pipe, udev->address,
- edesc->bEndpointAddress, udev->flags.usb2_mode,
- sc->sc_addr);
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- if (udev->device_index == sc->sc_addr) {
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &ohci_root_ctrl_methods;
- break;
- case UE_DIR_IN | OHCI_INTR_ENDPT:
- pipe->methods = &ohci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
- switch (edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- pipe->methods = &ohci_device_ctrl_methods;
- break;
- case UE_INTERRUPT:
- pipe->methods = &ohci_device_intr_methods;
- break;
- case UE_ISOCHRONOUS:
- if (udev->speed == USB_SPEED_FULL) {
- pipe->methods = &ohci_device_isoc_methods;
- }
- break;
- case UE_BULK:
- if (udev->speed != USB_SPEED_LOW) {
- pipe->methods = &ohci_device_bulk_methods;
- }
- break;
- default:
- /* do nothing */
- break;
- }
- }
-}
-
-static void
-ohci_xfer_unsetup(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_get_dma_delay(struct usb2_bus *bus, uint32_t *pus)
-{
- /*
- * Wait until hardware has finished any possible use of the
- * transfer descriptor(s) and QH
- */
- *pus = (1125); /* microseconds */
-}
-
-static void
-ohci_device_resume(struct usb2_device *udev)
-{
- struct ohci_softc *sc = OHCI_BUS2SC(udev->bus);
- struct usb2_xfer *xfer;
- struct usb2_pipe_methods *methods;
- ohci_ed_t *ed;
-
- DPRINTF("\n");
-
- USB_BUS_LOCK(udev->bus);
-
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-
- if (xfer->xroot->udev == udev) {
-
- methods = xfer->pipe->methods;
- ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- if (methods == &ohci_device_bulk_methods) {
- OHCI_APPEND_QH(ed, sc->sc_bulk_p_last);
- OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
- }
- if (methods == &ohci_device_ctrl_methods) {
- OHCI_APPEND_QH(ed, sc->sc_ctrl_p_last);
- OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
- }
- if (methods == &ohci_device_intr_methods) {
- OHCI_APPEND_QH(ed, sc->sc_intr_p_last[xfer->qh_pos]);
- }
- }
- }
-
- USB_BUS_UNLOCK(udev->bus);
-
- return;
-}
-
-static void
-ohci_device_suspend(struct usb2_device *udev)
-{
- struct ohci_softc *sc = OHCI_BUS2SC(udev->bus);
- struct usb2_xfer *xfer;
- struct usb2_pipe_methods *methods;
- ohci_ed_t *ed;
-
- DPRINTF("\n");
-
- USB_BUS_LOCK(udev->bus);
-
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-
- if (xfer->xroot->udev == udev) {
-
- methods = xfer->pipe->methods;
- ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- if (methods == &ohci_device_bulk_methods) {
- OHCI_REMOVE_QH(ed, sc->sc_bulk_p_last);
- }
- if (methods == &ohci_device_ctrl_methods) {
- OHCI_REMOVE_QH(ed, sc->sc_ctrl_p_last);
- }
- if (methods == &ohci_device_intr_methods) {
- OHCI_REMOVE_QH(ed, sc->sc_intr_p_last[xfer->qh_pos]);
- }
- }
- }
-
- USB_BUS_UNLOCK(udev->bus);
-
- return;
-}
-
-static void
-ohci_set_hw_power(struct usb2_bus *bus)
-{
- struct ohci_softc *sc = OHCI_BUS2SC(bus);
- uint32_t temp;
- uint32_t flags;
-
- DPRINTF("\n");
-
- USB_BUS_LOCK(bus);
-
- flags = bus->hw_power_state;
-
- temp = OREAD4(sc, OHCI_CONTROL);
- temp &= ~(OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE);
-
- if (flags & USB_HW_POWER_CONTROL)
- temp |= OHCI_CLE;
-
- if (flags & USB_HW_POWER_BULK)
- temp |= OHCI_BLE;
-
- if (flags & USB_HW_POWER_INTERRUPT)
- temp |= OHCI_PLE;
-
- if (flags & USB_HW_POWER_ISOC)
- temp |= OHCI_IE | OHCI_PLE;
-
- OWRITE4(sc, OHCI_CONTROL, temp);
-
- USB_BUS_UNLOCK(bus);
-
- return;
-}
-
-struct usb2_bus_methods ohci_bus_methods =
-{
- .pipe_init = ohci_pipe_init,
- .xfer_setup = ohci_xfer_setup,
- .xfer_unsetup = ohci_xfer_unsetup,
- .do_poll = ohci_do_poll,
- .get_dma_delay = ohci_get_dma_delay,
- .device_resume = ohci_device_resume,
- .device_suspend = ohci_device_suspend,
- .set_hw_power = ohci_set_hw_power,
- .roothub_exec = ohci_root_ctrl_task,
-};
diff --git a/sys/dev/usb2/controller/ohci2.h b/sys/dev/usb2/controller/ohci2.h
deleted file mode 100644
index 84a6afd..0000000
--- a/sys/dev/usb2/controller/ohci2.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (lennart@augustsson.net) at
- * Carlstedt Research & Technology.
- *
- * 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.
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``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 FOUNDATION OR CONTRIBUTORS
- * 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.
- */
-
-#ifndef _OHCI_H_
-#define _OHCI_H_
-
-#define OHCI_MAX_DEVICES USB_MAX_DEVICES
-
-/* PCI config registers */
-#define PCI_CBMEM 0x10 /* configuration base memory */
-#define PCI_INTERFACE_OHCI 0x10
-
-/* OHCI registers */
-#define OHCI_REVISION 0x00 /* OHCI revision */
-#define OHCI_REV_LO(rev) ((rev) & 0xf)
-#define OHCI_REV_HI(rev) (((rev)>>4) & 0xf)
-#define OHCI_REV_LEGACY(rev) ((rev) & 0x100)
-#define OHCI_CONTROL 0x04
-#define OHCI_CBSR_MASK 0x00000003 /* Control/Bulk Service Ratio */
-#define OHCI_RATIO_1_1 0x00000000
-#define OHCI_RATIO_1_2 0x00000001
-#define OHCI_RATIO_1_3 0x00000002
-#define OHCI_RATIO_1_4 0x00000003
-#define OHCI_PLE 0x00000004 /* Periodic List Enable */
-#define OHCI_IE 0x00000008 /* Isochronous Enable */
-#define OHCI_CLE 0x00000010 /* Control List Enable */
-#define OHCI_BLE 0x00000020 /* Bulk List Enable */
-#define OHCI_HCFS_MASK 0x000000c0 /* HostControllerFunctionalStat
- * e */
-#define OHCI_HCFS_RESET 0x00000000
-#define OHCI_HCFS_RESUME 0x00000040
-#define OHCI_HCFS_OPERATIONAL 0x00000080
-#define OHCI_HCFS_SUSPEND 0x000000c0
-#define OHCI_IR 0x00000100 /* Interrupt Routing */
-#define OHCI_RWC 0x00000200 /* Remote Wakeup Connected */
-#define OHCI_RWE 0x00000400 /* Remote Wakeup Enabled */
-#define OHCI_COMMAND_STATUS 0x08
-#define OHCI_HCR 0x00000001 /* Host Controller Reset */
-#define OHCI_CLF 0x00000002 /* Control List Filled */
-#define OHCI_BLF 0x00000004 /* Bulk List Filled */
-#define OHCI_OCR 0x00000008 /* Ownership Change Request */
-#define OHCI_SOC_MASK 0x00030000 /* Scheduling Overrun Count */
-#define OHCI_INTERRUPT_STATUS 0x0c
-#define OHCI_SO 0x00000001 /* Scheduling Overrun */
-#define OHCI_WDH 0x00000002 /* Writeback Done Head */
-#define OHCI_SF 0x00000004 /* Start of Frame */
-#define OHCI_RD 0x00000008 /* Resume Detected */
-#define OHCI_UE 0x00000010 /* Unrecoverable Error */
-#define OHCI_FNO 0x00000020 /* Frame Number Overflow */
-#define OHCI_RHSC 0x00000040 /* Root Hub Status Change */
-#define OHCI_OC 0x40000000 /* Ownership Change */
-#define OHCI_MIE 0x80000000 /* Master Interrupt Enable */
-#define OHCI_INTERRUPT_ENABLE 0x10
-#define OHCI_INTERRUPT_DISABLE 0x14
-#define OHCI_HCCA 0x18
-#define OHCI_PERIOD_CURRENT_ED 0x1c
-#define OHCI_CONTROL_HEAD_ED 0x20
-#define OHCI_CONTROL_CURRENT_ED 0x24
-#define OHCI_BULK_HEAD_ED 0x28
-#define OHCI_BULK_CURRENT_ED 0x2c
-#define OHCI_DONE_HEAD 0x30
-#define OHCI_FM_INTERVAL 0x34
-#define OHCI_GET_IVAL(s) ((s) & 0x3fff)
-#define OHCI_GET_FSMPS(s) (((s) >> 16) & 0x7fff)
-#define OHCI_FIT 0x80000000
-#define OHCI_FM_REMAINING 0x38
-#define OHCI_FM_NUMBER 0x3c
-#define OHCI_PERIODIC_START 0x40
-#define OHCI_LS_THRESHOLD 0x44
-#define OHCI_RH_DESCRIPTOR_A 0x48
-#define OHCI_GET_NDP(s) ((s) & 0xff)
-#define OHCI_PSM 0x0100 /* Power Switching Mode */
-#define OHCI_NPS 0x0200 /* No Power Switching */
-#define OHCI_DT 0x0400 /* Device Type */
-#define OHCI_OCPM 0x0800 /* Overcurrent Protection Mode */
-#define OHCI_NOCP 0x1000 /* No Overcurrent Protection */
-#define OHCI_GET_POTPGT(s) ((s) >> 24)
-#define OHCI_RH_DESCRIPTOR_B 0x4c
-#define OHCI_RH_STATUS 0x50
-#define OHCI_LPS 0x00000001 /* Local Power Status */
-#define OHCI_OCI 0x00000002 /* OverCurrent Indicator */
-#define OHCI_DRWE 0x00008000 /* Device Remote Wakeup Enable */
-#define OHCI_LPSC 0x00010000 /* Local Power Status Change */
-#define OHCI_CCIC 0x00020000 /* OverCurrent Indicator
- * Change */
-#define OHCI_CRWE 0x80000000 /* Clear Remote Wakeup Enable */
-#define OHCI_RH_PORT_STATUS(n) (0x50 + ((n)*4)) /* 1 based indexing */
-
-#define OHCI_LES (OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE)
-#define OHCI_ALL_INTRS (OHCI_SO | OHCI_WDH | OHCI_SF | \
- OHCI_RD | OHCI_UE | OHCI_FNO | \
- OHCI_RHSC | OHCI_OC)
-#define OHCI_NORMAL_INTRS (OHCI_WDH | OHCI_RD | OHCI_UE | OHCI_RHSC)
-
-#define OHCI_FSMPS(i) (((i-210)*6/7) << 16)
-#define OHCI_PERIODIC(i) ((i)*9/10)
-
-#define OHCI_NO_INTRS 32
-#define OHCI_HCCA_SIZE 256
-
-/* Structures alignment (bytes) */
-#define OHCI_HCCA_ALIGN 256
-#define OHCI_ED_ALIGN 16
-#define OHCI_TD_ALIGN 16
-#define OHCI_ITD_ALIGN 32
-
-#define OHCI_PAGE_SIZE 0x1000
-#define OHCI_PAGE(x) ((x) &~ 0xfff)
-#define OHCI_PAGE_OFFSET(x) ((x) & 0xfff)
-#define OHCI_PAGE_MASK(x) ((x) & 0xfff)
-
-#if ((USB_PAGE_SIZE < OHCI_ED_ALIGN) || (OHCI_ED_ALIGN == 0) || \
- (USB_PAGE_SIZE < OHCI_TD_ALIGN) || (OHCI_TD_ALIGN == 0) || \
- (USB_PAGE_SIZE < OHCI_ITD_ALIGN) || (OHCI_ITD_ALIGN == 0) || \
- (USB_PAGE_SIZE < OHCI_PAGE_SIZE) || (OHCI_PAGE_SIZE == 0))
-#error "Invalid USB page size!"
-#endif
-
-#define OHCI_VIRTUAL_FRAMELIST_COUNT 128/* dummy */
-
-#if (OHCI_VIRTUAL_FRAMELIST_COUNT < USB_MAX_FS_ISOC_FRAMES_PER_XFER)
-#error "maximum number of full-speed isochronous frames is higher than supported!"
-#endif
-
-struct ohci_hcca {
- volatile uint32_t hcca_interrupt_table[OHCI_NO_INTRS];
- volatile uint32_t hcca_frame_number;
- volatile uint32_t hcca_done_head;
-#define OHCI_DONE_INTRS 1
-} __aligned(OHCI_HCCA_ALIGN);
-
-typedef struct ohci_hcca ohci_hcca_t;
-
-struct ohci_ed {
- volatile uint32_t ed_flags;
-#define OHCI_ED_GET_FA(s) ((s) & 0x7f)
-#define OHCI_ED_ADDRMASK 0x0000007f
-#define OHCI_ED_SET_FA(s) (s)
-#define OHCI_ED_GET_EN(s) (((s) >> 7) & 0xf)
-#define OHCI_ED_SET_EN(s) ((s) << 7)
-#define OHCI_ED_DIR_MASK 0x00001800
-#define OHCI_ED_DIR_TD 0x00000000
-#define OHCI_ED_DIR_OUT 0x00000800
-#define OHCI_ED_DIR_IN 0x00001000
-#define OHCI_ED_SPEED 0x00002000
-#define OHCI_ED_SKIP 0x00004000
-#define OHCI_ED_FORMAT_GEN 0x00000000
-#define OHCI_ED_FORMAT_ISO 0x00008000
-#define OHCI_ED_GET_MAXP(s) (((s) >> 16) & 0x07ff)
-#define OHCI_ED_SET_MAXP(s) ((s) << 16)
-#define OHCI_ED_MAXPMASK (0x7ff << 16)
- volatile uint32_t ed_tailp;
- volatile uint32_t ed_headp;
-#define OHCI_HALTED 0x00000001
-#define OHCI_TOGGLECARRY 0x00000002
-#define OHCI_HEADMASK 0xfffffffc
- volatile uint32_t ed_next;
-/*
- * Extra information needed:
- */
- struct ohci_ed *next;
- struct ohci_ed *prev;
- struct ohci_ed *obj_next;
- struct usb2_page_cache *page_cache;
- uint32_t ed_self;
-} __aligned(OHCI_ED_ALIGN);
-
-typedef struct ohci_ed ohci_ed_t;
-
-struct ohci_td {
- volatile uint32_t td_flags;
-#define OHCI_TD_R 0x00040000 /* Buffer Rounding */
-#define OHCI_TD_DP_MASK 0x00180000 /* Direction / PID */
-#define OHCI_TD_SETUP 0x00000000
-#define OHCI_TD_OUT 0x00080000
-#define OHCI_TD_IN 0x00100000
-#define OHCI_TD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */
-#define OHCI_TD_SET_DI(x) ((x) << 21)
-#define OHCI_TD_NOINTR 0x00e00000
-#define OHCI_TD_INTR_MASK 0x00e00000
-#define OHCI_TD_TOGGLE_CARRY 0x00000000
-#define OHCI_TD_TOGGLE_0 0x02000000
-#define OHCI_TD_TOGGLE_1 0x03000000
-#define OHCI_TD_TOGGLE_MASK 0x03000000
-#define OHCI_TD_GET_EC(x) (((x) >> 26) & 3) /* Error Count */
-#define OHCI_TD_GET_CC(x) ((x) >> 28) /* Condition Code */
-#define OHCI_TD_SET_CC(x) ((x) << 28)
-#define OHCI_TD_NOCC 0xf0000000
- volatile uint32_t td_cbp; /* Current Buffer Pointer */
- volatile uint32_t td_next; /* Next TD */
-#define OHCI_TD_NEXT_END 0
- volatile uint32_t td_be; /* Buffer End */
-/*
- * Extra information needed:
- */
- struct ohci_td *obj_next;
- struct ohci_td *alt_next;
- struct usb2_page_cache *page_cache;
- uint32_t td_self;
- uint16_t len;
-} __aligned(OHCI_TD_ALIGN);
-
-typedef struct ohci_td ohci_td_t;
-
-struct ohci_itd {
- volatile uint32_t itd_flags;
-#define OHCI_ITD_GET_SF(x) ((x) & 0x0000ffff)
-#define OHCI_ITD_SET_SF(x) ((x) & 0xffff)
-#define OHCI_ITD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */
-#define OHCI_ITD_SET_DI(x) ((x) << 21)
-#define OHCI_ITD_NOINTR 0x00e00000
-#define OHCI_ITD_GET_FC(x) ((((x) >> 24) & 7)+1) /* Frame Count */
-#define OHCI_ITD_SET_FC(x) (((x)-1) << 24)
-#define OHCI_ITD_GET_CC(x) ((x) >> 28) /* Condition Code */
-#define OHCI_ITD_NOCC 0xf0000000
-#define OHCI_ITD_NOFFSET 8
- volatile uint32_t itd_bp0; /* Buffer Page 0 */
- volatile uint32_t itd_next; /* Next ITD */
- volatile uint32_t itd_be; /* Buffer End */
- volatile uint16_t itd_offset[OHCI_ITD_NOFFSET]; /* Buffer offsets and
- * Status */
-#define OHCI_ITD_PAGE_SELECT 0x00001000
-#define OHCI_ITD_MK_OFFS(len) (0xe000 | ((len) & 0x1fff))
-#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff) /* Transfer length */
-#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12) /* Condition Code */
-/*
- * Extra information needed:
- */
- struct ohci_itd *obj_next;
- struct usb2_page_cache *page_cache;
- uint32_t itd_self;
- uint8_t frames;
-} __aligned(OHCI_ITD_ALIGN);
-
-typedef struct ohci_itd ohci_itd_t;
-
-#define OHCI_CC_NO_ERROR 0
-#define OHCI_CC_CRC 1
-#define OHCI_CC_BIT_STUFFING 2
-#define OHCI_CC_DATA_TOGGLE_MISMATCH 3
-#define OHCI_CC_STALL 4
-#define OHCI_CC_DEVICE_NOT_RESPONDING 5
-#define OHCI_CC_PID_CHECK_FAILURE 6
-#define OHCI_CC_UNEXPECTED_PID 7
-#define OHCI_CC_DATA_OVERRUN 8
-#define OHCI_CC_DATA_UNDERRUN 9
-#define OHCI_CC_BUFFER_OVERRUN 12
-#define OHCI_CC_BUFFER_UNDERRUN 13
-#define OHCI_CC_NOT_ACCESSED 15
-
-/* Some delay needed when changing certain registers. */
-#define OHCI_ENABLE_POWER_DELAY 5
-#define OHCI_READ_DESC_DELAY 5
-
-#define OHCI_NO_EDS (2*OHCI_NO_INTRS)
-
-struct ohci_hw_softc {
- struct usb2_page_cache hcca_pc;
- struct usb2_page_cache ctrl_start_pc;
- struct usb2_page_cache bulk_start_pc;
- struct usb2_page_cache isoc_start_pc;
- struct usb2_page_cache intr_start_pc[OHCI_NO_EDS];
-
- struct usb2_page hcca_pg;
- struct usb2_page ctrl_start_pg;
- struct usb2_page bulk_start_pg;
- struct usb2_page isoc_start_pg;
- struct usb2_page intr_start_pg[OHCI_NO_EDS];
-};
-
-struct ohci_config_desc {
- struct usb2_config_descriptor confd;
- struct usb2_interface_descriptor ifcd;
- struct usb2_endpoint_descriptor endpd;
-} __packed;
-
-union ohci_hub_desc {
- struct usb2_status stat;
- struct usb2_port_status ps;
- struct usb2_device_descriptor devd;
- struct usb2_hub_descriptor hubd;
- uint8_t temp[128];
-};
-
-typedef struct ohci_softc {
- struct ohci_hw_softc sc_hw;
- struct usb2_bus sc_bus; /* base device */
- struct usb2_callout sc_tmo_rhsc;
- union ohci_hub_desc sc_hub_desc;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
-
- struct usb2_device *sc_devices[OHCI_MAX_DEVICES];
- struct resource *sc_io_res;
- struct resource *sc_irq_res;
- struct ohci_hcca *sc_hcca_p;
- struct ohci_ed *sc_ctrl_p_last;
- struct ohci_ed *sc_bulk_p_last;
- struct ohci_ed *sc_isoc_p_last;
- struct ohci_ed *sc_intr_p_last[OHCI_NO_EDS];
- void *sc_intr_hdl;
- device_t sc_dev;
- bus_size_t sc_io_size;
- bus_space_tag_t sc_io_tag;
- bus_space_handle_t sc_io_hdl;
-
- uint32_t sc_eintrs; /* enabled interrupts */
- uint32_t sc_control; /* Preserved during suspend/standby */
- uint32_t sc_intre;
-
- uint16_t sc_intr_stat[OHCI_NO_EDS];
- uint16_t sc_id_vendor;
-
- uint8_t sc_noport;
- uint8_t sc_addr; /* device address */
- uint8_t sc_conf; /* device configuration */
- uint8_t sc_hub_idata[32];
-
- char sc_vendor[16];
-
-} ohci_softc_t;
-
-usb2_bus_mem_cb_t ohci_iterate_hw_softc;
-
-usb2_error_t ohci_init(ohci_softc_t *sc);
-void ohci_detach(struct ohci_softc *sc);
-void ohci_suspend(ohci_softc_t *sc);
-void ohci_resume(ohci_softc_t *sc);
-void ohci_interrupt(ohci_softc_t *sc);
-
-#endif /* _OHCI_H_ */
diff --git a/sys/dev/usb2/controller/ohci2_atmelarm.c b/sys/dev/usb2/controller/ohci2_atmelarm.c
deleted file mode 100644
index a7f086c..0000000
--- a/sys/dev/usb2/controller/ohci2_atmelarm.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*-
- * Copyright (c) 2006 M. Warner Losh. 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.
- * 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 <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/ohci2.h>
-
-#include <sys/rman.h>
-
-#include <arm/at91/at91_pmcvar.h>
-
-#define MEM_RID 0
-
-static device_probe_t ohci_atmelarm_probe;
-static device_attach_t ohci_atmelarm_attach;
-static device_detach_t ohci_atmelarm_detach;
-
-struct at91_ohci_softc {
- struct ohci_softc sc_ohci; /* must be first */
- struct at91_pmc_clock *iclk;
- struct at91_pmc_clock *fclk;
-};
-
-static int
-ohci_atmelarm_probe(device_t dev)
-{
- device_set_desc(dev, "AT91 integrated OHCI controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-ohci_atmelarm_attach(device_t dev)
-{
- struct at91_ohci_softc *sc = device_get_softc(dev);
- int err;
- int rid;
-
- /* initialise some bus fields */
- sc->sc_ohci.sc_bus.parent = dev;
- sc->sc_ohci.sc_bus.devices = sc->sc_ohci.sc_devices;
- sc->sc_ohci.sc_bus.devices_max = OHCI_MAX_DEVICES;
-
- /* get all DMA memory */
- if (usb2_bus_mem_alloc_all(&sc->sc_ohci.sc_bus,
- USB_GET_DMA_TAG(dev), &ohci_iterate_hw_softc)) {
- return (ENOMEM);
- }
- sc->iclk = at91_pmc_clock_ref("ohci_clk");
- sc->fclk = at91_pmc_clock_ref("uhpck");
-
- sc->sc_ohci.sc_dev = dev;
-
- rid = MEM_RID;
- sc->sc_ohci.sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &rid, RF_ACTIVE);
-
- if (!(sc->sc_ohci.sc_io_res)) {
- err = ENOMEM;
- goto error;
- }
- sc->sc_ohci.sc_io_tag = rman_get_bustag(sc->sc_ohci.sc_io_res);
- sc->sc_ohci.sc_io_hdl = rman_get_bushandle(sc->sc_ohci.sc_io_res);
- sc->sc_ohci.sc_io_size = rman_get_size(sc->sc_ohci.sc_io_res);
-
- rid = 0;
- sc->sc_ohci.sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_ACTIVE);
- if (!(sc->sc_ohci.sc_irq_res)) {
- goto error;
- }
- sc->sc_ohci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
- if (!(sc->sc_ohci.sc_bus.bdev)) {
- goto error;
- }
- device_set_ivars(sc->sc_ohci.sc_bus.bdev, &sc->sc_ohci.sc_bus);
-
- strlcpy(sc->sc_ohci.sc_vendor, "Atmel", sizeof(sc->sc_ohci.sc_vendor));
-
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl);
-#else
- err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl);
-#endif
- if (err) {
- sc->sc_ohci.sc_intr_hdl = NULL;
- goto error;
- }
- /*
- * turn on the clocks from the AT91's point of view. Keep the unit in reset.
- */
- at91_pmc_clock_enable(sc->iclk);
- at91_pmc_clock_enable(sc->fclk);
- bus_space_write_4(sc->sc_ohci.sc_io_tag, sc->sc_ohci.sc_io_hdl,
- OHCI_CONTROL, 0);
-
- err = ohci_init(&sc->sc_ohci);
- if (!err) {
- err = device_probe_and_attach(sc->sc_ohci.sc_bus.bdev);
- }
- if (err) {
- goto error;
- }
- return (0);
-
-error:
- ohci_atmelarm_detach(dev);
- return (ENXIO);
-}
-
-static int
-ohci_atmelarm_detach(device_t dev)
-{
- struct at91_ohci_softc *sc = device_get_softc(dev);
- device_t bdev;
- int err;
-
- if (sc->sc_ohci.sc_bus.bdev) {
- bdev = sc->sc_ohci.sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(dev);
-
- /*
- * Put the controller into reset, then disable clocks and do
- * the MI tear down. We have to disable the clocks/hardware
- * after we do the rest of the teardown. We also disable the
- * clocks in the opposite order we acquire them, but that
- * doesn't seem to be absolutely necessary. We free up the
- * clocks after we disable them, so the system could, in
- * theory, reuse them.
- */
- bus_space_write_4(sc->sc_ohci.sc_io_tag, sc->sc_ohci.sc_io_hdl,
- OHCI_CONTROL, 0);
-
- at91_pmc_clock_disable(sc->fclk);
- at91_pmc_clock_disable(sc->iclk);
- at91_pmc_clock_deref(sc->fclk);
- at91_pmc_clock_deref(sc->iclk);
-
- if (sc->sc_ohci.sc_irq_res && sc->sc_ohci.sc_intr_hdl) {
- /*
- * only call ohci_detach() after ohci_init()
- */
- ohci_detach(&sc->sc_ohci);
-
- err = bus_teardown_intr(dev, sc->sc_ohci.sc_irq_res, sc->sc_ohci.sc_intr_hdl);
- sc->sc_ohci.sc_intr_hdl = NULL;
- }
- if (sc->sc_ohci.sc_irq_res) {
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_ohci.sc_irq_res);
- sc->sc_ohci.sc_irq_res = NULL;
- }
- if (sc->sc_ohci.sc_io_res) {
- bus_release_resource(dev, SYS_RES_MEMORY, MEM_RID,
- sc->sc_ohci.sc_io_res);
- sc->sc_ohci.sc_io_res = NULL;
- }
- usb2_bus_mem_free_all(&sc->sc_ohci.sc_bus, &ohci_iterate_hw_softc);
-
- return (0);
-}
-
-static device_method_t ohci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ohci_atmelarm_probe),
- DEVMETHOD(device_attach, ohci_atmelarm_attach),
- DEVMETHOD(device_detach, ohci_atmelarm_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
-};
-
-static driver_t ohci_driver = {
- "ohci",
- ohci_methods,
- sizeof(struct at91_ohci_softc),
-};
-
-static devclass_t ohci_devclass;
-
-DRIVER_MODULE(ohci, atmelarm, ohci_driver, ohci_devclass, 0, 0);
-MODULE_DEPEND(ohci, usb2_controller, 1, 1, 1);
-MODULE_DEPEND(ohci, usb2_core, 1, 1, 1);
diff --git a/sys/dev/usb2/controller/ohci2_pci.c b/sys/dev/usb2/controller/ohci2_pci.c
deleted file mode 100644
index 7d3506e..0000000
--- a/sys/dev/usb2/controller/ohci2_pci.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (augustss@carlstedt.se) at
- * Carlstedt Research & Technology.
- *
- * 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.
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``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 FOUNDATION OR CONTRIBUTORS
- * 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$");
-
-/*
- * USB Open Host Controller driver.
- *
- * OHCI spec: http://www.intel.com/design/usb/ohci11d.pdf
- */
-
-/* The low level controller code for OHCI has been split into
- * PCI probes and OHCI specific code. This was done to facilitate the
- * sharing of code between *BSD's
- */
-
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_defs.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/usb2_pci.h>
-#include <dev/usb2/controller/ohci2.h>
-
-#define PCI_OHCI_VENDORID_ACERLABS 0x10b9
-#define PCI_OHCI_VENDORID_AMD 0x1022
-#define PCI_OHCI_VENDORID_APPLE 0x106b
-#define PCI_OHCI_VENDORID_ATI 0x1002
-#define PCI_OHCI_VENDORID_CMDTECH 0x1095
-#define PCI_OHCI_VENDORID_NEC 0x1033
-#define PCI_OHCI_VENDORID_NVIDIA 0x12D2
-#define PCI_OHCI_VENDORID_NVIDIA2 0x10DE
-#define PCI_OHCI_VENDORID_OPTI 0x1045
-#define PCI_OHCI_VENDORID_SIS 0x1039
-#define PCI_OHCI_VENDORID_SUN 0x108e
-
-#define PCI_OHCI_BASE_REG 0x10
-
-static device_probe_t ohci_pci_probe;
-static device_attach_t ohci_pci_attach;
-static device_detach_t ohci_pci_detach;
-static device_suspend_t ohci_pci_suspend;
-static device_resume_t ohci_pci_resume;
-
-static int
-ohci_pci_suspend(device_t self)
-{
- ohci_softc_t *sc = device_get_softc(self);
- int err;
-
- err = bus_generic_suspend(self);
- if (err) {
- return (err);
- }
- ohci_suspend(sc);
- return (0);
-}
-
-static int
-ohci_pci_resume(device_t self)
-{
- ohci_softc_t *sc = device_get_softc(self);
- uint32_t reg, int_line;
-
- if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) {
- device_printf(self, "chip is in D%d mode "
- "-- setting to D0\n", pci_get_powerstate(self));
- reg = pci_read_config(self, PCI_CBMEM, 4);
- int_line = pci_read_config(self, PCIR_INTLINE, 4);
- pci_set_powerstate(self, PCI_POWERSTATE_D0);
- pci_write_config(self, PCI_CBMEM, reg, 4);
- pci_write_config(self, PCIR_INTLINE, int_line, 4);
- }
- ohci_resume(sc);
-
- bus_generic_resume(self);
- return (0);
-}
-
-static const char *
-ohci_pci_match(device_t self)
-{
- uint32_t device_id = pci_get_devid(self);
-
- switch (device_id) {
- case 0x523710b9:
- return ("AcerLabs M5237 (Aladdin-V) USB controller");
-
- case 0x740c1022:
- return ("AMD-756 USB Controller");
-
- case 0x74141022:
- return ("AMD-766 USB Controller");
-
- case 0x43741002:
- return "ATI SB400 USB Controller";
- case 0x43751002:
- return "ATI SB400 USB Controller";
-
- case 0x06701095:
- return ("CMD Tech 670 (USB0670) USB controller");
-
- case 0x06731095:
- return ("CMD Tech 673 (USB0673) USB controller");
-
- case 0xc8611045:
- return ("OPTi 82C861 (FireLink) USB controller");
-
- case 0x00351033:
- return ("NEC uPD 9210 USB controller");
-
- case 0x00d710de:
- return ("nVidia nForce3 USB Controller");
-
- case 0x70011039:
- return ("SiS 5571 USB controller");
-
- case 0x1103108e:
- return "Sun PCIO-2 USB controller";
-
- case 0x0019106b:
- return ("Apple KeyLargo USB controller");
-
- default:
- break;
- }
- if ((pci_get_class(self) == PCIC_SERIALBUS) &&
- (pci_get_subclass(self) == PCIS_SERIALBUS_USB) &&
- (pci_get_progif(self) == PCI_INTERFACE_OHCI)) {
- return ("OHCI (generic) USB controller");
- }
- return (NULL);
-}
-
-static int
-ohci_pci_probe(device_t self)
-{
- const char *desc = ohci_pci_match(self);
-
- if (desc) {
- device_set_desc(self, desc);
- return (0);
- } else {
- return (ENXIO);
- }
-}
-
-static int
-ohci_pci_attach(device_t self)
-{
- ohci_softc_t *sc = device_get_softc(self);
- int rid;
- int err;
-
- /* initialise some bus fields */
- sc->sc_bus.parent = self;
- sc->sc_bus.devices = sc->sc_devices;
- sc->sc_bus.devices_max = OHCI_MAX_DEVICES;
-
- /* get all DMA memory */
- if (usb2_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
- &ohci_iterate_hw_softc)) {
- return (ENOMEM);
- }
- sc->sc_dev = self;
-
- pci_enable_busmaster(self);
-
- /*
- * Some Sun PCIO-2 USB controllers have their intpin register
- * bogusly set to 0, although it should be 4. Correct that.
- */
- if (pci_get_devid(self) == 0x1103108e && pci_get_intpin(self) == 0)
- pci_set_intpin(self, 4);
-
- rid = PCI_CBMEM;
- sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
- RF_ACTIVE);
- if (!sc->sc_io_res) {
- device_printf(self, "Could not map memory\n");
- goto error;
- }
- sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
- sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
- sc->sc_io_size = rman_get_size(sc->sc_io_res);
-
- rid = 0;
- sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (sc->sc_irq_res == NULL) {
- device_printf(self, "Could not allocate irq\n");
- goto error;
- }
- sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
- if (!sc->sc_bus.bdev) {
- device_printf(self, "Could not add USB device\n");
- goto error;
- }
- device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
-
- /*
- * ohci_pci_match will never return NULL if ohci_pci_probe
- * succeeded
- */
- device_set_desc(sc->sc_bus.bdev, ohci_pci_match(self));
- switch (pci_get_vendor(self)) {
- case PCI_OHCI_VENDORID_ACERLABS:
- sprintf(sc->sc_vendor, "AcerLabs");
- break;
- case PCI_OHCI_VENDORID_AMD:
- sprintf(sc->sc_vendor, "AMD");
- break;
- case PCI_OHCI_VENDORID_APPLE:
- sprintf(sc->sc_vendor, "Apple");
- break;
- case PCI_OHCI_VENDORID_ATI:
- sprintf(sc->sc_vendor, "ATI");
- break;
- case PCI_OHCI_VENDORID_CMDTECH:
- sprintf(sc->sc_vendor, "CMDTECH");
- break;
- case PCI_OHCI_VENDORID_NEC:
- sprintf(sc->sc_vendor, "NEC");
- break;
- case PCI_OHCI_VENDORID_NVIDIA:
- case PCI_OHCI_VENDORID_NVIDIA2:
- sprintf(sc->sc_vendor, "nVidia");
- break;
- case PCI_OHCI_VENDORID_OPTI:
- sprintf(sc->sc_vendor, "OPTi");
- break;
- case PCI_OHCI_VENDORID_SIS:
- sprintf(sc->sc_vendor, "SiS");
- break;
- case PCI_OHCI_VENDORID_SUN:
- sprintf(sc->sc_vendor, "SUN");
- break;
- default:
- if (bootverbose) {
- device_printf(self, "(New OHCI DeviceId=0x%08x)\n",
- pci_get_devid(self));
- }
- sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
- }
-
- /* sc->sc_bus.usbrev; set by ohci_init() */
-
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)ohci_interrupt, sc, &sc->sc_intr_hdl);
-#else
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)(void *)ohci_interrupt, sc, &sc->sc_intr_hdl);
-#endif
- if (err) {
- device_printf(self, "Could not setup irq, %d\n", err);
- sc->sc_intr_hdl = NULL;
- goto error;
- }
- err = ohci_init(sc);
- if (!err) {
- err = device_probe_and_attach(sc->sc_bus.bdev);
- }
- if (err) {
- device_printf(self, "USB init failed\n");
- goto error;
- }
- return (0);
-
-error:
- ohci_pci_detach(self);
- return (ENXIO);
-}
-
-static int
-ohci_pci_detach(device_t self)
-{
- ohci_softc_t *sc = device_get_softc(self);
- device_t bdev;
-
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(self);
-
- pci_disable_busmaster(self);
-
- if (sc->sc_irq_res && sc->sc_intr_hdl) {
- /*
- * only call ohci_detach() after ohci_init()
- */
- ohci_detach(sc);
-
- int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
-
- if (err) {
- /* XXX or should we panic? */
- device_printf(self, "Could not tear down irq, %d\n",
- err);
- }
- sc->sc_intr_hdl = NULL;
- }
- if (sc->sc_irq_res) {
- bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
- sc->sc_irq_res = NULL;
- }
- if (sc->sc_io_res) {
- bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM,
- sc->sc_io_res);
- sc->sc_io_res = NULL;
- }
- usb2_bus_mem_free_all(&sc->sc_bus, &ohci_iterate_hw_softc);
-
- return (0);
-}
-
-static driver_t ohci_driver =
-{
- .name = "ohci",
- .methods = (device_method_t[]){
- /* device interface */
- DEVMETHOD(device_probe, ohci_pci_probe),
- DEVMETHOD(device_attach, ohci_pci_attach),
- DEVMETHOD(device_detach, ohci_pci_detach),
- DEVMETHOD(device_suspend, ohci_pci_suspend),
- DEVMETHOD(device_resume, ohci_pci_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
- },
- .size = sizeof(struct ohci_softc),
-};
-
-static devclass_t ohci_devclass;
-
-DRIVER_MODULE(ohci, pci, ohci_driver, ohci_devclass, 0, 0);
-DRIVER_MODULE(ohci, cardbus, ohci_driver, ohci_devclass, 0, 0);
-MODULE_DEPEND(ohci, usb2_controller, 1, 1, 1);
-MODULE_DEPEND(ohci, usb2_core, 1, 1, 1);
diff --git a/sys/dev/usb2/controller/uhci2.c b/sys/dev/usb2/controller/uhci2.c
deleted file mode 100644
index a5af720..0000000
--- a/sys/dev/usb2/controller/uhci2.c
+++ /dev/null
@@ -1,3381 +0,0 @@
-/*-
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
- * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
- * Copyright (c) 1998 Lennart Augustsson. 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.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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$");
-
-/*
- * USB Universal Host Controller driver.
- * Handles e.g. PIIX3 and PIIX4.
- *
- * UHCI spec: http://developer.intel.com/design/USB/UHCI11D.htm
- * USB spec: http://www.usb.org/developers/docs/usbspec.zip
- * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf
- * ftp://download.intel.com/design/intarch/datashts/29056201.pdf
- */
-
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_defs.h>
-
-#define USB_DEBUG_VAR uhcidebug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_transfer.h>
-#include <dev/usb2/core/usb2_device.h>
-#include <dev/usb2/core/usb2_hub.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/uhci2.h>
-
-#define alt_next next
-#define UHCI_BUS2SC(bus) ((uhci_softc_t *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((uhci_softc_t *)0)->sc_bus))))
-
-#if USB_DEBUG
-static int uhcidebug = 0;
-static int uhcinoloop = 0;
-
-SYSCTL_NODE(_hw_usb2, OID_AUTO, uhci, CTLFLAG_RW, 0, "USB uhci");
-SYSCTL_INT(_hw_usb2_uhci, OID_AUTO, debug, CTLFLAG_RW,
- &uhcidebug, 0, "uhci debug level");
-SYSCTL_INT(_hw_usb2_uhci, OID_AUTO, loop, CTLFLAG_RW,
- &uhcinoloop, 0, "uhci noloop");
-static void uhci_dumpregs(uhci_softc_t *sc);
-static void uhci_dump_tds(uhci_td_t *td);
-
-#endif
-
-#define UBARR(sc) bus_space_barrier((sc)->sc_io_tag, (sc)->sc_io_hdl, 0, (sc)->sc_io_size, \
- BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
-#define UWRITE1(sc, r, x) \
- do { UBARR(sc); bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (r), (x)); \
- } while (/*CONSTCOND*/0)
-#define UWRITE2(sc, r, x) \
- do { UBARR(sc); bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (r), (x)); \
- } while (/*CONSTCOND*/0)
-#define UWRITE4(sc, r, x) \
- do { UBARR(sc); bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (r), (x)); \
- } while (/*CONSTCOND*/0)
-#define UREAD1(sc, r) (UBARR(sc), bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (r)))
-#define UREAD2(sc, r) (UBARR(sc), bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (r)))
-#define UREAD4(sc, r) (UBARR(sc), bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (r)))
-
-#define UHCICMD(sc, cmd) UWRITE2(sc, UHCI_CMD, cmd)
-#define UHCISTS(sc) UREAD2(sc, UHCI_STS)
-
-#define UHCI_RESET_TIMEOUT 100 /* ms, reset timeout */
-
-#define UHCI_INTR_ENDPT 1
-
-struct uhci_mem_layout {
-
- struct usb2_page_search buf_res;
- struct usb2_page_search fix_res;
-
- struct usb2_page_cache *buf_pc;
- struct usb2_page_cache *fix_pc;
-
- uint32_t buf_offset;
-
- uint16_t max_frame_size;
-};
-
-struct uhci_std_temp {
-
- struct uhci_mem_layout ml;
- uhci_td_t *td;
- uhci_td_t *td_next;
- uint32_t average;
- uint32_t td_status;
- uint32_t td_token;
- uint32_t len;
- uint16_t max_frame_size;
- uint8_t shortpkt;
- uint8_t setup_alt_next;
- uint8_t short_frames_ok;
-};
-
-extern struct usb2_bus_methods uhci_bus_methods;
-extern struct usb2_pipe_methods uhci_device_bulk_methods;
-extern struct usb2_pipe_methods uhci_device_ctrl_methods;
-extern struct usb2_pipe_methods uhci_device_intr_methods;
-extern struct usb2_pipe_methods uhci_device_isoc_methods;
-extern struct usb2_pipe_methods uhci_root_ctrl_methods;
-extern struct usb2_pipe_methods uhci_root_intr_methods;
-
-static void uhci_root_ctrl_poll(struct uhci_softc *);
-static void uhci_do_poll(struct usb2_bus *);
-static void uhci_device_done(struct usb2_xfer *, usb2_error_t);
-static void uhci_transfer_intr_enqueue(struct usb2_xfer *);
-static void uhci_root_intr_check(void *);
-static void uhci_timeout(void *);
-static uint8_t uhci_check_transfer(struct usb2_xfer *);
-
-void
-uhci_iterate_hw_softc(struct usb2_bus *bus, usb2_bus_mem_sub_cb_t *cb)
-{
- struct uhci_softc *sc = UHCI_BUS2SC(bus);
- uint32_t i;
-
- cb(bus, &sc->sc_hw.pframes_pc, &sc->sc_hw.pframes_pg,
- sizeof(uint32_t) * UHCI_FRAMELIST_COUNT, UHCI_FRAMELIST_ALIGN);
-
- cb(bus, &sc->sc_hw.ls_ctl_start_pc, &sc->sc_hw.ls_ctl_start_pg,
- sizeof(uhci_qh_t), UHCI_QH_ALIGN);
-
- cb(bus, &sc->sc_hw.fs_ctl_start_pc, &sc->sc_hw.fs_ctl_start_pg,
- sizeof(uhci_qh_t), UHCI_QH_ALIGN);
-
- cb(bus, &sc->sc_hw.bulk_start_pc, &sc->sc_hw.bulk_start_pg,
- sizeof(uhci_qh_t), UHCI_QH_ALIGN);
-
- cb(bus, &sc->sc_hw.last_qh_pc, &sc->sc_hw.last_qh_pg,
- sizeof(uhci_qh_t), UHCI_QH_ALIGN);
-
- cb(bus, &sc->sc_hw.last_td_pc, &sc->sc_hw.last_td_pg,
- sizeof(uhci_td_t), UHCI_TD_ALIGN);
-
- for (i = 0; i != UHCI_VFRAMELIST_COUNT; i++) {
- cb(bus, sc->sc_hw.isoc_start_pc + i,
- sc->sc_hw.isoc_start_pg + i,
- sizeof(uhci_td_t), UHCI_TD_ALIGN);
- }
-
- for (i = 0; i != UHCI_IFRAMELIST_COUNT; i++) {
- cb(bus, sc->sc_hw.intr_start_pc + i,
- sc->sc_hw.intr_start_pg + i,
- sizeof(uhci_qh_t), UHCI_QH_ALIGN);
- }
-}
-
-static void
-uhci_mem_layout_init(struct uhci_mem_layout *ml, struct usb2_xfer *xfer)
-{
- ml->buf_pc = xfer->frbuffers + 0;
- ml->fix_pc = xfer->buf_fixup;
-
- ml->buf_offset = 0;
-
- ml->max_frame_size = xfer->max_frame_size;
-}
-
-static void
-uhci_mem_layout_fixup(struct uhci_mem_layout *ml, struct uhci_td *td)
-{
- usb2_get_page(ml->buf_pc, ml->buf_offset, &ml->buf_res);
-
- if (ml->buf_res.length < td->len) {
-
- /* need to do a fixup */
-
- usb2_get_page(ml->fix_pc, 0, &ml->fix_res);
-
- td->td_buffer = htole32(ml->fix_res.physaddr);
-
- /*
- * The UHCI driver cannot handle
- * page crossings, so a fixup is
- * needed:
- *
- * +----+----+ - - -
- * | YYY|Y |
- * +----+----+ - - -
- * \ \
- * \ \
- * +----+
- * |YYYY| (fixup)
- * +----+
- */
-
- if ((td->td_token & htole32(UHCI_TD_PID)) ==
- htole32(UHCI_TD_PID_IN)) {
- td->fix_pc = ml->fix_pc;
- usb2_pc_cpu_invalidate(ml->fix_pc);
-
- } else {
- td->fix_pc = NULL;
-
- /* copy data to fixup location */
-
- usb2_copy_out(ml->buf_pc, ml->buf_offset,
- ml->fix_res.buffer, td->len);
-
- usb2_pc_cpu_flush(ml->fix_pc);
- }
-
- /* prepare next fixup */
-
- ml->fix_pc++;
-
- } else {
-
- td->td_buffer = htole32(ml->buf_res.physaddr);
- td->fix_pc = NULL;
- }
-
- /* prepare next data location */
-
- ml->buf_offset += td->len;
-}
-
-void
-uhci_reset(uhci_softc_t *sc)
-{
- struct usb2_page_search buf_res;
- uint16_t n;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- DPRINTF("resetting the HC\n");
-
- /* disable interrupts */
-
- UWRITE2(sc, UHCI_INTR, 0);
-
- /* global reset */
-
- UHCICMD(sc, UHCI_CMD_GRESET);
-
- /* wait */
-
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_BUS_RESET_DELAY));
-
- /* terminate all transfers */
-
- UHCICMD(sc, UHCI_CMD_HCRESET);
-
- /* the reset bit goes low when the controller is done */
-
- n = UHCI_RESET_TIMEOUT;
- while (n--) {
- /* wait one millisecond */
-
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
-
- if (!(UREAD2(sc, UHCI_CMD) & UHCI_CMD_HCRESET)) {
- goto done_1;
- }
- }
-
- device_printf(sc->sc_bus.bdev,
- "controller did not reset\n");
-
-done_1:
-
- n = 10;
- while (n--) {
- /* wait one millisecond */
-
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
-
- /* check if HC is stopped */
- if (UREAD2(sc, UHCI_STS) & UHCI_STS_HCH) {
- goto done_2;
- }
- }
-
- device_printf(sc->sc_bus.bdev,
- "controller did not stop\n");
-
-done_2:
-
- /* reload the configuration */
- usb2_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res);
- UWRITE4(sc, UHCI_FLBASEADDR, buf_res.physaddr);
- UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum);
- UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof);
-}
-
-static void
-uhci_start(uhci_softc_t *sc)
-{
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- DPRINTFN(2, "enabling\n");
-
- /* enable interrupts */
-
- UWRITE2(sc, UHCI_INTR,
- (UHCI_INTR_TOCRCIE |
- UHCI_INTR_RIE |
- UHCI_INTR_IOCE |
- UHCI_INTR_SPIE));
-
- /*
- * assume 64 byte packets at frame end and start HC controller
- */
-
- UHCICMD(sc, (UHCI_CMD_MAXP | UHCI_CMD_RS));
-
- uint8_t n = 10;
-
- while (n--) {
- /* wait one millisecond */
-
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
-
- /* check that controller has started */
-
- if (!(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH)) {
- goto done;
- }
- }
-
- device_printf(sc->sc_bus.bdev,
- "cannot start HC controller\n");
-
-done:
- return;
-}
-
-static struct uhci_qh *
-uhci_init_qh(struct usb2_page_cache *pc)
-{
- struct usb2_page_search buf_res;
- struct uhci_qh *qh;
-
- usb2_get_page(pc, 0, &buf_res);
-
- qh = buf_res.buffer;
-
- qh->qh_self =
- htole32(buf_res.physaddr) |
- htole32(UHCI_PTR_QH);
-
- qh->page_cache = pc;
-
- return (qh);
-}
-
-static struct uhci_td *
-uhci_init_td(struct usb2_page_cache *pc)
-{
- struct usb2_page_search buf_res;
- struct uhci_td *td;
-
- usb2_get_page(pc, 0, &buf_res);
-
- td = buf_res.buffer;
-
- td->td_self =
- htole32(buf_res.physaddr) |
- htole32(UHCI_PTR_TD);
-
- td->page_cache = pc;
-
- return (td);
-}
-
-usb2_error_t
-uhci_init(uhci_softc_t *sc)
-{
- uint16_t bit;
- uint16_t x;
- uint16_t y;
-
- DPRINTF("start\n");
-
-#if USB_DEBUG
- if (uhcidebug > 2) {
- uhci_dumpregs(sc);
- }
-#endif
-
- sc->sc_saved_sof = 0x40; /* default value */
- sc->sc_saved_frnum = 0; /* default frame number */
-
- /*
- * Setup QH's
- */
- sc->sc_ls_ctl_p_last =
- uhci_init_qh(&sc->sc_hw.ls_ctl_start_pc);
-
- sc->sc_fs_ctl_p_last =
- uhci_init_qh(&sc->sc_hw.fs_ctl_start_pc);
-
- sc->sc_bulk_p_last =
- uhci_init_qh(&sc->sc_hw.bulk_start_pc);
-#if 0
- sc->sc_reclaim_qh_p =
- sc->sc_fs_ctl_p_last;
-#else
- /* setup reclaim looping point */
- sc->sc_reclaim_qh_p =
- sc->sc_bulk_p_last;
-#endif
-
- sc->sc_last_qh_p =
- uhci_init_qh(&sc->sc_hw.last_qh_pc);
-
- sc->sc_last_td_p =
- uhci_init_td(&sc->sc_hw.last_td_pc);
-
- for (x = 0; x != UHCI_VFRAMELIST_COUNT; x++) {
- sc->sc_isoc_p_last[x] =
- uhci_init_td(sc->sc_hw.isoc_start_pc + x);
- }
-
- for (x = 0; x != UHCI_IFRAMELIST_COUNT; x++) {
- sc->sc_intr_p_last[x] =
- uhci_init_qh(sc->sc_hw.intr_start_pc + x);
- }
-
- /*
- * the QHs are arranged to give poll intervals that are
- * powers of 2 times 1ms
- */
- bit = UHCI_IFRAMELIST_COUNT / 2;
- while (bit) {
- x = bit;
- while (x & bit) {
- uhci_qh_t *qh_x;
- uhci_qh_t *qh_y;
-
- y = (x ^ bit) | (bit / 2);
-
- /*
- * the next QH has half the poll interval
- */
- qh_x = sc->sc_intr_p_last[x];
- qh_y = sc->sc_intr_p_last[y];
-
- qh_x->h_next = NULL;
- qh_x->qh_h_next = qh_y->qh_self;
- qh_x->e_next = NULL;
- qh_x->qh_e_next = htole32(UHCI_PTR_T);
- x++;
- }
- bit >>= 1;
- }
-
- if (1) {
- uhci_qh_t *qh_ls;
- uhci_qh_t *qh_intr;
-
- qh_ls = sc->sc_ls_ctl_p_last;
- qh_intr = sc->sc_intr_p_last[0];
-
- /* start QH for interrupt traffic */
- qh_intr->h_next = qh_ls;
- qh_intr->qh_h_next = qh_ls->qh_self;
- qh_intr->e_next = 0;
- qh_intr->qh_e_next = htole32(UHCI_PTR_T);
- }
- for (x = 0; x != UHCI_VFRAMELIST_COUNT; x++) {
-
- uhci_td_t *td_x;
- uhci_qh_t *qh_intr;
-
- td_x = sc->sc_isoc_p_last[x];
- qh_intr = sc->sc_intr_p_last[x | (UHCI_IFRAMELIST_COUNT / 2)];
-
- /* start TD for isochronous traffic */
- td_x->next = NULL;
- td_x->td_next = qh_intr->qh_self;
- td_x->td_status = htole32(UHCI_TD_IOS);
- td_x->td_token = htole32(0);
- td_x->td_buffer = htole32(0);
- }
-
- if (1) {
- uhci_qh_t *qh_ls;
- uhci_qh_t *qh_fs;
-
- qh_ls = sc->sc_ls_ctl_p_last;
- qh_fs = sc->sc_fs_ctl_p_last;
-
- /* start QH where low speed control traffic will be queued */
- qh_ls->h_next = qh_fs;
- qh_ls->qh_h_next = qh_fs->qh_self;
- qh_ls->e_next = 0;
- qh_ls->qh_e_next = htole32(UHCI_PTR_T);
- }
- if (1) {
- uhci_qh_t *qh_ctl;
- uhci_qh_t *qh_blk;
- uhci_qh_t *qh_lst;
- uhci_td_t *td_lst;
-
- qh_ctl = sc->sc_fs_ctl_p_last;
- qh_blk = sc->sc_bulk_p_last;
-
- /* start QH where full speed control traffic will be queued */
- qh_ctl->h_next = qh_blk;
- qh_ctl->qh_h_next = qh_blk->qh_self;
- qh_ctl->e_next = 0;
- qh_ctl->qh_e_next = htole32(UHCI_PTR_T);
-
- qh_lst = sc->sc_last_qh_p;
-
- /* start QH where bulk traffic will be queued */
- qh_blk->h_next = qh_lst;
- qh_blk->qh_h_next = qh_lst->qh_self;
- qh_blk->e_next = 0;
- qh_blk->qh_e_next = htole32(UHCI_PTR_T);
-
- td_lst = sc->sc_last_td_p;
-
- /* end QH which is used for looping the QHs */
- qh_lst->h_next = 0;
- qh_lst->qh_h_next = htole32(UHCI_PTR_T); /* end of QH chain */
- qh_lst->e_next = td_lst;
- qh_lst->qh_e_next = td_lst->td_self;
-
- /*
- * end TD which hangs from the last QH, to avoid a bug in the PIIX
- * that makes it run berserk otherwise
- */
- td_lst->next = 0;
- td_lst->td_next = htole32(UHCI_PTR_T);
- td_lst->td_status = htole32(0); /* inactive */
- td_lst->td_token = htole32(0);
- td_lst->td_buffer = htole32(0);
- }
- if (1) {
- struct usb2_page_search buf_res;
- uint32_t *pframes;
-
- usb2_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res);
-
- pframes = buf_res.buffer;
-
-
- /*
- * Setup UHCI framelist
- *
- * Execution order:
- *
- * pframes -> full speed isochronous -> interrupt QH's -> low
- * speed control -> full speed control -> bulk transfers
- *
- */
-
- for (x = 0; x != UHCI_FRAMELIST_COUNT; x++) {
- pframes[x] =
- sc->sc_isoc_p_last[x % UHCI_VFRAMELIST_COUNT]->td_self;
- }
- }
- /* flush all cache into memory */
-
- usb2_bus_mem_flush_all(&sc->sc_bus, &uhci_iterate_hw_softc);
-
- /* set up the bus struct */
- sc->sc_bus.methods = &uhci_bus_methods;
-
- USB_BUS_LOCK(&sc->sc_bus);
- /* reset the controller */
- uhci_reset(sc);
-
- /* start the controller */
- uhci_start(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- /* catch lost interrupts */
- uhci_do_poll(&sc->sc_bus);
-
- return (0);
-}
-
-/* NOTE: suspend/resume is called from
- * interrupt context and cannot sleep!
- */
-
-void
-uhci_suspend(uhci_softc_t *sc)
-{
- USB_BUS_LOCK(&sc->sc_bus);
-
-#if USB_DEBUG
- if (uhcidebug > 2) {
- uhci_dumpregs(sc);
- }
-#endif
- /* save some state if BIOS doesn't */
-
- sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM);
- sc->sc_saved_sof = UREAD1(sc, UHCI_SOF);
-
- /* stop the controller */
-
- uhci_reset(sc);
-
- /* enter global suspend */
-
- UHCICMD(sc, UHCI_CMD_EGSM);
-
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_WAIT));
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-void
-uhci_resume(uhci_softc_t *sc)
-{
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* reset the controller */
-
- uhci_reset(sc);
-
- /* force global resume */
-
- UHCICMD(sc, UHCI_CMD_FGR);
-
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_RESUME_DELAY));
-
- /* and start traffic again */
-
- uhci_start(sc);
-
-#if USB_DEBUG
- if (uhcidebug > 2) {
- uhci_dumpregs(sc);
- }
-#endif
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- /* catch lost interrupts */
- uhci_do_poll(&sc->sc_bus);
-}
-
-#if USB_DEBUG
-static void
-uhci_dumpregs(uhci_softc_t *sc)
-{
- DPRINTFN(0, "%s regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, "
- "flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n",
- device_get_nameunit(sc->sc_bus.bdev),
- UREAD2(sc, UHCI_CMD),
- UREAD2(sc, UHCI_STS),
- UREAD2(sc, UHCI_INTR),
- UREAD2(sc, UHCI_FRNUM),
- UREAD4(sc, UHCI_FLBASEADDR),
- UREAD1(sc, UHCI_SOF),
- UREAD2(sc, UHCI_PORTSC1),
- UREAD2(sc, UHCI_PORTSC2));
-}
-
-static uint8_t
-uhci_dump_td(uhci_td_t *p)
-{
- uint32_t td_next;
- uint32_t td_status;
- uint32_t td_token;
- uint8_t temp;
-
- usb2_pc_cpu_invalidate(p->page_cache);
-
- td_next = le32toh(p->td_next);
- td_status = le32toh(p->td_status);
- td_token = le32toh(p->td_token);
-
- /*
- * Check whether the link pointer in this TD marks the link pointer
- * as end of queue:
- */
- temp = ((td_next & UHCI_PTR_T) || (td_next == 0));
-
- printf("TD(%p) at 0x%08x = link=0x%08x status=0x%08x "
- "token=0x%08x buffer=0x%08x\n",
- p,
- le32toh(p->td_self),
- td_next,
- td_status,
- td_token,
- le32toh(p->td_buffer));
-
- printf("TD(%p) td_next=%s%s%s td_status=%s%s%s%s%s%s%s%s%s%s%s, errcnt=%d, actlen=%d pid=%02x,"
- "addr=%d,endpt=%d,D=%d,maxlen=%d\n",
- p,
- (td_next & 1) ? "-T" : "",
- (td_next & 2) ? "-Q" : "",
- (td_next & 4) ? "-VF" : "",
- (td_status & UHCI_TD_BITSTUFF) ? "-BITSTUFF" : "",
- (td_status & UHCI_TD_CRCTO) ? "-CRCTO" : "",
- (td_status & UHCI_TD_NAK) ? "-NAK" : "",
- (td_status & UHCI_TD_BABBLE) ? "-BABBLE" : "",
- (td_status & UHCI_TD_DBUFFER) ? "-DBUFFER" : "",
- (td_status & UHCI_TD_STALLED) ? "-STALLED" : "",
- (td_status & UHCI_TD_ACTIVE) ? "-ACTIVE" : "",
- (td_status & UHCI_TD_IOC) ? "-IOC" : "",
- (td_status & UHCI_TD_IOS) ? "-IOS" : "",
- (td_status & UHCI_TD_LS) ? "-LS" : "",
- (td_status & UHCI_TD_SPD) ? "-SPD" : "",
- UHCI_TD_GET_ERRCNT(td_status),
- UHCI_TD_GET_ACTLEN(td_status),
- UHCI_TD_GET_PID(td_token),
- UHCI_TD_GET_DEVADDR(td_token),
- UHCI_TD_GET_ENDPT(td_token),
- UHCI_TD_GET_DT(td_token),
- UHCI_TD_GET_MAXLEN(td_token));
-
- return (temp);
-}
-
-static uint8_t
-uhci_dump_qh(uhci_qh_t *sqh)
-{
- uint8_t temp;
- uint32_t qh_h_next;
- uint32_t qh_e_next;
-
- usb2_pc_cpu_invalidate(sqh->page_cache);
-
- qh_h_next = le32toh(sqh->qh_h_next);
- qh_e_next = le32toh(sqh->qh_e_next);
-
- DPRINTFN(0, "QH(%p) at 0x%08x: h_next=0x%08x e_next=0x%08x\n", sqh,
- le32toh(sqh->qh_self), qh_h_next, qh_e_next);
-
- temp = ((((sqh->h_next != NULL) && !(qh_h_next & UHCI_PTR_T)) ? 1 : 0) |
- (((sqh->e_next != NULL) && !(qh_e_next & UHCI_PTR_T)) ? 2 : 0));
-
- return (temp);
-}
-
-static void
-uhci_dump_all(uhci_softc_t *sc)
-{
- uhci_dumpregs(sc);
- uhci_dump_qh(sc->sc_ls_ctl_p_last);
- uhci_dump_qh(sc->sc_fs_ctl_p_last);
- uhci_dump_qh(sc->sc_bulk_p_last);
- uhci_dump_qh(sc->sc_last_qh_p);
-}
-
-static void
-uhci_dump_qhs(uhci_qh_t *sqh)
-{
- uint8_t temp;
-
- temp = uhci_dump_qh(sqh);
-
- /*
- * uhci_dump_qhs displays all the QHs and TDs from the given QH
- * onwards Traverses sideways first, then down.
- *
- * QH1 QH2 No QH TD2.1 TD2.2 TD1.1 etc.
- *
- * TD2.x being the TDs queued at QH2 and QH1 being referenced from QH1.
- */
-
- if (temp & 1)
- uhci_dump_qhs(sqh->h_next);
- else
- DPRINTF("No QH\n");
-
- if (temp & 2)
- uhci_dump_tds(sqh->e_next);
- else
- DPRINTF("No TD\n");
-}
-
-static void
-uhci_dump_tds(uhci_td_t *td)
-{
- for (;
- td != NULL;
- td = td->obj_next) {
- if (uhci_dump_td(td)) {
- break;
- }
- }
-}
-
-#endif
-
-/*
- * Let the last QH loop back to the full speed control transfer QH.
- * This is what intel calls "bandwidth reclamation" and improves
- * USB performance a lot for some devices.
- * If we are already looping, just count it.
- */
-static void
-uhci_add_loop(uhci_softc_t *sc)
-{
- struct uhci_qh *qh_lst;
- struct uhci_qh *qh_rec;
-
-#if USB_DEBUG
- if (uhcinoloop) {
- return;
- }
-#endif
- if (++(sc->sc_loops) == 1) {
- DPRINTFN(6, "add\n");
-
- qh_lst = sc->sc_last_qh_p;
- qh_rec = sc->sc_reclaim_qh_p;
-
- /* NOTE: we don't loop back the soft pointer */
-
- qh_lst->qh_h_next = qh_rec->qh_self;
- usb2_pc_cpu_flush(qh_lst->page_cache);
- }
-}
-
-static void
-uhci_rem_loop(uhci_softc_t *sc)
-{
- struct uhci_qh *qh_lst;
-
-#if USB_DEBUG
- if (uhcinoloop) {
- return;
- }
-#endif
- if (--(sc->sc_loops) == 0) {
- DPRINTFN(6, "remove\n");
-
- qh_lst = sc->sc_last_qh_p;
- qh_lst->qh_h_next = htole32(UHCI_PTR_T);
- usb2_pc_cpu_flush(qh_lst->page_cache);
- }
-}
-
-static void
-uhci_transfer_intr_enqueue(struct usb2_xfer *xfer)
-{
- /* check for early completion */
- if (uhci_check_transfer(xfer)) {
- return;
- }
- /* put transfer on interrupt queue */
- usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
-
- /* start timeout, if any */
- if (xfer->timeout != 0) {
- usb2_transfer_timeout_ms(xfer, &uhci_timeout, xfer->timeout);
- }
-}
-
-#define UHCI_APPEND_TD(std,last) (last) = _uhci_append_td(std,last)
-static uhci_td_t *
-_uhci_append_td(uhci_td_t *std, uhci_td_t *last)
-{
- DPRINTFN(11, "%p to %p\n", std, last);
-
- /* (sc->sc_bus.mtx) must be locked */
-
- std->next = last->next;
- std->td_next = last->td_next;
-
- std->prev = last;
-
- usb2_pc_cpu_flush(std->page_cache);
-
- /*
- * the last->next->prev is never followed: std->next->prev = std;
- */
- last->next = std;
- last->td_next = std->td_self;
-
- usb2_pc_cpu_flush(last->page_cache);
-
- return (std);
-}
-
-#define UHCI_APPEND_QH(sqh,last) (last) = _uhci_append_qh(sqh,last)
-static uhci_qh_t *
-_uhci_append_qh(uhci_qh_t *sqh, uhci_qh_t *last)
-{
- DPRINTFN(11, "%p to %p\n", sqh, last);
-
- if (sqh->h_prev != NULL) {
- /* should not happen */
- DPRINTFN(0, "QH already linked!\n");
- return (last);
- }
- /* (sc->sc_bus.mtx) must be locked */
-
- sqh->h_next = last->h_next;
- sqh->qh_h_next = last->qh_h_next;
-
- sqh->h_prev = last;
-
- usb2_pc_cpu_flush(sqh->page_cache);
-
- /*
- * The "last->h_next->h_prev" is never followed:
- *
- * "sqh->h_next->h_prev" = sqh;
- */
-
- last->h_next = sqh;
- last->qh_h_next = sqh->qh_self;
-
- usb2_pc_cpu_flush(last->page_cache);
-
- return (sqh);
-}
-
-/**/
-
-#define UHCI_REMOVE_TD(std,last) (last) = _uhci_remove_td(std,last)
-static uhci_td_t *
-_uhci_remove_td(uhci_td_t *std, uhci_td_t *last)
-{
- DPRINTFN(11, "%p from %p\n", std, last);
-
- /* (sc->sc_bus.mtx) must be locked */
-
- std->prev->next = std->next;
- std->prev->td_next = std->td_next;
-
- usb2_pc_cpu_flush(std->prev->page_cache);
-
- if (std->next) {
- std->next->prev = std->prev;
- usb2_pc_cpu_flush(std->next->page_cache);
- }
- return ((last == std) ? std->prev : last);
-}
-
-#define UHCI_REMOVE_QH(sqh,last) (last) = _uhci_remove_qh(sqh,last)
-static uhci_qh_t *
-_uhci_remove_qh(uhci_qh_t *sqh, uhci_qh_t *last)
-{
- DPRINTFN(11, "%p from %p\n", sqh, last);
-
- /* (sc->sc_bus.mtx) must be locked */
-
- /* only remove if not removed from a queue */
- if (sqh->h_prev) {
-
- sqh->h_prev->h_next = sqh->h_next;
- sqh->h_prev->qh_h_next = sqh->qh_h_next;
-
- usb2_pc_cpu_flush(sqh->h_prev->page_cache);
-
- if (sqh->h_next) {
- sqh->h_next->h_prev = sqh->h_prev;
- usb2_pc_cpu_flush(sqh->h_next->page_cache);
- }
- last = ((last == sqh) ? sqh->h_prev : last);
-
- sqh->h_prev = 0;
-
- usb2_pc_cpu_flush(sqh->page_cache);
- }
- return (last);
-}
-
-static void
-uhci_isoc_done(uhci_softc_t *sc, struct usb2_xfer *xfer)
-{
- struct usb2_page_search res;
- uint32_t nframes = xfer->nframes;
- uint32_t status;
- uint32_t offset = 0;
- uint32_t *plen = xfer->frlengths;
- uint16_t len = 0;
- uhci_td_t *td = xfer->td_transfer_first;
- uhci_td_t **pp_last = &sc->sc_isoc_p_last[xfer->qh_pos];
-
- DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
- /* sync any DMA memory before doing fixups */
-
- usb2_bdma_post_sync(xfer);
-
- while (nframes--) {
- if (td == NULL) {
- panic("%s:%d: out of TD's\n",
- __FUNCTION__, __LINE__);
- }
- if (pp_last >= &sc->sc_isoc_p_last[UHCI_VFRAMELIST_COUNT]) {
- pp_last = &sc->sc_isoc_p_last[0];
- }
-#if USB_DEBUG
- if (uhcidebug > 5) {
- DPRINTF("isoc TD\n");
- uhci_dump_td(td);
- }
-#endif
- usb2_pc_cpu_invalidate(td->page_cache);
- status = le32toh(td->td_status);
-
- len = UHCI_TD_GET_ACTLEN(status);
-
- if (len > *plen) {
- len = *plen;
- }
- if (td->fix_pc) {
-
- usb2_get_page(td->fix_pc, 0, &res);
-
- /* copy data from fixup location to real location */
-
- usb2_pc_cpu_invalidate(td->fix_pc);
-
- usb2_copy_in(xfer->frbuffers, offset,
- res.buffer, len);
- }
- offset += *plen;
-
- *plen = len;
-
- /* remove TD from schedule */
- UHCI_REMOVE_TD(td, *pp_last);
-
- pp_last++;
- plen++;
- td = td->obj_next;
- }
-
- xfer->aframes = xfer->nframes;
-}
-
-static usb2_error_t
-uhci_non_isoc_done_sub(struct usb2_xfer *xfer)
-{
- struct usb2_page_search res;
- uhci_td_t *td;
- uhci_td_t *td_alt_next;
- uint32_t status;
- uint32_t token;
- uint16_t len;
-
- td = xfer->td_transfer_cache;
- td_alt_next = td->alt_next;
-
- if (xfer->aframes != xfer->nframes) {
- xfer->frlengths[xfer->aframes] = 0;
- }
- while (1) {
-
- usb2_pc_cpu_invalidate(td->page_cache);
- status = le32toh(td->td_status);
- token = le32toh(td->td_token);
-
- /*
- * Verify the status and add
- * up the actual length:
- */
-
- len = UHCI_TD_GET_ACTLEN(status);
- if (len > td->len) {
- /* should not happen */
- DPRINTF("Invalid status length, "
- "0x%04x/0x%04x bytes\n", len, td->len);
- status |= UHCI_TD_STALLED;
-
- } else if ((xfer->aframes != xfer->nframes) && (len > 0)) {
-
- if (td->fix_pc) {
-
- usb2_get_page(td->fix_pc, 0, &res);
-
- /*
- * copy data from fixup location to real
- * location
- */
-
- usb2_pc_cpu_invalidate(td->fix_pc);
-
- usb2_copy_in(xfer->frbuffers + xfer->aframes,
- xfer->frlengths[xfer->aframes], res.buffer, len);
- }
- /* update actual length */
-
- xfer->frlengths[xfer->aframes] += len;
- }
- /* Check for last transfer */
- if (((void *)td) == xfer->td_transfer_last) {
- td = NULL;
- break;
- }
- if (status & UHCI_TD_STALLED) {
- /* the transfer is finished */
- td = NULL;
- break;
- }
- /* Check for short transfer */
- if (len != td->len) {
- if (xfer->flags_int.short_frames_ok) {
- /* follow alt next */
- td = td->alt_next;
- } else {
- /* the transfer is finished */
- td = NULL;
- }
- break;
- }
- td = td->obj_next;
-
- if (td->alt_next != td_alt_next) {
- /* this USB frame is complete */
- break;
- }
- }
-
- /* update transfer cache */
-
- xfer->td_transfer_cache = td;
-
- /* update data toggle */
-
- xfer->pipe->toggle_next = (token & UHCI_TD_SET_DT(1)) ? 0 : 1;
-
-#if USB_DEBUG
- if (status & UHCI_TD_ERROR) {
- DPRINTFN(11, "error, addr=%d, endpt=0x%02x, frame=0x%02x "
- "status=%s%s%s%s%s%s%s%s%s%s%s\n",
- xfer->address, xfer->endpoint, xfer->aframes,
- (status & UHCI_TD_BITSTUFF) ? "[BITSTUFF]" : "",
- (status & UHCI_TD_CRCTO) ? "[CRCTO]" : "",
- (status & UHCI_TD_NAK) ? "[NAK]" : "",
- (status & UHCI_TD_BABBLE) ? "[BABBLE]" : "",
- (status & UHCI_TD_DBUFFER) ? "[DBUFFER]" : "",
- (status & UHCI_TD_STALLED) ? "[STALLED]" : "",
- (status & UHCI_TD_ACTIVE) ? "[ACTIVE]" : "[NOT_ACTIVE]",
- (status & UHCI_TD_IOC) ? "[IOC]" : "",
- (status & UHCI_TD_IOS) ? "[IOS]" : "",
- (status & UHCI_TD_LS) ? "[LS]" : "",
- (status & UHCI_TD_SPD) ? "[SPD]" : "");
- }
-#endif
- return (status & UHCI_TD_STALLED) ?
- USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION;
-}
-
-static void
-uhci_non_isoc_done(struct usb2_xfer *xfer)
-{
- usb2_error_t err = 0;
-
- DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
-#if USB_DEBUG
- if (uhcidebug > 10) {
- uhci_dump_tds(xfer->td_transfer_first);
- }
-#endif
-
- /* sync any DMA memory before doing fixups */
-
- usb2_bdma_post_sync(xfer);
-
- /* reset scanner */
-
- xfer->td_transfer_cache = xfer->td_transfer_first;
-
- if (xfer->flags_int.control_xfr) {
- if (xfer->flags_int.control_hdr) {
-
- err = uhci_non_isoc_done_sub(xfer);
- }
- xfer->aframes = 1;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
- while (xfer->aframes != xfer->nframes) {
-
- err = uhci_non_isoc_done_sub(xfer);
- xfer->aframes++;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- err = uhci_non_isoc_done_sub(xfer);
- }
-done:
- uhci_device_done(xfer, err);
-}
-
-/*------------------------------------------------------------------------*
- * uhci_check_transfer_sub
- *
- * The main purpose of this function is to update the data-toggle
- * in case it is wrong.
- *------------------------------------------------------------------------*/
-static void
-uhci_check_transfer_sub(struct usb2_xfer *xfer)
-{
- uhci_qh_t *qh;
- uhci_td_t *td;
- uhci_td_t *td_alt_next;
-
- uint32_t td_token;
- uint32_t td_self;
-
- td = xfer->td_transfer_cache;
- qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- td_token = td->obj_next->td_token;
- td = td->alt_next;
- xfer->td_transfer_cache = td;
- td_self = td->td_self;
- td_alt_next = td->alt_next;
-
- if ((td->td_token ^ td_token) & htole32(UHCI_TD_SET_DT(1))) {
-
- /*
- * The data toggle is wrong and
- * we need to switch it !
- */
-
- while (1) {
-
- td->td_token ^= htole32(UHCI_TD_SET_DT(1));
- usb2_pc_cpu_flush(td->page_cache);
-
- if (td == xfer->td_transfer_last) {
- /* last transfer */
- break;
- }
- td = td->obj_next;
-
- if (td->alt_next != td_alt_next) {
- /* next frame */
- break;
- }
- }
- }
- /* update the QH */
- qh->qh_e_next = td_self;
- usb2_pc_cpu_flush(qh->page_cache);
-
- DPRINTFN(13, "xfer=%p following alt next\n", xfer);
-}
-
-/*------------------------------------------------------------------------*
- * uhci_check_transfer
- *
- * Return values:
- * 0: USB transfer is not finished
- * Else: USB transfer is finished
- *------------------------------------------------------------------------*/
-static uint8_t
-uhci_check_transfer(struct usb2_xfer *xfer)
-{
- uint32_t status;
- uint32_t token;
- uhci_td_t *td;
-
- DPRINTFN(16, "xfer=%p checking transfer\n", xfer);
-
- if (xfer->pipe->methods == &uhci_device_isoc_methods) {
- /* isochronous transfer */
-
- td = xfer->td_transfer_last;
-
- usb2_pc_cpu_invalidate(td->page_cache);
- status = le32toh(td->td_status);
-
- /* check also if the first is complete */
-
- td = xfer->td_transfer_first;
-
- usb2_pc_cpu_invalidate(td->page_cache);
- status |= le32toh(td->td_status);
-
- if (!(status & UHCI_TD_ACTIVE)) {
- uhci_device_done(xfer, USB_ERR_NORMAL_COMPLETION);
- goto transferred;
- }
- } else {
- /* non-isochronous transfer */
-
- /*
- * check whether there is an error somewhere
- * in the middle, or whether there was a short
- * packet (SPD and not ACTIVE)
- */
- td = xfer->td_transfer_cache;
-
- while (1) {
- usb2_pc_cpu_invalidate(td->page_cache);
- status = le32toh(td->td_status);
- token = le32toh(td->td_token);
-
- /*
- * if there is an active TD the transfer isn't done
- */
- if (status & UHCI_TD_ACTIVE) {
- /* update cache */
- xfer->td_transfer_cache = td;
- goto done;
- }
- /*
- * last transfer descriptor makes the transfer done
- */
- if (((void *)td) == xfer->td_transfer_last) {
- break;
- }
- /*
- * any kind of error makes the transfer done
- */
- if (status & UHCI_TD_STALLED) {
- break;
- }
- /*
- * check if we reached the last packet
- * or if there is a short packet:
- */
- if ((td->td_next == htole32(UHCI_PTR_T)) ||
- (UHCI_TD_GET_ACTLEN(status) < td->len)) {
-
- if (xfer->flags_int.short_frames_ok) {
- /* follow alt next */
- if (td->alt_next) {
- /* update cache */
- xfer->td_transfer_cache = td;
- uhci_check_transfer_sub(xfer);
- goto done;
- }
- }
- /* transfer is done */
- break;
- }
- td = td->obj_next;
- }
- uhci_non_isoc_done(xfer);
- goto transferred;
- }
-
-done:
- DPRINTFN(13, "xfer=%p is still active\n", xfer);
- return (0);
-
-transferred:
- return (1);
-}
-
-static void
-uhci_interrupt_poll(uhci_softc_t *sc)
-{
- struct usb2_xfer *xfer;
-
-repeat:
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- /*
- * check if transfer is transferred
- */
- if (uhci_check_transfer(xfer)) {
- /* queue has been modified */
- goto repeat;
- }
- }
-}
-
-/*------------------------------------------------------------------------*
- * uhci_interrupt - UHCI interrupt handler
- *
- * NOTE: Do not access "sc->sc_bus.bdev" inside the interrupt handler,
- * hence the interrupt handler will be setup before "sc->sc_bus.bdev"
- * is present !
- *------------------------------------------------------------------------*/
-void
-uhci_interrupt(uhci_softc_t *sc)
-{
- uint32_t status;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- DPRINTFN(16, "real interrupt\n");
-
-#if USB_DEBUG
- if (uhcidebug > 15) {
- uhci_dumpregs(sc);
- }
-#endif
- status = UREAD2(sc, UHCI_STS) & UHCI_STS_ALLINTRS;
- if (status == 0) {
- /* the interrupt was not for us */
- goto done;
- }
- if (status & (UHCI_STS_RD | UHCI_STS_HSE |
- UHCI_STS_HCPE | UHCI_STS_HCH)) {
-
- if (status & UHCI_STS_RD) {
-#if USB_DEBUG
- printf("%s: resume detect\n",
- __FUNCTION__);
-#endif
- }
- if (status & UHCI_STS_HSE) {
- printf("%s: host system error\n",
- __FUNCTION__);
- }
- if (status & UHCI_STS_HCPE) {
- printf("%s: host controller process error\n",
- __FUNCTION__);
- }
- if (status & UHCI_STS_HCH) {
- /* no acknowledge needed */
- DPRINTF("%s: host controller halted\n",
- __FUNCTION__);
-#if USB_DEBUG
- if (uhcidebug > 0) {
- uhci_dump_all(sc);
- }
-#endif
- }
- }
- /* get acknowledge bits */
- status &= (UHCI_STS_USBINT |
- UHCI_STS_USBEI |
- UHCI_STS_RD |
- UHCI_STS_HSE |
- UHCI_STS_HCPE);
-
- if (status == 0) {
- /* nothing to acknowledge */
- goto done;
- }
- /* acknowledge interrupts */
- UWRITE2(sc, UHCI_STS, status);
-
- /* poll all the USB transfers */
- uhci_interrupt_poll(sc);
-
-done:
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-/*
- * called when a request does not complete
- */
-static void
-uhci_timeout(void *arg)
-{
- struct usb2_xfer *xfer = arg;
-
- DPRINTF("xfer=%p\n", xfer);
-
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- /* transfer is transferred */
- uhci_device_done(xfer, USB_ERR_TIMEOUT);
-}
-
-static void
-uhci_do_poll(struct usb2_bus *bus)
-{
- struct uhci_softc *sc = UHCI_BUS2SC(bus);
-
- USB_BUS_LOCK(&sc->sc_bus);
- uhci_interrupt_poll(sc);
- uhci_root_ctrl_poll(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-static void
-uhci_setup_standard_chain_sub(struct uhci_std_temp *temp)
-{
- uhci_td_t *td;
- uhci_td_t *td_next;
- uhci_td_t *td_alt_next;
- uint32_t average;
- uint32_t len_old;
- uint8_t shortpkt_old;
- uint8_t precompute;
-
- td_alt_next = NULL;
- shortpkt_old = temp->shortpkt;
- len_old = temp->len;
- precompute = 1;
-
- /* software is used to detect short incoming transfers */
-
- if ((temp->td_token & htole32(UHCI_TD_PID)) == htole32(UHCI_TD_PID_IN)) {
- temp->td_status |= htole32(UHCI_TD_SPD);
- } else {
- temp->td_status &= ~htole32(UHCI_TD_SPD);
- }
-
- temp->ml.buf_offset = 0;
-
-restart:
-
- temp->td_token &= ~htole32(UHCI_TD_SET_MAXLEN(0));
- temp->td_token |= htole32(UHCI_TD_SET_MAXLEN(temp->average));
-
- td = temp->td;
- td_next = temp->td_next;
-
- while (1) {
-
- if (temp->len == 0) {
-
- if (temp->shortpkt) {
- break;
- }
- /* send a Zero Length Packet, ZLP, last */
-
- temp->shortpkt = 1;
- temp->td_token |= htole32(UHCI_TD_SET_MAXLEN(0));
- average = 0;
-
- } else {
-
- average = temp->average;
-
- if (temp->len < average) {
- temp->shortpkt = 1;
- temp->td_token &= ~htole32(UHCI_TD_SET_MAXLEN(0));
- temp->td_token |= htole32(UHCI_TD_SET_MAXLEN(temp->len));
- average = temp->len;
- }
- }
-
- if (td_next == NULL) {
- panic("%s: out of UHCI transfer descriptors!", __FUNCTION__);
- }
- /* get next TD */
-
- td = td_next;
- td_next = td->obj_next;
-
- /* check if we are pre-computing */
-
- if (precompute) {
-
- /* update remaining length */
-
- temp->len -= average;
-
- continue;
- }
- /* fill out current TD */
-
- td->td_status = temp->td_status;
- td->td_token = temp->td_token;
-
- /* update data toggle */
-
- temp->td_token ^= htole32(UHCI_TD_SET_DT(1));
-
- if (average == 0) {
-
- td->len = 0;
- td->td_buffer = 0;
- td->fix_pc = NULL;
-
- } else {
-
- /* update remaining length */
-
- temp->len -= average;
-
- td->len = average;
-
- /* fill out buffer pointer and do fixup, if any */
-
- uhci_mem_layout_fixup(&temp->ml, td);
- }
-
- td->alt_next = td_alt_next;
-
- if ((td_next == td_alt_next) && temp->setup_alt_next) {
- /* we need to receive these frames one by one ! */
- td->td_status |= htole32(UHCI_TD_IOC);
- td->td_next = htole32(UHCI_PTR_T);
- } else {
- if (td_next) {
- /* link the current TD with the next one */
- td->td_next = td_next->td_self;
- }
- }
-
- usb2_pc_cpu_flush(td->page_cache);
- }
-
- if (precompute) {
- precompute = 0;
-
- /* setup alt next pointer, if any */
- if (temp->short_frames_ok) {
- if (temp->setup_alt_next) {
- td_alt_next = td_next;
- }
- } else {
- /* we use this field internally */
- td_alt_next = td_next;
- }
-
- /* restore */
- temp->shortpkt = shortpkt_old;
- temp->len = len_old;
- goto restart;
- }
- temp->td = td;
- temp->td_next = td_next;
-}
-
-static uhci_td_t *
-uhci_setup_standard_chain(struct usb2_xfer *xfer)
-{
- struct uhci_std_temp temp;
- uhci_td_t *td;
- uint32_t x;
-
- DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
- xfer->address, UE_GET_ADDR(xfer->endpoint),
- xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
-
- temp.average = xfer->max_frame_size;
- temp.max_frame_size = xfer->max_frame_size;
-
- /* toggle the DMA set we are using */
- xfer->flags_int.curr_dma_set ^= 1;
-
- /* get next DMA set */
- td = xfer->td_start[xfer->flags_int.curr_dma_set];
- xfer->td_transfer_first = td;
- xfer->td_transfer_cache = td;
-
- temp.td = NULL;
- temp.td_next = td;
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.short_frames_ok = xfer->flags_int.short_frames_ok;
-
- uhci_mem_layout_init(&temp.ml, xfer);
-
- temp.td_status =
- htole32(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) |
- UHCI_TD_ACTIVE));
-
- if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
- temp.td_status |= htole32(UHCI_TD_LS);
- }
- temp.td_token =
- htole32(UHCI_TD_SET_ENDPT(xfer->endpoint) |
- UHCI_TD_SET_DEVADDR(xfer->address));
-
- if (xfer->pipe->toggle_next) {
- /* DATA1 is next */
- temp.td_token |= htole32(UHCI_TD_SET_DT(1));
- }
- /* check if we should prepend a setup message */
-
- if (xfer->flags_int.control_xfr) {
-
- if (xfer->flags_int.control_hdr) {
-
- temp.td_token &= htole32(UHCI_TD_SET_DEVADDR(0x7F) |
- UHCI_TD_SET_ENDPT(0xF));
- temp.td_token |= htole32(UHCI_TD_PID_SETUP |
- UHCI_TD_SET_DT(0));
-
- temp.len = xfer->frlengths[0];
- temp.ml.buf_pc = xfer->frbuffers + 0;
- temp.shortpkt = temp.len ? 1 : 0;
-
- uhci_setup_standard_chain_sub(&temp);
- }
- x = 1;
- } else {
- x = 0;
- }
-
- while (x != xfer->nframes) {
-
- /* DATA0 / DATA1 message */
-
- temp.len = xfer->frlengths[x];
- temp.ml.buf_pc = xfer->frbuffers + x;
-
- x++;
-
- if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
- }
- /*
- * Keep previous data toggle,
- * device address and endpoint number:
- */
-
- temp.td_token &= htole32(UHCI_TD_SET_DEVADDR(0x7F) |
- UHCI_TD_SET_ENDPT(0xF) |
- UHCI_TD_SET_DT(1));
-
- if (temp.len == 0) {
-
- /* make sure that we send an USB packet */
-
- temp.shortpkt = 0;
-
- } else {
-
- /* regular data transfer */
-
- temp.shortpkt = (xfer->flags.force_short_xfer) ? 0 : 1;
- }
-
- /* set endpoint direction */
-
- temp.td_token |=
- (UE_GET_DIR(xfer->endpoint) == UE_DIR_IN) ?
- htole32(UHCI_TD_PID_IN) :
- htole32(UHCI_TD_PID_OUT);
-
- uhci_setup_standard_chain_sub(&temp);
- }
-
- /* check if we should append a status stage */
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- /*
- * send a DATA1 message and reverse the current endpoint
- * direction
- */
-
- temp.td_token &= htole32(UHCI_TD_SET_DEVADDR(0x7F) |
- UHCI_TD_SET_ENDPT(0xF) |
- UHCI_TD_SET_DT(1));
- temp.td_token |=
- (UE_GET_DIR(xfer->endpoint) == UE_DIR_OUT) ?
- htole32(UHCI_TD_PID_IN | UHCI_TD_SET_DT(1)) :
- htole32(UHCI_TD_PID_OUT | UHCI_TD_SET_DT(1));
-
- temp.len = 0;
- temp.ml.buf_pc = NULL;
- temp.shortpkt = 0;
-
- uhci_setup_standard_chain_sub(&temp);
- }
- td = temp.td;
-
- td->td_next = htole32(UHCI_PTR_T);
-
- /* set interrupt bit */
-
- td->td_status |= htole32(UHCI_TD_IOC);
-
- usb2_pc_cpu_flush(td->page_cache);
-
- /* must have at least one frame! */
-
- xfer->td_transfer_last = td;
-
-#if USB_DEBUG
- if (uhcidebug > 8) {
- DPRINTF("nexttog=%d; data before transfer:\n",
- xfer->pipe->toggle_next);
- uhci_dump_tds(xfer->td_transfer_first);
- }
-#endif
- return (xfer->td_transfer_first);
-}
-
-/* NOTE: "done" can be run two times in a row,
- * from close and from interrupt
- */
-
-static void
-uhci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
-{
- struct usb2_pipe_methods *methods = xfer->pipe->methods;
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
- uhci_qh_t *qh;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
- xfer, xfer->pipe, error);
-
- qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
- if (qh) {
- usb2_pc_cpu_invalidate(qh->page_cache);
- }
- if (xfer->flags_int.bandwidth_reclaimed) {
- xfer->flags_int.bandwidth_reclaimed = 0;
- uhci_rem_loop(sc);
- }
- if (methods == &uhci_device_bulk_methods) {
- UHCI_REMOVE_QH(qh, sc->sc_bulk_p_last);
- }
- if (methods == &uhci_device_ctrl_methods) {
- if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
- UHCI_REMOVE_QH(qh, sc->sc_ls_ctl_p_last);
- } else {
- UHCI_REMOVE_QH(qh, sc->sc_fs_ctl_p_last);
- }
- }
- if (methods == &uhci_device_intr_methods) {
- UHCI_REMOVE_QH(qh, sc->sc_intr_p_last[xfer->qh_pos]);
- }
- /*
- * Only finish isochronous transfers once
- * which will update "xfer->frlengths".
- */
- if (xfer->td_transfer_first &&
- xfer->td_transfer_last) {
- if (methods == &uhci_device_isoc_methods) {
- uhci_isoc_done(sc, xfer);
- }
- xfer->td_transfer_first = NULL;
- xfer->td_transfer_last = NULL;
- }
- /* dequeue transfer and start next transfer */
- usb2_transfer_done(xfer, error);
-}
-
-/*------------------------------------------------------------------------*
- * uhci bulk support
- *------------------------------------------------------------------------*/
-static void
-uhci_device_bulk_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_device_bulk_close(struct usb2_xfer *xfer)
-{
- uhci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uhci_device_bulk_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_device_bulk_start(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
- uhci_td_t *td;
- uhci_qh_t *qh;
-
- /* setup TD's */
- td = uhci_setup_standard_chain(xfer);
-
- /* setup QH */
- qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- qh->e_next = td;
- qh->qh_e_next = td->td_self;
-
- if (xfer->xroot->udev->pwr_save.suspended == 0) {
- UHCI_APPEND_QH(qh, sc->sc_bulk_p_last);
- uhci_add_loop(sc);
- xfer->flags_int.bandwidth_reclaimed = 1;
- } else {
- usb2_pc_cpu_flush(qh->page_cache);
- }
-
- /* put transfer on interrupt queue */
- uhci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods uhci_device_bulk_methods =
-{
- .open = uhci_device_bulk_open,
- .close = uhci_device_bulk_close,
- .enter = uhci_device_bulk_enter,
- .start = uhci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * uhci control support
- *------------------------------------------------------------------------*/
-static void
-uhci_device_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_device_ctrl_close(struct usb2_xfer *xfer)
-{
- uhci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uhci_device_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_device_ctrl_start(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
- uhci_qh_t *qh;
- uhci_td_t *td;
-
- /* setup TD's */
- td = uhci_setup_standard_chain(xfer);
-
- /* setup QH */
- qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- qh->e_next = td;
- qh->qh_e_next = td->td_self;
-
- /*
- * NOTE: some devices choke on bandwidth- reclamation for control
- * transfers
- */
- if (xfer->xroot->udev->pwr_save.suspended == 0) {
- if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
- UHCI_APPEND_QH(qh, sc->sc_ls_ctl_p_last);
- } else {
- UHCI_APPEND_QH(qh, sc->sc_fs_ctl_p_last);
- }
- } else {
- usb2_pc_cpu_flush(qh->page_cache);
- }
- /* put transfer on interrupt queue */
- uhci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods uhci_device_ctrl_methods =
-{
- .open = uhci_device_ctrl_open,
- .close = uhci_device_ctrl_close,
- .enter = uhci_device_ctrl_enter,
- .start = uhci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * uhci interrupt support
- *------------------------------------------------------------------------*/
-static void
-uhci_device_intr_open(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
- uint16_t best;
- uint16_t bit;
- uint16_t x;
-
- best = 0;
- bit = UHCI_IFRAMELIST_COUNT / 2;
- while (bit) {
- if (xfer->interval >= bit) {
- x = bit;
- best = bit;
- while (x & bit) {
- if (sc->sc_intr_stat[x] <
- sc->sc_intr_stat[best]) {
- best = x;
- }
- x++;
- }
- break;
- }
- bit >>= 1;
- }
-
- sc->sc_intr_stat[best]++;
- xfer->qh_pos = best;
-
- DPRINTFN(3, "best=%d interval=%d\n",
- best, xfer->interval);
-}
-
-static void
-uhci_device_intr_close(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_intr_stat[xfer->qh_pos]--;
-
- uhci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uhci_device_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_device_intr_start(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
- uhci_qh_t *qh;
- uhci_td_t *td;
-
- /* setup TD's */
- td = uhci_setup_standard_chain(xfer);
-
- /* setup QH */
- qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- qh->e_next = td;
- qh->qh_e_next = td->td_self;
-
- if (xfer->xroot->udev->pwr_save.suspended == 0) {
-
- /* enter QHs into the controller data structures */
- UHCI_APPEND_QH(qh, sc->sc_intr_p_last[xfer->qh_pos]);
-
- } else {
- usb2_pc_cpu_flush(qh->page_cache);
- }
-
- /* put transfer on interrupt queue */
- uhci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods uhci_device_intr_methods =
-{
- .open = uhci_device_intr_open,
- .close = uhci_device_intr_close,
- .enter = uhci_device_intr_enter,
- .start = uhci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * uhci isochronous support
- *------------------------------------------------------------------------*/
-static void
-uhci_device_isoc_open(struct usb2_xfer *xfer)
-{
- uhci_td_t *td;
- uint32_t td_token;
- uint8_t ds;
-
- td_token =
- (UE_GET_DIR(xfer->endpoint) == UE_DIR_IN) ?
- UHCI_TD_IN(0, xfer->endpoint, xfer->address, 0) :
- UHCI_TD_OUT(0, xfer->endpoint, xfer->address, 0);
-
- td_token = htole32(td_token);
-
- /* initialize all TD's */
-
- for (ds = 0; ds != 2; ds++) {
-
- for (td = xfer->td_start[ds]; td; td = td->obj_next) {
-
- /* mark TD as inactive */
- td->td_status = htole32(UHCI_TD_IOS);
- td->td_token = td_token;
-
- usb2_pc_cpu_flush(td->page_cache);
- }
- }
-}
-
-static void
-uhci_device_isoc_close(struct usb2_xfer *xfer)
-{
- uhci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uhci_device_isoc_enter(struct usb2_xfer *xfer)
-{
- struct uhci_mem_layout ml;
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
- uint32_t nframes;
- uint32_t temp;
- uint32_t *plen;
-
-#if USB_DEBUG
- uint8_t once = 1;
-
-#endif
- uhci_td_t *td;
- uhci_td_t *td_last = NULL;
- uhci_td_t **pp_last;
-
- DPRINTFN(6, "xfer=%p next=%d nframes=%d\n",
- xfer, xfer->pipe->isoc_next, xfer->nframes);
-
- nframes = UREAD2(sc, UHCI_FRNUM);
-
- temp = (nframes - xfer->pipe->isoc_next) &
- (UHCI_VFRAMELIST_COUNT - 1);
-
- if ((xfer->pipe->is_synced == 0) ||
- (temp < xfer->nframes)) {
- /*
- * If there is data underflow or the pipe queue is empty we
- * schedule the transfer a few frames ahead of the current
- * frame position. Else two isochronous transfers might
- * overlap.
- */
- xfer->pipe->isoc_next = (nframes + 3) & (UHCI_VFRAMELIST_COUNT - 1);
- xfer->pipe->is_synced = 1;
- DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next);
- }
- /*
- * compute how many milliseconds the insertion is ahead of the
- * current frame position:
- */
- temp = (xfer->pipe->isoc_next - nframes) &
- (UHCI_VFRAMELIST_COUNT - 1);
-
- /*
- * pre-compute when the isochronous transfer will be finished:
- */
- xfer->isoc_time_complete =
- usb2_isoc_time_expand(&sc->sc_bus, nframes) + temp +
- xfer->nframes;
-
- /* get the real number of frames */
-
- nframes = xfer->nframes;
-
- uhci_mem_layout_init(&ml, xfer);
-
- plen = xfer->frlengths;
-
- /* toggle the DMA set we are using */
- xfer->flags_int.curr_dma_set ^= 1;
-
- /* get next DMA set */
- td = xfer->td_start[xfer->flags_int.curr_dma_set];
- xfer->td_transfer_first = td;
-
- pp_last = &sc->sc_isoc_p_last[xfer->pipe->isoc_next];
-
- /* store starting position */
-
- xfer->qh_pos = xfer->pipe->isoc_next;
-
- while (nframes--) {
- if (td == NULL) {
- panic("%s:%d: out of TD's\n",
- __FUNCTION__, __LINE__);
- }
- if (pp_last >= &sc->sc_isoc_p_last[UHCI_VFRAMELIST_COUNT]) {
- pp_last = &sc->sc_isoc_p_last[0];
- }
- if (*plen > xfer->max_frame_size) {
-#if USB_DEBUG
- if (once) {
- once = 0;
- printf("%s: frame length(%d) exceeds %d "
- "bytes (frame truncated)\n",
- __FUNCTION__, *plen,
- xfer->max_frame_size);
- }
-#endif
- *plen = xfer->max_frame_size;
- }
- /* reuse td_token from last transfer */
-
- td->td_token &= htole32(~UHCI_TD_MAXLEN_MASK);
- td->td_token |= htole32(UHCI_TD_SET_MAXLEN(*plen));
-
- td->len = *plen;
-
- if (td->len == 0) {
- /*
- * Do not call "uhci_mem_layout_fixup()" when the
- * length is zero!
- */
- td->td_buffer = 0;
- td->fix_pc = NULL;
-
- } else {
-
- /* fill out buffer pointer and do fixup, if any */
-
- uhci_mem_layout_fixup(&ml, td);
-
- }
-
- /* update status */
- if (nframes == 0) {
- td->td_status = htole32
- (UHCI_TD_ZERO_ACTLEN
- (UHCI_TD_SET_ERRCNT(0) |
- UHCI_TD_ACTIVE |
- UHCI_TD_IOS |
- UHCI_TD_IOC));
- } else {
- td->td_status = htole32
- (UHCI_TD_ZERO_ACTLEN
- (UHCI_TD_SET_ERRCNT(0) |
- UHCI_TD_ACTIVE |
- UHCI_TD_IOS));
- }
-
- usb2_pc_cpu_flush(td->page_cache);
-
-#if USB_DEBUG
- if (uhcidebug > 5) {
- DPRINTF("TD %d\n", nframes);
- uhci_dump_td(td);
- }
-#endif
- /* insert TD into schedule */
- UHCI_APPEND_TD(td, *pp_last);
- pp_last++;
-
- plen++;
- td_last = td;
- td = td->obj_next;
- }
-
- xfer->td_transfer_last = td_last;
-
- /* update isoc_next */
- xfer->pipe->isoc_next = (pp_last - &sc->sc_isoc_p_last[0]) &
- (UHCI_VFRAMELIST_COUNT - 1);
-}
-
-static void
-uhci_device_isoc_start(struct usb2_xfer *xfer)
-{
- /* put transfer on interrupt queue */
- uhci_transfer_intr_enqueue(xfer);
-}
-
-struct usb2_pipe_methods uhci_device_isoc_methods =
-{
- .open = uhci_device_isoc_open,
- .close = uhci_device_isoc_close,
- .enter = uhci_device_isoc_enter,
- .start = uhci_device_isoc_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * uhci root control support
- *------------------------------------------------------------------------*
- * simulate a hardware hub by handling
- * all the necessary requests
- *------------------------------------------------------------------------*/
-
-static void
-uhci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- uhci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/* data structures and routines
- * to emulate the root hub:
- */
-
-static const
-struct usb2_device_descriptor uhci_devd =
-{
- sizeof(struct usb2_device_descriptor),
- UDESC_DEVICE, /* type */
- {0x00, 0x01}, /* USB version */
- UDCLASS_HUB, /* class */
- UDSUBCLASS_HUB, /* subclass */
- UDPROTO_FSHUB, /* protocol */
- 64, /* max packet */
- {0}, {0}, {0x00, 0x01}, /* device id */
- 1, 2, 0, /* string indicies */
- 1 /* # of configurations */
-};
-
-static const struct uhci_config_desc uhci_confd = {
- .confd = {
- .bLength = sizeof(struct usb2_config_descriptor),
- .bDescriptorType = UDESC_CONFIG,
- .wTotalLength[0] = sizeof(uhci_confd),
- .bNumInterface = 1,
- .bConfigurationValue = 1,
- .iConfiguration = 0,
- .bmAttributes = UC_SELF_POWERED,
- .bMaxPower = 0 /* max power */
- },
-
- .ifcd = {
- .bLength = sizeof(struct usb2_interface_descriptor),
- .bDescriptorType = UDESC_INTERFACE,
- .bNumEndpoints = 1,
- .bInterfaceClass = UICLASS_HUB,
- .bInterfaceSubClass = UISUBCLASS_HUB,
- .bInterfaceProtocol = UIPROTO_FSHUB,
- },
-
- .endpd = {
- .bLength = sizeof(struct usb2_endpoint_descriptor),
- .bDescriptorType = UDESC_ENDPOINT,
- .bEndpointAddress = UE_DIR_IN | UHCI_INTR_ENDPT,
- .bmAttributes = UE_INTERRUPT,
- .wMaxPacketSize[0] = 8, /* max packet (63 ports) */
- .bInterval = 255,
- },
-};
-
-static const
-struct usb2_hub_descriptor_min uhci_hubd_piix =
-{
- sizeof(uhci_hubd_piix),
- UDESC_HUB,
- 2,
- {UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL, 0},
- 50, /* power on to power good */
- 0,
- {0x00}, /* both ports are removable */
-};
-
-/*
- * The USB hub protocol requires that SET_FEATURE(PORT_RESET) also
- * enables the port, and also states that SET_FEATURE(PORT_ENABLE)
- * should not be used by the USB subsystem. As we cannot issue a
- * SET_FEATURE(PORT_ENABLE) externally, we must ensure that the port
- * will be enabled as part of the reset.
- *
- * On the VT83C572, the port cannot be successfully enabled until the
- * outstanding "port enable change" and "connection status change"
- * events have been reset.
- */
-static usb2_error_t
-uhci_portreset(uhci_softc_t *sc, uint16_t index, uint8_t use_polling)
-{
- uint16_t port;
- uint16_t x;
- uint8_t lim;
-
- if (index == 1)
- port = UHCI_PORTSC1;
- else if (index == 2)
- port = UHCI_PORTSC2;
- else
- return (USB_ERR_IOERROR);
-
- /*
- * Before we do anything, turn on SOF messages on the USB
- * BUS. Some USB devices do not cope without them!
- */
- if (!(UREAD2(sc, UHCI_CMD) & UHCI_CMD_RS)) {
-
- DPRINTF("Activating SOFs!\n");
-
- UHCICMD(sc, (UHCI_CMD_MAXP | UHCI_CMD_RS));
-
- /* wait a little bit */
- if (use_polling) {
- DELAY(10000);
- } else {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100);
- }
- }
-
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x | UHCI_PORTSC_PR);
-
- if (use_polling) {
- /* polling */
- DELAY(USB_PORT_ROOT_RESET_DELAY * 1000);
- } else {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_PORT_ROOT_RESET_DELAY));
- }
-
- DPRINTFN(4, "uhci port %d reset, status0 = 0x%04x\n",
- index, UREAD2(sc, port));
-
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x & ~UHCI_PORTSC_PR);
-
-
- mtx_unlock(&sc->sc_bus.bus_mtx);
-
- /*
- * This delay needs to be exactly 100us, else some USB devices
- * fail to attach!
- */
- DELAY(100);
-
- mtx_lock(&sc->sc_bus.bus_mtx);
-
- DPRINTFN(4, "uhci port %d reset, status1 = 0x%04x\n",
- index, UREAD2(sc, port));
-
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x | UHCI_PORTSC_PE);
-
- for (lim = 0; lim < 12; lim++) {
-
- if (use_polling) {
- /* polling */
- DELAY(USB_PORT_RESET_DELAY * 1000);
- } else {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx,
- USB_MS_TO_TICKS(USB_PORT_RESET_DELAY));
- }
-
- x = UREAD2(sc, port);
-
- DPRINTFN(4, "uhci port %d iteration %u, status = 0x%04x\n",
- index, lim, x);
-
- if (!(x & UHCI_PORTSC_CCS)) {
- /*
- * No device is connected (or was disconnected
- * during reset). Consider the port reset.
- * The delay must be long enough to ensure on
- * the initial iteration that the device
- * connection will have been registered. 50ms
- * appears to be sufficient, but 20ms is not.
- */
- DPRINTFN(4, "uhci port %d loop %u, device detached\n",
- index, lim);
- goto done;
- }
- if (x & (UHCI_PORTSC_POEDC | UHCI_PORTSC_CSC)) {
- /*
- * Port enabled changed and/or connection
- * status changed were set. Reset either or
- * both raised flags (by writing a 1 to that
- * bit), and wait again for state to settle.
- */
- UWRITE2(sc, port, URWMASK(x) |
- (x & (UHCI_PORTSC_POEDC | UHCI_PORTSC_CSC)));
- continue;
- }
- if (x & UHCI_PORTSC_PE) {
- /* port is enabled */
- goto done;
- }
- UWRITE2(sc, port, URWMASK(x) | UHCI_PORTSC_PE);
- }
-
- DPRINTFN(2, "uhci port %d reset timed out\n", index);
- return (USB_ERR_TIMEOUT);
-
-done:
- DPRINTFN(4, "uhci port %d reset, status2 = 0x%04x\n",
- index, UREAD2(sc, port));
-
- sc->sc_isreset = 1;
- return (USB_ERR_NORMAL_COMPLETION);
-}
-
-static void
-uhci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- DPRINTF("\n");
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-uhci_root_ctrl_task(struct usb2_bus *bus)
-{
- uhci_root_ctrl_poll(UHCI_BUS2SC(bus));
-}
-
-static void
-uhci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
- char *ptr;
- uint16_t x;
- uint16_t port;
- uint16_t value;
- uint16_t index;
- uint16_t status;
- uint16_t change;
- uint8_t use_polling;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- uhci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* buffer reset */
- std->ptr = sc->sc_hub_desc.temp;
- std->len = 0;
-
- value = UGETW(std->req.wValue);
- index = UGETW(std->req.wIndex);
-
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- DPRINTFN(3, "type=0x%02x request=0x%02x wLen=0x%04x "
- "wValue=0x%04x wIndex=0x%04x\n",
- std->req.bmRequestType, std->req.bRequest,
- UGETW(std->req.wLength), value, index);
-
-#define C(x,y) ((x) | ((y) << 8))
- switch (C(std->req.bRequest, std->req.bmRequestType)) {
- case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
- case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
- case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
- /*
- * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
- * for the integrated root hub.
- */
- break;
- case C(UR_GET_CONFIG, UT_READ_DEVICE):
- std->len = 1;
- sc->sc_hub_desc.temp[0] = sc->sc_conf;
- break;
- case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
- switch (value >> 8) {
- case UDESC_DEVICE:
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- std->len = sizeof(uhci_devd);
- sc->sc_hub_desc.devd = uhci_devd;
- break;
-
- case UDESC_CONFIG:
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- std->len = sizeof(uhci_confd);
- std->ptr = USB_ADD_BYTES(&uhci_confd, 0);
- break;
-
- case UDESC_STRING:
- switch (value & 0xff) {
- case 0: /* Language table */
- ptr = "\001";
- break;
-
- case 1: /* Vendor */
- ptr = sc->sc_vendor;
- break;
-
- case 2: /* Product */
- ptr = "UHCI root HUB";
- break;
-
- default:
- ptr = "";
- break;
- }
-
- std->len = usb2_make_str_desc
- (sc->sc_hub_desc.temp,
- sizeof(sc->sc_hub_desc.temp),
- ptr);
- break;
-
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- break;
- case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
- std->len = 1;
- sc->sc_hub_desc.temp[0] = 0;
- break;
- case C(UR_GET_STATUS, UT_READ_DEVICE):
- std->len = 2;
- USETW(sc->sc_hub_desc.stat.wStatus, UDS_SELF_POWERED);
- break;
- case C(UR_GET_STATUS, UT_READ_INTERFACE):
- case C(UR_GET_STATUS, UT_READ_ENDPOINT):
- std->len = 2;
- USETW(sc->sc_hub_desc.stat.wStatus, 0);
- break;
- case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
- if (value >= USB_MAX_DEVICES) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- sc->sc_addr = value;
- break;
- case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
- if ((value != 0) && (value != 1)) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- sc->sc_conf = value;
- break;
- case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
- break;
- case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
- case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
- case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
- std->err = USB_ERR_IOERROR;
- goto done;
- case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
- break;
- case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
- break;
- /* Hub requests */
- case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
- break;
- case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
- DPRINTFN(4, "UR_CLEAR_PORT_FEATURE "
- "port=%d feature=%d\n",
- index, value);
- if (index == 1)
- port = UHCI_PORTSC1;
- else if (index == 2)
- port = UHCI_PORTSC2;
- else {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- switch (value) {
- case UHF_PORT_ENABLE:
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x & ~UHCI_PORTSC_PE);
- break;
- case UHF_PORT_SUSPEND:
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x & ~(UHCI_PORTSC_SUSP));
- break;
- case UHF_PORT_RESET:
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x & ~UHCI_PORTSC_PR);
- break;
- case UHF_C_PORT_CONNECTION:
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x | UHCI_PORTSC_CSC);
- break;
- case UHF_C_PORT_ENABLE:
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x | UHCI_PORTSC_POEDC);
- break;
- case UHF_C_PORT_OVER_CURRENT:
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x | UHCI_PORTSC_OCIC);
- break;
- case UHF_C_PORT_RESET:
- sc->sc_isreset = 0;
- std->err = USB_ERR_NORMAL_COMPLETION;
- goto done;
- case UHF_C_PORT_SUSPEND:
- sc->sc_isresumed &= ~(1 << index);
- break;
- case UHF_PORT_CONNECTION:
- case UHF_PORT_OVER_CURRENT:
- case UHF_PORT_POWER:
- case UHF_PORT_LOW_SPEED:
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- break;
- case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
- if (index == 1)
- port = UHCI_PORTSC1;
- else if (index == 2)
- port = UHCI_PORTSC2;
- else {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- std->len = 1;
- sc->sc_hub_desc.temp[0] =
- ((UREAD2(sc, port) & UHCI_PORTSC_LS) >>
- UHCI_PORTSC_LS_SHIFT);
- break;
- case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
- if ((value & 0xff) != 0) {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- std->len = sizeof(uhci_hubd_piix);
- std->ptr = USB_ADD_BYTES(&uhci_hubd_piix, 0);
- break;
- case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
- std->len = 16;
- bzero(sc->sc_hub_desc.temp, 16);
- break;
- case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
- if (index == 1)
- port = UHCI_PORTSC1;
- else if (index == 2)
- port = UHCI_PORTSC2;
- else {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- x = UREAD2(sc, port);
- status = change = 0;
- if (x & UHCI_PORTSC_CCS)
- status |= UPS_CURRENT_CONNECT_STATUS;
- if (x & UHCI_PORTSC_CSC)
- change |= UPS_C_CONNECT_STATUS;
- if (x & UHCI_PORTSC_PE)
- status |= UPS_PORT_ENABLED;
- if (x & UHCI_PORTSC_POEDC)
- change |= UPS_C_PORT_ENABLED;
- if (x & UHCI_PORTSC_OCI)
- status |= UPS_OVERCURRENT_INDICATOR;
- if (x & UHCI_PORTSC_OCIC)
- change |= UPS_C_OVERCURRENT_INDICATOR;
- if (x & UHCI_PORTSC_LSDA)
- status |= UPS_LOW_SPEED;
- if ((x & UHCI_PORTSC_PE) && (x & UHCI_PORTSC_RD)) {
- /* need to do a write back */
- UWRITE2(sc, port, URWMASK(x));
-
- /* wait 20ms for resume sequence to complete */
- if (use_polling) {
- /* polling */
- DELAY(20000);
- } else {
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 50);
- }
-
- /* clear suspend and resume detect */
- UWRITE2(sc, port, URWMASK(x) & ~(UHCI_PORTSC_RD |
- UHCI_PORTSC_SUSP));
-
- /* wait a little bit */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 500);
-
- sc->sc_isresumed |= (1 << index);
-
- } else if (x & UHCI_PORTSC_SUSP) {
- status |= UPS_SUSPEND;
- }
- status |= UPS_PORT_POWER;
- if (sc->sc_isresumed & (1 << index))
- change |= UPS_C_SUSPEND;
- if (sc->sc_isreset)
- change |= UPS_C_PORT_RESET;
- USETW(sc->sc_hub_desc.ps.wPortStatus, status);
- USETW(sc->sc_hub_desc.ps.wPortChange, change);
- std->len = sizeof(sc->sc_hub_desc.ps);
- break;
- case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
- std->err = USB_ERR_IOERROR;
- goto done;
- case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
- break;
- case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
- if (index == 1)
- port = UHCI_PORTSC1;
- else if (index == 2)
- port = UHCI_PORTSC2;
- else {
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- switch (value) {
- case UHF_PORT_ENABLE:
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x | UHCI_PORTSC_PE);
- break;
- case UHF_PORT_SUSPEND:
- x = URWMASK(UREAD2(sc, port));
- UWRITE2(sc, port, x | UHCI_PORTSC_SUSP);
- break;
- case UHF_PORT_RESET:
- std->err = uhci_portreset(sc, index, use_polling);
- goto done;
- case UHF_PORT_POWER:
- /* pretend we turned on power */
- std->err = USB_ERR_NORMAL_COMPLETION;
- goto done;
- case UHF_C_PORT_CONNECTION:
- case UHF_C_PORT_ENABLE:
- case UHF_C_PORT_OVER_CURRENT:
- case UHF_PORT_CONNECTION:
- case UHF_PORT_OVER_CURRENT:
- case UHF_PORT_LOW_SPEED:
- case UHF_C_PORT_SUSPEND:
- case UHF_C_PORT_RESET:
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
-done:
- return;
-}
-
-static void
-uhci_root_ctrl_poll(struct uhci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &uhci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods uhci_root_ctrl_methods =
-{
- .open = uhci_root_ctrl_open,
- .close = uhci_root_ctrl_close,
- .enter = uhci_root_ctrl_enter,
- .start = uhci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * uhci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-uhci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_root_intr_close(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- uhci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uhci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_root_intr_start(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-
- usb2_transfer_timeout_ms(xfer,
- &uhci_root_intr_check, xfer->interval);
-}
-
-static void
-uhci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer is transferred */
- uhci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-done:
- return;
-}
-
-/*
- * this routine is executed periodically and simulates interrupts
- * from the root controller interrupt pipe for port status change
- */
-static void
-uhci_root_intr_check(void *arg)
-{
- struct usb2_xfer *xfer = arg;
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- DPRINTFN(21, "\n");
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- sc->sc_hub_idata[0] = 0;
-
- if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC |
- UHCI_PORTSC_OCIC | UHCI_PORTSC_RD)) {
- sc->sc_hub_idata[0] |= 1 << 1;
- }
- if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC |
- UHCI_PORTSC_OCIC | UHCI_PORTSC_RD)) {
- sc->sc_hub_idata[0] |= 1 << 2;
- }
- if (sc->sc_hub_idata[0] == 0) {
- /*
- * no change or controller not running, try again in a while
- */
- uhci_root_intr_start(xfer);
- } else {
- usb2_sw_transfer(&sc->sc_root_intr,
- &uhci_root_intr_done);
- }
-}
-
-struct usb2_pipe_methods uhci_root_intr_methods =
-{
- .open = uhci_root_intr_open,
- .close = uhci_root_intr_close,
- .enter = uhci_root_intr_enter,
- .start = uhci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
-uhci_xfer_setup(struct usb2_setup_params *parm)
-{
- struct usb2_page_search page_info;
- struct usb2_page_cache *pc;
- uhci_softc_t *sc;
- struct usb2_xfer *xfer;
- void *last_obj;
- uint32_t ntd;
- uint32_t nqh;
- uint32_t nfixup;
- uint32_t n;
- uint16_t align;
-
- sc = UHCI_BUS2SC(parm->udev->bus);
- xfer = parm->curr_xfer;
-
- parm->hc_max_packet_size = 0x500;
- parm->hc_max_packet_count = 1;
- parm->hc_max_frame_size = 0x500;
-
- /*
- * compute ntd and nqh
- */
- if (parm->methods == &uhci_device_ctrl_methods) {
- xfer->flags_int.bdma_enable = 1;
- xfer->flags_int.bdma_no_post_sync = 1;
-
- usb2_transfer_setup_sub(parm);
-
- /* see EHCI HC driver for proof of "ntd" formula */
-
- nqh = 1;
- ntd = ((2 * xfer->nframes) + 1 /* STATUS */
- + (xfer->max_data_length / xfer->max_frame_size));
-
- } else if (parm->methods == &uhci_device_bulk_methods) {
- xfer->flags_int.bdma_enable = 1;
- xfer->flags_int.bdma_no_post_sync = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nqh = 1;
- ntd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_frame_size));
-
- } else if (parm->methods == &uhci_device_intr_methods) {
- xfer->flags_int.bdma_enable = 1;
- xfer->flags_int.bdma_no_post_sync = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nqh = 1;
- ntd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_frame_size));
-
- } else if (parm->methods == &uhci_device_isoc_methods) {
- xfer->flags_int.bdma_enable = 1;
- xfer->flags_int.bdma_no_post_sync = 1;
-
- usb2_transfer_setup_sub(parm);
-
- nqh = 0;
- ntd = xfer->nframes;
-
- } else {
-
- usb2_transfer_setup_sub(parm);
-
- nqh = 0;
- ntd = 0;
- }
-
- if (parm->err) {
- return;
- }
- /*
- * NOTE: the UHCI controller requires that
- * every packet must be contiguous on
- * the same USB memory page !
- */
- nfixup = (parm->bufsize / USB_PAGE_SIZE) + 1;
-
- /*
- * Compute a suitable power of two alignment
- * for our "max_frame_size" fixup buffer(s):
- */
- align = xfer->max_frame_size;
- n = 0;
- while (align) {
- align >>= 1;
- n++;
- }
-
- /* check for power of two */
- if (!(xfer->max_frame_size &
- (xfer->max_frame_size - 1))) {
- n--;
- }
- /*
- * We don't allow alignments of
- * less than 8 bytes:
- *
- * NOTE: Allocating using an aligment
- * of 1 byte has special meaning!
- */
- if (n < 3) {
- n = 3;
- }
- align = (1 << n);
-
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, xfer->max_frame_size,
- align, nfixup)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- xfer->buf_fixup = pc;
-
-alloc_dma_set:
-
- if (parm->err) {
- return;
- }
- last_obj = NULL;
-
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, sizeof(uhci_td_t),
- UHCI_TD_ALIGN, ntd)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- if (parm->buf) {
- for (n = 0; n != ntd; n++) {
- uhci_td_t *td;
-
- usb2_get_page(pc + n, 0, &page_info);
-
- td = page_info.buffer;
-
- /* init TD */
- if ((parm->methods == &uhci_device_bulk_methods) ||
- (parm->methods == &uhci_device_ctrl_methods) ||
- (parm->methods == &uhci_device_intr_methods)) {
- /* set depth first bit */
- td->td_self = htole32(page_info.physaddr |
- UHCI_PTR_TD | UHCI_PTR_VF);
- } else {
- td->td_self = htole32(page_info.physaddr |
- UHCI_PTR_TD);
- }
-
- td->obj_next = last_obj;
- td->page_cache = pc + n;
-
- last_obj = td;
-
- usb2_pc_cpu_flush(pc + n);
- }
- }
- xfer->td_start[xfer->flags_int.curr_dma_set] = last_obj;
-
- last_obj = NULL;
-
- if (usb2_transfer_setup_sub_malloc(
- parm, &pc, sizeof(uhci_qh_t),
- UHCI_QH_ALIGN, nqh)) {
- parm->err = USB_ERR_NOMEM;
- return;
- }
- if (parm->buf) {
- for (n = 0; n != nqh; n++) {
- uhci_qh_t *qh;
-
- usb2_get_page(pc + n, 0, &page_info);
-
- qh = page_info.buffer;
-
- /* init QH */
- qh->qh_self = htole32(page_info.physaddr | UHCI_PTR_QH);
- qh->obj_next = last_obj;
- qh->page_cache = pc + n;
-
- last_obj = qh;
-
- usb2_pc_cpu_flush(pc + n);
- }
- }
- xfer->qh_start[xfer->flags_int.curr_dma_set] = last_obj;
-
- if (!xfer->flags_int.curr_dma_set) {
- xfer->flags_int.curr_dma_set = 1;
- goto alloc_dma_set;
- }
-}
-
-static void
-uhci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
- struct usb2_pipe *pipe)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(udev->bus);
-
- DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
- pipe, udev->address,
- edesc->bEndpointAddress, udev->flags.usb2_mode,
- sc->sc_addr);
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- if (udev->device_index == sc->sc_addr) {
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &uhci_root_ctrl_methods;
- break;
- case UE_DIR_IN | UHCI_INTR_ENDPT:
- pipe->methods = &uhci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
- switch (edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- pipe->methods = &uhci_device_ctrl_methods;
- break;
- case UE_INTERRUPT:
- pipe->methods = &uhci_device_intr_methods;
- break;
- case UE_ISOCHRONOUS:
- if (udev->speed == USB_SPEED_FULL) {
- pipe->methods = &uhci_device_isoc_methods;
- }
- break;
- case UE_BULK:
- if (udev->speed != USB_SPEED_LOW) {
- pipe->methods = &uhci_device_bulk_methods;
- }
- break;
- default:
- /* do nothing */
- break;
- }
- }
-}
-
-static void
-uhci_xfer_unsetup(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_get_dma_delay(struct usb2_bus *bus, uint32_t *pus)
-{
- /*
- * Wait until hardware has finished any possible use of the
- * transfer descriptor(s) and QH
- */
- *pus = (1125); /* microseconds */
-}
-
-static void
-uhci_device_resume(struct usb2_device *udev)
-{
- struct uhci_softc *sc = UHCI_BUS2SC(udev->bus);
- struct usb2_xfer *xfer;
- struct usb2_pipe_methods *methods;
- uhci_qh_t *qh;
-
- DPRINTF("\n");
-
- USB_BUS_LOCK(udev->bus);
-
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-
- if (xfer->xroot->udev == udev) {
-
- methods = xfer->pipe->methods;
- qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- if (methods == &uhci_device_bulk_methods) {
- UHCI_APPEND_QH(qh, sc->sc_bulk_p_last);
- uhci_add_loop(sc);
- xfer->flags_int.bandwidth_reclaimed = 1;
- }
- if (methods == &uhci_device_ctrl_methods) {
- if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
- UHCI_APPEND_QH(qh, sc->sc_ls_ctl_p_last);
- } else {
- UHCI_APPEND_QH(qh, sc->sc_fs_ctl_p_last);
- }
- }
- if (methods == &uhci_device_intr_methods) {
- UHCI_APPEND_QH(qh, sc->sc_intr_p_last[xfer->qh_pos]);
- }
- }
- }
-
- USB_BUS_UNLOCK(udev->bus);
-
- return;
-}
-
-static void
-uhci_device_suspend(struct usb2_device *udev)
-{
- struct uhci_softc *sc = UHCI_BUS2SC(udev->bus);
- struct usb2_xfer *xfer;
- struct usb2_pipe_methods *methods;
- uhci_qh_t *qh;
-
- DPRINTF("\n");
-
- USB_BUS_LOCK(udev->bus);
-
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-
- if (xfer->xroot->udev == udev) {
-
- methods = xfer->pipe->methods;
- qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
-
- if (xfer->flags_int.bandwidth_reclaimed) {
- xfer->flags_int.bandwidth_reclaimed = 0;
- uhci_rem_loop(sc);
- }
- if (methods == &uhci_device_bulk_methods) {
- UHCI_REMOVE_QH(qh, sc->sc_bulk_p_last);
- }
- if (methods == &uhci_device_ctrl_methods) {
- if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
- UHCI_REMOVE_QH(qh, sc->sc_ls_ctl_p_last);
- } else {
- UHCI_REMOVE_QH(qh, sc->sc_fs_ctl_p_last);
- }
- }
- if (methods == &uhci_device_intr_methods) {
- UHCI_REMOVE_QH(qh, sc->sc_intr_p_last[xfer->qh_pos]);
- }
- }
- }
-
- USB_BUS_UNLOCK(udev->bus);
-
- return;
-}
-
-static void
-uhci_set_hw_power(struct usb2_bus *bus)
-{
- struct uhci_softc *sc = UHCI_BUS2SC(bus);
- uint32_t flags;
-
- DPRINTF("\n");
-
- USB_BUS_LOCK(bus);
-
- flags = bus->hw_power_state;
-
- /*
- * WARNING: Some FULL speed USB devices require periodic SOF
- * messages! If any USB devices are connected through the
- * UHCI, power save will be disabled!
- */
- if (flags & (USB_HW_POWER_CONTROL |
- USB_HW_POWER_NON_ROOT_HUB |
- USB_HW_POWER_BULK |
- USB_HW_POWER_INTERRUPT |
- USB_HW_POWER_ISOC)) {
- DPRINTF("Some USB transfer is "
- "active on %u.\n",
- device_get_unit(sc->sc_bus.bdev));
- UHCICMD(sc, (UHCI_CMD_MAXP | UHCI_CMD_RS));
- } else {
- DPRINTF("Power save on %u.\n",
- device_get_unit(sc->sc_bus.bdev));
- UHCICMD(sc, UHCI_CMD_MAXP);
- }
-
- USB_BUS_UNLOCK(bus);
-
- return;
-}
-
-
-struct usb2_bus_methods uhci_bus_methods =
-{
- .pipe_init = uhci_pipe_init,
- .xfer_setup = uhci_xfer_setup,
- .xfer_unsetup = uhci_xfer_unsetup,
- .do_poll = uhci_do_poll,
- .get_dma_delay = uhci_get_dma_delay,
- .device_resume = uhci_device_resume,
- .device_suspend = uhci_device_suspend,
- .set_hw_power = uhci_set_hw_power,
- .roothub_exec = uhci_root_ctrl_task,
-};
diff --git a/sys/dev/usb2/controller/uhci2.h b/sys/dev/usb2/controller/uhci2.h
deleted file mode 100644
index 9365a4c..0000000
--- a/sys/dev/usb2/controller/uhci2.h
+++ /dev/null
@@ -1,321 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (lennart@augustsson.net) at
- * Carlstedt Research & Technology.
- *
- * 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.
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``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 FOUNDATION OR CONTRIBUTORS
- * 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.
- */
-
-#ifndef _UHCI_H_
-#define _UHCI_H_
-
-#define UHCI_MAX_DEVICES USB_MAX_DEVICES
-
-/* PCI config registers */
-#define PCI_USBREV 0x60 /* USB protocol revision */
-#define PCI_USB_REV_MASK 0xff
-#define PCI_USB_REV_PRE_1_0 0x00
-#define PCI_USB_REV_1_0 0x10
-#define PCI_USB_REV_1_1 0x11
-#define PCI_LEGSUP 0xc0 /* Legacy Support register */
-#define PCI_LEGSUP_USBPIRQDEN 0x2000 /* USB PIRQ D Enable */
-#define PCI_CBIO 0x20 /* configuration base IO */
-#define PCI_INTERFACE_UHCI 0x00
-
-/* UHCI registers */
-#define UHCI_CMD 0x00
-#define UHCI_CMD_RS 0x0001
-#define UHCI_CMD_HCRESET 0x0002
-#define UHCI_CMD_GRESET 0x0004
-#define UHCI_CMD_EGSM 0x0008
-#define UHCI_CMD_FGR 0x0010
-#define UHCI_CMD_SWDBG 0x0020
-#define UHCI_CMD_CF 0x0040
-#define UHCI_CMD_MAXP 0x0080
-#define UHCI_STS 0x02
-#define UHCI_STS_USBINT 0x0001
-#define UHCI_STS_USBEI 0x0002
-#define UHCI_STS_RD 0x0004
-#define UHCI_STS_HSE 0x0008
-#define UHCI_STS_HCPE 0x0010
-#define UHCI_STS_HCH 0x0020
-#define UHCI_STS_ALLINTRS 0x003f
-#define UHCI_INTR 0x04
-#define UHCI_INTR_TOCRCIE 0x0001
-#define UHCI_INTR_RIE 0x0002
-#define UHCI_INTR_IOCE 0x0004
-#define UHCI_INTR_SPIE 0x0008
-#define UHCI_FRNUM 0x06
-#define UHCI_FRNUM_MASK 0x03ff
-#define UHCI_FLBASEADDR 0x08
-#define UHCI_SOF 0x0c
-#define UHCI_SOF_MASK 0x7f
-#define UHCI_PORTSC1 0x010
-#define UHCI_PORTSC2 0x012
-#define UHCI_PORTSC_CCS 0x0001
-#define UHCI_PORTSC_CSC 0x0002
-#define UHCI_PORTSC_PE 0x0004
-#define UHCI_PORTSC_POEDC 0x0008
-#define UHCI_PORTSC_LS 0x0030
-#define UHCI_PORTSC_LS_SHIFT 4
-#define UHCI_PORTSC_RD 0x0040
-#define UHCI_PORTSC_LSDA 0x0100
-#define UHCI_PORTSC_PR 0x0200
-#define UHCI_PORTSC_OCI 0x0400
-#define UHCI_PORTSC_OCIC 0x0800
-#define UHCI_PORTSC_SUSP 0x1000
-
-#define URWMASK(x) ((x) & (UHCI_PORTSC_SUSP | \
- UHCI_PORTSC_PR | UHCI_PORTSC_RD | \
- UHCI_PORTSC_PE))
-
-#define UHCI_FRAMELIST_COUNT 1024 /* units */
-#define UHCI_FRAMELIST_ALIGN 4096 /* bytes */
-
-/* Structures alignment (bytes) */
-#define UHCI_TD_ALIGN 16
-#define UHCI_QH_ALIGN 16
-
-#if ((USB_PAGE_SIZE < UHCI_TD_ALIGN) || (UHCI_TD_ALIGN == 0) || \
- (USB_PAGE_SIZE < UHCI_QH_ALIGN) || (UHCI_QH_ALIGN == 0))
-#error "Invalid USB page size!"
-#endif
-
-typedef uint32_t uhci_physaddr_t;
-
-#define UHCI_PTR_T 0x00000001
-#define UHCI_PTR_TD 0x00000000
-#define UHCI_PTR_QH 0x00000002
-#define UHCI_PTR_VF 0x00000004
-
-#define UHCI_QH_REMOVE_DELAY 5 /* us - QH remove delay */
-
-/*
- * The Queue Heads (QH) and Transfer Descriptors (TD) are accessed by
- * both the CPU and the USB-controller which run concurrently. Great
- * care must be taken. When the data-structures are linked into the
- * USB controller's frame list, the USB-controller "owns" the
- * td_status and qh_elink fields, which will not be written by the
- * CPU.
- *
- */
-
-struct uhci_td {
-/*
- * Data used by the UHCI controller.
- * volatile is used in order to mantain struct members ordering.
- */
- volatile uint32_t td_next;
- volatile uint32_t td_status;
-#define UHCI_TD_GET_ACTLEN(s) (((s) + 1) & 0x3ff)
-#define UHCI_TD_ZERO_ACTLEN(t) ((t) | 0x3ff)
-#define UHCI_TD_BITSTUFF 0x00020000
-#define UHCI_TD_CRCTO 0x00040000
-#define UHCI_TD_NAK 0x00080000
-#define UHCI_TD_BABBLE 0x00100000
-#define UHCI_TD_DBUFFER 0x00200000
-#define UHCI_TD_STALLED 0x00400000
-#define UHCI_TD_ACTIVE 0x00800000
-#define UHCI_TD_IOC 0x01000000
-#define UHCI_TD_IOS 0x02000000
-#define UHCI_TD_LS 0x04000000
-#define UHCI_TD_GET_ERRCNT(s) (((s) >> 27) & 3)
-#define UHCI_TD_SET_ERRCNT(n) ((n) << 27)
-#define UHCI_TD_SPD 0x20000000
- volatile uint32_t td_token;
-#define UHCI_TD_PID 0x000000ff
-#define UHCI_TD_PID_IN 0x00000069
-#define UHCI_TD_PID_OUT 0x000000e1
-#define UHCI_TD_PID_SETUP 0x0000002d
-#define UHCI_TD_GET_PID(s) ((s) & 0xff)
-#define UHCI_TD_SET_DEVADDR(a) ((a) << 8)
-#define UHCI_TD_GET_DEVADDR(s) (((s) >> 8) & 0x7f)
-#define UHCI_TD_SET_ENDPT(e) (((e) & 0xf) << 15)
-#define UHCI_TD_GET_ENDPT(s) (((s) >> 15) & 0xf)
-#define UHCI_TD_SET_DT(t) ((t) << 19)
-#define UHCI_TD_GET_DT(s) (((s) >> 19) & 1)
-#define UHCI_TD_SET_MAXLEN(l) (((l)-1) << 21)
-#define UHCI_TD_GET_MAXLEN(s) ((((s) >> 21) + 1) & 0x7ff)
-#define UHCI_TD_MAXLEN_MASK 0xffe00000
- volatile uint32_t td_buffer;
-/*
- * Extra information needed:
- */
- struct uhci_td *next;
- struct uhci_td *prev;
- struct uhci_td *obj_next;
- struct usb2_page_cache *page_cache;
- struct usb2_page_cache *fix_pc;
- uint32_t td_self;
- uint16_t len;
-} __aligned(UHCI_TD_ALIGN);
-
-typedef struct uhci_td uhci_td_t;
-
-#define UHCI_TD_ERROR (UHCI_TD_BITSTUFF | UHCI_TD_CRCTO | \
- UHCI_TD_BABBLE | UHCI_TD_DBUFFER | UHCI_TD_STALLED)
-
-#define UHCI_TD_SETUP(len, endp, dev) (UHCI_TD_SET_MAXLEN(len) | \
- UHCI_TD_SET_ENDPT(endp) | \
- UHCI_TD_SET_DEVADDR(dev) | \
- UHCI_TD_PID_SETUP)
-
-#define UHCI_TD_OUT(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \
- UHCI_TD_SET_ENDPT(endp) | \
- UHCI_TD_SET_DEVADDR(dev) | \
- UHCI_TD_PID_OUT | UHCI_TD_SET_DT(dt))
-
-#define UHCI_TD_IN(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \
- UHCI_TD_SET_ENDPT(endp) | \
- UHCI_TD_SET_DEVADDR(dev) | \
- UHCI_TD_PID_IN | UHCI_TD_SET_DT(dt))
-
-struct uhci_qh {
-/*
- * Data used by the UHCI controller.
- */
- volatile uint32_t qh_h_next;
- volatile uint32_t qh_e_next;
-/*
- * Extra information needed:
- */
- struct uhci_qh *h_next;
- struct uhci_qh *h_prev;
- struct uhci_qh *obj_next;
- struct uhci_td *e_next;
- struct usb2_page_cache *page_cache;
- uint32_t qh_self;
- uint16_t intr_pos;
-} __aligned(UHCI_QH_ALIGN);
-
-typedef struct uhci_qh uhci_qh_t;
-
-/* Maximum number of isochronous TD's and QH's interrupt */
-#define UHCI_VFRAMELIST_COUNT 128
-#define UHCI_IFRAMELIST_COUNT (2 * UHCI_VFRAMELIST_COUNT)
-
-#if (((UHCI_VFRAMELIST_COUNT & (UHCI_VFRAMELIST_COUNT-1)) != 0) || \
- (UHCI_VFRAMELIST_COUNT > UHCI_FRAMELIST_COUNT))
-#error "UHCI_VFRAMELIST_COUNT is not power of two"
-#error "or UHCI_VFRAMELIST_COUNT > UHCI_FRAMELIST_COUNT"
-#endif
-
-#if (UHCI_VFRAMELIST_COUNT < USB_MAX_FS_ISOC_FRAMES_PER_XFER)
-#error "maximum number of full-speed isochronous frames is higher than supported!"
-#endif
-
-struct uhci_config_desc {
- struct usb2_config_descriptor confd;
- struct usb2_interface_descriptor ifcd;
- struct usb2_endpoint_descriptor endpd;
-} __packed;
-
-union uhci_hub_desc {
- struct usb2_status stat;
- struct usb2_port_status ps;
- struct usb2_device_descriptor devd;
- uint8_t temp[128];
-};
-
-struct uhci_hw_softc {
- struct usb2_page_cache pframes_pc;
- struct usb2_page_cache isoc_start_pc[UHCI_VFRAMELIST_COUNT];
- struct usb2_page_cache intr_start_pc[UHCI_IFRAMELIST_COUNT];
- struct usb2_page_cache ls_ctl_start_pc;
- struct usb2_page_cache fs_ctl_start_pc;
- struct usb2_page_cache bulk_start_pc;
- struct usb2_page_cache last_qh_pc;
- struct usb2_page_cache last_td_pc;
-
- struct usb2_page pframes_pg;
- struct usb2_page isoc_start_pg[UHCI_VFRAMELIST_COUNT];
- struct usb2_page intr_start_pg[UHCI_IFRAMELIST_COUNT];
- struct usb2_page ls_ctl_start_pg;
- struct usb2_page fs_ctl_start_pg;
- struct usb2_page bulk_start_pg;
- struct usb2_page last_qh_pg;
- struct usb2_page last_td_pg;
-};
-
-typedef struct uhci_softc {
- struct uhci_hw_softc sc_hw;
- struct usb2_bus sc_bus; /* base device */
- union uhci_hub_desc sc_hub_desc;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
-
- struct usb2_device *sc_devices[UHCI_MAX_DEVICES];
- struct uhci_td *sc_isoc_p_last[UHCI_VFRAMELIST_COUNT]; /* pointer to last TD
- * for isochronous */
- struct uhci_qh *sc_intr_p_last[UHCI_IFRAMELIST_COUNT]; /* pointer to last QH
- * for interrupt */
- struct uhci_qh *sc_ls_ctl_p_last; /* pointer to last QH for low
- * speed control */
- struct uhci_qh *sc_fs_ctl_p_last; /* pointer to last QH for full
- * speed control */
- struct uhci_qh *sc_bulk_p_last; /* pointer to last QH for bulk */
- struct uhci_qh *sc_reclaim_qh_p;
- struct uhci_qh *sc_last_qh_p;
- struct uhci_td *sc_last_td_p;
- struct resource *sc_io_res;
- struct resource *sc_irq_res;
- void *sc_intr_hdl;
- device_t sc_dev;
- bus_size_t sc_io_size;
- bus_space_tag_t sc_io_tag;
- bus_space_handle_t sc_io_hdl;
-
- uint32_t sc_loops; /* number of QHs that wants looping */
-
- uint16_t sc_intr_stat[UHCI_IFRAMELIST_COUNT];
- uint16_t sc_saved_frnum;
-
- uint8_t sc_addr; /* device address */
- uint8_t sc_conf; /* device configuration */
- uint8_t sc_isreset; /* bits set if a root hub is reset */
- uint8_t sc_isresumed; /* bits set if a port was resumed */
- uint8_t sc_saved_sof;
- uint8_t sc_hub_idata[1];
-
- char sc_vendor[16]; /* vendor string for root hub */
-} uhci_softc_t;
-
-usb2_bus_mem_cb_t uhci_iterate_hw_softc;
-
-usb2_error_t uhci_init(uhci_softc_t *sc);
-void uhci_suspend(uhci_softc_t *sc);
-void uhci_resume(uhci_softc_t *sc);
-void uhci_reset(uhci_softc_t *sc);
-void uhci_interrupt(uhci_softc_t *sc);
-
-#endif /* _UHCI_H_ */
diff --git a/sys/dev/usb2/controller/uhci2_pci.c b/sys/dev/usb2/controller/uhci2_pci.c
deleted file mode 100644
index 725cd84..0000000
--- a/sys/dev/usb2/controller/uhci2_pci.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (augustss@carlstedt.se) at
- * Carlstedt Research & Technology.
- *
- * 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.
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``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 FOUNDATION OR CONTRIBUTORS
- * 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$");
-
-/* Universal Host Controller Interface
- *
- * UHCI spec: http://www.intel.com/
- */
-
-/* The low level controller code for UHCI has been split into
- * PCI probes and UHCI specific code. This was done to facilitate the
- * sharing of code between *BSD's
- */
-
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-#include <dev/usb2/core/usb2_debug.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/usb2_pci.h>
-#include <dev/usb2/controller/uhci2.h>
-
-#define PCI_UHCI_VENDORID_INTEL 0x8086
-#define PCI_UHCI_VENDORID_VIA 0x1106
-
-/* PIIX4E has no separate stepping */
-
-#define PCI_UHCI_BASE_REG 0x20
-
-static device_probe_t uhci_pci_probe;
-static device_attach_t uhci_pci_attach;
-static device_detach_t uhci_pci_detach;
-static device_suspend_t uhci_pci_suspend;
-static device_resume_t uhci_pci_resume;
-
-static int
-uhci_pci_suspend(device_t self)
-{
- uhci_softc_t *sc = device_get_softc(self);
- int err;
-
- err = bus_generic_suspend(self);
- if (err) {
- return (err);
- }
- uhci_suspend(sc);
- return (0);
-}
-
-static int
-uhci_pci_resume(device_t self)
-{
- uhci_softc_t *sc = device_get_softc(self);
-
- pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2);
-
- uhci_resume(sc);
-
- bus_generic_resume(self);
- return (0);
-}
-
-static const char *
-uhci_pci_match(device_t self)
-{
- uint32_t device_id = pci_get_devid(self);
-
- switch (device_id) {
- case 0x26888086:
- return ("Intel 631XESB/632XESB/3100 USB controller USB-1");
-
- case 0x26898086:
- return ("Intel 631XESB/632XESB/3100 USB controller USB-2");
-
- case 0x268a8086:
- return ("Intel 631XESB/632XESB/3100 USB controller USB-3");
-
- case 0x268b8086:
- return ("Intel 631XESB/632XESB/3100 USB controller USB-4");
-
- case 0x70208086:
- return ("Intel 82371SB (PIIX3) USB controller");
-
- case 0x71128086:
- return ("Intel 82371AB/EB (PIIX4) USB controller");
-
- case 0x24128086:
- return ("Intel 82801AA (ICH) USB controller");
-
- case 0x24228086:
- return ("Intel 82801AB (ICH0) USB controller");
-
- case 0x24428086:
- return ("Intel 82801BA/BAM (ICH2) USB controller USB-A");
-
- case 0x24448086:
- return ("Intel 82801BA/BAM (ICH2) USB controller USB-B");
-
- case 0x24828086:
- return ("Intel 82801CA/CAM (ICH3) USB controller USB-A");
-
- case 0x24848086:
- return ("Intel 82801CA/CAM (ICH3) USB controller USB-B");
-
- case 0x24878086:
- return ("Intel 82801CA/CAM (ICH3) USB controller USB-C");
-
- case 0x24c28086:
- return ("Intel 82801DB (ICH4) USB controller USB-A");
-
- case 0x24c48086:
- return ("Intel 82801DB (ICH4) USB controller USB-B");
-
- case 0x24c78086:
- return ("Intel 82801DB (ICH4) USB controller USB-C");
-
- case 0x24d28086:
- return ("Intel 82801EB (ICH5) USB controller USB-A");
-
- case 0x24d48086:
- return ("Intel 82801EB (ICH5) USB controller USB-B");
-
- case 0x24d78086:
- return ("Intel 82801EB (ICH5) USB controller USB-C");
-
- case 0x24de8086:
- return ("Intel 82801EB (ICH5) USB controller USB-D");
-
- case 0x26588086:
- return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-A");
-
- case 0x26598086:
- return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-B");
-
- case 0x265a8086:
- return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-C");
-
- case 0x265b8086:
- return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-D");
-
- case 0x28308086:
- return ("Intel 82801H (ICH8) USB controller USB-A");
- case 0x28318086:
- return ("Intel 82801H (ICH8) USB controller USB-B");
- case 0x28328086:
- return ("Intel 82801H (ICH8) USB controller USB-C");
- case 0x28348086:
- return ("Intel 82801H (ICH8) USB controller USB-D");
- case 0x28358086:
- return ("Intel 82801H (ICH8) USB controller USB-E");
- case 0x29348086:
- return ("Intel 82801I (ICH9) USB controller");
- case 0x29358086:
- return ("Intel 82801I (ICH9) USB controller");
- case 0x29368086:
- return ("Intel 82801I (ICH9) USB controller");
- case 0x29378086:
- return ("Intel 82801I (ICH9) USB controller");
- case 0x29388086:
- return ("Intel 82801I (ICH9) USB controller");
- case 0x29398086:
- return ("Intel 82801I (ICH9) USB controller");
-
- case 0x719a8086:
- return ("Intel 82443MX USB controller");
-
- case 0x76028086:
- return ("Intel 82372FB/82468GX USB controller");
-
- case 0x30381106:
- return ("VIA 83C572 USB controller");
-
- default:
- break;
- }
-
- if ((pci_get_class(self) == PCIC_SERIALBUS) &&
- (pci_get_subclass(self) == PCIS_SERIALBUS_USB) &&
- (pci_get_progif(self) == PCI_INTERFACE_UHCI)) {
- return ("UHCI (generic) USB controller");
- }
- return (NULL);
-}
-
-static int
-uhci_pci_probe(device_t self)
-{
- const char *desc = uhci_pci_match(self);
-
- if (desc) {
- device_set_desc(self, desc);
- return (0);
- } else {
- return (ENXIO);
- }
-}
-
-static int
-uhci_pci_attach(device_t self)
-{
- uhci_softc_t *sc = device_get_softc(self);
- int rid;
- int err;
-
- /* initialise some bus fields */
- sc->sc_bus.parent = self;
- sc->sc_bus.devices = sc->sc_devices;
- sc->sc_bus.devices_max = UHCI_MAX_DEVICES;
-
- /* get all DMA memory */
- if (usb2_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
- &uhci_iterate_hw_softc)) {
- return ENOMEM;
- }
- sc->sc_dev = self;
-
- pci_enable_busmaster(self);
-
- rid = PCI_UHCI_BASE_REG;
- sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_IOPORT, &rid,
- RF_ACTIVE);
- if (!sc->sc_io_res) {
- device_printf(self, "Could not map ports\n");
- goto error;
- }
- sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
- sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
- sc->sc_io_size = rman_get_size(sc->sc_io_res);
-
- /* disable interrupts */
- bus_space_write_2(sc->sc_io_tag, sc->sc_io_hdl, UHCI_INTR, 0);
-
- rid = 0;
- sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (sc->sc_irq_res == NULL) {
- device_printf(self, "Could not allocate irq\n");
- goto error;
- }
- sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
- if (!sc->sc_bus.bdev) {
- device_printf(self, "Could not add USB device\n");
- goto error;
- }
- device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
-
- /*
- * uhci_pci_match must never return NULL if uhci_pci_probe
- * succeeded
- */
- device_set_desc(sc->sc_bus.bdev, uhci_pci_match(self));
- switch (pci_get_vendor(self)) {
- case PCI_UHCI_VENDORID_INTEL:
- sprintf(sc->sc_vendor, "Intel");
- break;
- case PCI_UHCI_VENDORID_VIA:
- sprintf(sc->sc_vendor, "VIA");
- break;
- default:
- if (bootverbose) {
- device_printf(self, "(New UHCI DeviceId=0x%08x)\n",
- pci_get_devid(self));
- }
- sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
- }
-
- switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USB_REV_MASK) {
- case PCI_USB_REV_PRE_1_0:
- sc->sc_bus.usbrev = USB_REV_PRE_1_0;
- break;
- case PCI_USB_REV_1_0:
- sc->sc_bus.usbrev = USB_REV_1_0;
- break;
- default:
- /* Quirk for Parallels Desktop 4.0 */
- device_printf(self, "USB revision is unknown. Assuming v1.1.\n");
- sc->sc_bus.usbrev = USB_REV_1_1;
- break;
- }
-
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)uhci_interrupt, sc, &sc->sc_intr_hdl);
-#else
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)(void *)uhci_interrupt, sc, &sc->sc_intr_hdl);
-#endif
-
- if (err) {
- device_printf(self, "Could not setup irq, %d\n", err);
- sc->sc_intr_hdl = NULL;
- goto error;
- }
- /*
- * Set the PIRQD enable bit and switch off all the others. We don't
- * want legacy support to interfere with us XXX Does this also mean
- * that the BIOS won't touch the keyboard anymore if it is connected
- * to the ports of the root hub?
- */
-#if USB_DEBUG
- if (pci_read_config(self, PCI_LEGSUP, 2) != PCI_LEGSUP_USBPIRQDEN) {
- device_printf(self, "LegSup = 0x%04x\n",
- pci_read_config(self, PCI_LEGSUP, 2));
- }
-#endif
- pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2);
-
- err = uhci_init(sc);
- if (!err) {
- err = device_probe_and_attach(sc->sc_bus.bdev);
- }
- if (err) {
- device_printf(self, "USB init failed\n");
- goto error;
- }
- return (0);
-
-error:
- uhci_pci_detach(self);
- return (ENXIO);
-}
-
-int
-uhci_pci_detach(device_t self)
-{
- uhci_softc_t *sc = device_get_softc(self);
- device_t bdev;
-
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(self);
-
- /*
- * disable interrupts that might have been switched on in
- * uhci_init.
- */
- if (sc->sc_io_res) {
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* stop the controller */
- uhci_reset(sc);
-
- USB_BUS_UNLOCK(&sc->sc_bus);
- }
- pci_disable_busmaster(self);
-
- if (sc->sc_irq_res && sc->sc_intr_hdl) {
- int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
-
- if (err) {
- /* XXX or should we panic? */
- device_printf(self, "Could not tear down irq, %d\n",
- err);
- }
- sc->sc_intr_hdl = NULL;
- }
- if (sc->sc_irq_res) {
- bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
- sc->sc_irq_res = NULL;
- }
- if (sc->sc_io_res) {
- bus_release_resource(self, SYS_RES_IOPORT, PCI_UHCI_BASE_REG,
- sc->sc_io_res);
- sc->sc_io_res = NULL;
- }
- usb2_bus_mem_free_all(&sc->sc_bus, &uhci_iterate_hw_softc);
-
- return (0);
-}
-
-static driver_t uhci_driver =
-{
- .name = "uhci",
- .methods = (device_method_t[]){
- /* device interface */
- DEVMETHOD(device_probe, uhci_pci_probe),
- DEVMETHOD(device_attach, uhci_pci_attach),
- DEVMETHOD(device_detach, uhci_pci_detach),
-
- DEVMETHOD(device_suspend, uhci_pci_suspend),
- DEVMETHOD(device_resume, uhci_pci_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- {0, 0}
- },
- .size = sizeof(struct uhci_softc),
-};
-
-static devclass_t uhci_devclass;
-
-DRIVER_MODULE(uhci, pci, uhci_driver, uhci_devclass, 0, 0);
-DRIVER_MODULE(uhci, cardbus, uhci_driver, uhci_devclass, 0, 0);
-MODULE_DEPEND(uhci, usb2_controller, 1, 1, 1);
-MODULE_DEPEND(uhci, usb2_core, 1, 1, 1);
diff --git a/sys/dev/usb2/controller/usb2_bus.h b/sys/dev/usb2/controller/usb2_bus.h
deleted file mode 100644
index 59287c4..0000000
--- a/sys/dev/usb2/controller/usb2_bus.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-#ifndef _USB2_BUS_H_
-#define _USB2_BUS_H_
-
-/*
- * The following structure defines the USB explore message sent to the
- * USB explore process.
- */
-
-struct usb2_bus_msg {
- struct usb2_proc_msg hdr;
- struct usb2_bus *bus;
-};
-
-/*
- * The following structure defines the USB statistics structure.
- */
-struct usb2_bus_stat {
- uint32_t uds_requests[4];
-};
-
-/*
- * The following structure defines an USB BUS. There is one USB BUS
- * for every Host or Device controller.
- */
-struct usb2_bus {
- struct usb2_bus_stat stats_err;
- struct usb2_bus_stat stats_ok;
- struct usb2_process explore_proc;
- struct usb2_process roothub_proc;
- struct root_hold_token *bus_roothold;
- /*
- * There are two callback processes. One for Giant locked
- * callbacks. One for non-Giant locked callbacks. This should
- * avoid congestion and reduce response time in most cases.
- */
- struct usb2_process giant_callback_proc;
- struct usb2_process non_giant_callback_proc;
- struct usb2_bus_msg explore_msg[2];
- struct usb2_bus_msg detach_msg[2];
- struct usb2_bus_msg attach_msg[2];
- struct usb2_bus_msg roothub_msg[2];
- /*
- * This mutex protects the USB hardware:
- */
- struct mtx bus_mtx;
- struct usb2_perm perm;
- struct usb2_xfer_queue intr_q;
- struct usb2_callout power_wdog; /* power management */
-
- device_t parent;
- device_t bdev; /* filled by HC driver */
-
- struct usb2_dma_parent_tag dma_parent_tag[1];
- struct usb2_dma_tag dma_tags[USB_BUS_DMA_TAG_MAX];
-
- struct usb2_bus_methods *methods; /* filled by HC driver */
- struct usb2_device **devices;
-
- uint32_t hw_power_state; /* see USB_HW_POWER_XXX */
- uint32_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
- uint32_t transfer_count[4];
- uint16_t isoc_time_last; /* in milliseconds */
-
- uint8_t alloc_failed; /* Set if memory allocation failed. */
- uint8_t driver_added_refcount; /* Current driver generation count */
- uint8_t usbrev; /* USB revision. See "USB_REV_XXX". */
-
- uint8_t devices_max; /* maximum number of USB devices */
- uint8_t do_probe; /* set if USB BUS should be re-probed */
-
- union {
- struct usb2_hw_ep_scratch hw_ep_scratch[1];
- struct usb2_temp_setup temp_setup[1];
- uint8_t data[128];
- } scratch[1];
-};
-
-#endif /* _USB2_BUS_H_ */
diff --git a/sys/dev/usb2/controller/usb2_controller.c b/sys/dev/usb2/controller/usb2_controller.c
deleted file mode 100644
index cd334ab..0000000
--- a/sys/dev/usb2/controller/usb2_controller.c
+++ /dev/null
@@ -1,623 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#define USB_DEBUG_VAR usb2_ctrl_debug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_dynamic.h>
-#include <dev/usb2/core/usb2_device.h>
-#include <dev/usb2/core/usb2_hub.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-
-/* function prototypes */
-
-static device_probe_t usb2_probe;
-static device_attach_t usb2_attach;
-static device_detach_t usb2_detach;
-
-static void usb2_attach_sub(device_t, struct usb2_bus *);
-static void usb2_post_init(void *);
-static void usb2_bus_mem_flush_all_cb(struct usb2_bus *,
- struct usb2_page_cache *, struct usb2_page *, uint32_t,
- uint32_t);
-static void usb2_bus_mem_alloc_all_cb(struct usb2_bus *,
- struct usb2_page_cache *, struct usb2_page *, uint32_t,
- uint32_t);
-static void usb2_bus_mem_free_all_cb(struct usb2_bus *,
- struct usb2_page_cache *, struct usb2_page *, uint32_t,
- uint32_t);
-static void usb2_bus_roothub(struct usb2_proc_msg *pm);
-
-/* static variables */
-
-#if USB_DEBUG
-static int usb2_ctrl_debug = 0;
-
-SYSCTL_NODE(_hw_usb2, OID_AUTO, ctrl, CTLFLAG_RW, 0, "USB controller");
-SYSCTL_INT(_hw_usb2_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb2_ctrl_debug, 0,
- "Debug level");
-#endif
-
-static uint8_t usb2_post_init_called = 0;
-
-static devclass_t usb2_devclass;
-
-static device_method_t usb2_methods[] = {
- DEVMETHOD(device_probe, usb2_probe),
- DEVMETHOD(device_attach, usb2_attach),
- DEVMETHOD(device_detach, usb2_detach),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- {0, 0}
-};
-
-static driver_t usb2_driver = {
- .name = "usbus",
- .methods = usb2_methods,
- .size = 0,
-};
-
-DRIVER_MODULE(usbus, ohci, usb2_driver, usb2_devclass, 0, 0);
-DRIVER_MODULE(usbus, uhci, usb2_driver, usb2_devclass, 0, 0);
-DRIVER_MODULE(usbus, ehci, usb2_driver, usb2_devclass, 0, 0);
-DRIVER_MODULE(usbus, at91_udp, usb2_driver, usb2_devclass, 0, 0);
-DRIVER_MODULE(usbus, uss820, usb2_driver, usb2_devclass, 0, 0);
-
-MODULE_DEPEND(usb2_controller, usb2_core, 1, 1, 1);
-MODULE_VERSION(usb2_controller, 1);
-
-/*------------------------------------------------------------------------*
- * usb2_probe
- *
- * This function is called from "{ehci,ohci,uhci}_pci_attach()".
- *------------------------------------------------------------------------*/
-static int
-usb2_probe(device_t dev)
-{
- DPRINTF("\n");
- return (0);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_attach
- *------------------------------------------------------------------------*/
-static int
-usb2_attach(device_t dev)
-{
- struct usb2_bus *bus = device_get_ivars(dev);
-
- DPRINTF("\n");
-
- if (bus == NULL) {
- DPRINTFN(0, "USB device has no ivars\n");
- return (ENXIO);
- }
-
- /* delay vfs_mountroot until the bus is explored */
- bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
-
- if (usb2_post_init_called) {
- mtx_lock(&Giant);
- usb2_attach_sub(dev, bus);
- mtx_unlock(&Giant);
- usb2_needs_explore(bus, 1);
- }
- return (0); /* return success */
-}
-
-/*------------------------------------------------------------------------*
- * usb2_detach
- *------------------------------------------------------------------------*/
-static int
-usb2_detach(device_t dev)
-{
- struct usb2_bus *bus = device_get_softc(dev);
-
- DPRINTF("\n");
-
- if (bus == NULL) {
- /* was never setup properly */
- return (0);
- }
- /* Stop power watchdog */
- usb2_callout_drain(&bus->power_wdog);
-
- /* Let the USB explore process detach all devices. */
- if (bus->bus_roothold != NULL) {
- root_mount_rel(bus->bus_roothold);
- bus->bus_roothold = NULL;
- }
-
- USB_BUS_LOCK(bus);
- if (usb2_proc_msignal(&bus->explore_proc,
- &bus->detach_msg[0], &bus->detach_msg[1])) {
- /* ignore */
- }
- /* Wait for detach to complete */
-
- usb2_proc_mwait(&bus->explore_proc,
- &bus->detach_msg[0], &bus->detach_msg[1]);
-
- USB_BUS_UNLOCK(bus);
-
- /* Get rid of USB callback processes */
-
- usb2_proc_free(&bus->giant_callback_proc);
- usb2_proc_free(&bus->non_giant_callback_proc);
-
- /* Get rid of USB roothub process */
-
- usb2_proc_free(&bus->roothub_proc);
-
- /* Get rid of USB explore process */
-
- usb2_proc_free(&bus->explore_proc);
-
- return (0);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_explore
- *
- * This function is used to explore the device tree from the root.
- *------------------------------------------------------------------------*/
-static void
-usb2_bus_explore(struct usb2_proc_msg *pm)
-{
- struct usb2_bus *bus;
- struct usb2_device *udev;
-
- bus = ((struct usb2_bus_msg *)pm)->bus;
- udev = bus->devices[USB_ROOT_HUB_ADDR];
-
- if (udev && udev->hub) {
-
- if (bus->do_probe) {
- bus->do_probe = 0;
- bus->driver_added_refcount++;
- }
- if (bus->driver_added_refcount == 0) {
- /* avoid zero, hence that is memory default */
- bus->driver_added_refcount = 1;
- }
- USB_BUS_UNLOCK(bus);
-
- mtx_lock(&Giant);
-
- /*
- * First update the USB power state!
- */
- usb2_bus_powerd(bus);
-
- /*
- * Explore the Root USB HUB. This call can sleep,
- * exiting Giant, which is actually Giant.
- */
- (udev->hub->explore) (udev);
-
- mtx_unlock(&Giant);
-
- USB_BUS_LOCK(bus);
- }
- if (bus->bus_roothold != NULL) {
- root_mount_rel(bus->bus_roothold);
- bus->bus_roothold = NULL;
- }
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_detach
- *
- * This function is used to detach the device tree from the root.
- *------------------------------------------------------------------------*/
-static void
-usb2_bus_detach(struct usb2_proc_msg *pm)
-{
- struct usb2_bus *bus;
- struct usb2_device *udev;
- device_t dev;
-
- bus = ((struct usb2_bus_msg *)pm)->bus;
- udev = bus->devices[USB_ROOT_HUB_ADDR];
- dev = bus->bdev;
- /* clear the softc */
- device_set_softc(dev, NULL);
- USB_BUS_UNLOCK(bus);
-
- mtx_lock(&Giant);
-
- /* detach children first */
- bus_generic_detach(dev);
-
- /*
- * Free USB Root device, but not any sub-devices, hence they
- * are freed by the caller of this function:
- */
- usb2_detach_device(udev, USB_IFACE_INDEX_ANY, 0);
- usb2_free_device(udev);
-
- mtx_unlock(&Giant);
- USB_BUS_LOCK(bus);
- /* clear bdev variable last */
- bus->bdev = NULL;
-}
-
-static void
-usb2_power_wdog(void *arg)
-{
- struct usb2_bus *bus = arg;
-
- USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
-
- usb2_callout_reset(&bus->power_wdog,
- 4 * hz, usb2_power_wdog, arg);
-
- USB_BUS_UNLOCK(bus);
-
- usb2_bus_power_update(bus);
-
- return;
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_attach
- *
- * This function attaches USB in context of the explore thread.
- *------------------------------------------------------------------------*/
-static void
-usb2_bus_attach(struct usb2_proc_msg *pm)
-{
- struct usb2_bus *bus;
- struct usb2_device *child;
- device_t dev;
- usb2_error_t err;
- uint8_t speed;
-
- bus = ((struct usb2_bus_msg *)pm)->bus;
- dev = bus->bdev;
-
- DPRINTF("\n");
-
- switch (bus->usbrev) {
- case USB_REV_1_0:
- speed = USB_SPEED_FULL;
- device_printf(bus->bdev, "12Mbps Full Speed USB v1.0\n");
- break;
-
- case USB_REV_1_1:
- speed = USB_SPEED_FULL;
- device_printf(bus->bdev, "12Mbps Full Speed USB v1.1\n");
- break;
-
- case USB_REV_2_0:
- speed = USB_SPEED_HIGH;
- device_printf(bus->bdev, "480Mbps High Speed USB v2.0\n");
- break;
-
- case USB_REV_2_5:
- speed = USB_SPEED_VARIABLE;
- device_printf(bus->bdev, "480Mbps Wireless USB v2.5\n");
- break;
-
- default:
- device_printf(bus->bdev, "Unsupported USB revision!\n");
- return;
- }
-
- USB_BUS_UNLOCK(bus);
- mtx_lock(&Giant); /* XXX not required by USB */
-
- /* Allocate the Root USB device */
-
- child = usb2_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
- speed, USB_MODE_HOST);
- if (child) {
- err = usb2_probe_and_attach(child,
- USB_IFACE_INDEX_ANY);
- if (!err) {
- if (!bus->devices[USB_ROOT_HUB_ADDR]->hub) {
- err = USB_ERR_NO_ROOT_HUB;
- }
- }
- } else {
- err = USB_ERR_NOMEM;
- }
-
- mtx_unlock(&Giant);
- USB_BUS_LOCK(bus);
-
- if (err) {
- device_printf(bus->bdev, "Root HUB problem, error=%s\n",
- usb2_errstr(err));
- }
-
- /* set softc - we are ready */
- device_set_softc(dev, bus);
-
- /* start watchdog - this function will unlock the BUS lock ! */
- usb2_power_wdog(bus);
-
- /* need to return locked */
- USB_BUS_LOCK(bus);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_attach_sub
- *
- * This function creates a thread which runs the USB attach code. It
- * is factored out, hence it can be called at two different places in
- * time. During bootup this function is called from
- * "usb2_post_init". During hot-plug it is called directly from the
- * "usb2_attach()" method.
- *------------------------------------------------------------------------*/
-static void
-usb2_attach_sub(device_t dev, struct usb2_bus *bus)
-{
- const char *pname = device_get_nameunit(dev);
-
- /* Initialise USB process messages */
- bus->explore_msg[0].hdr.pm_callback = &usb2_bus_explore;
- bus->explore_msg[0].bus = bus;
- bus->explore_msg[1].hdr.pm_callback = &usb2_bus_explore;
- bus->explore_msg[1].bus = bus;
-
- bus->detach_msg[0].hdr.pm_callback = &usb2_bus_detach;
- bus->detach_msg[0].bus = bus;
- bus->detach_msg[1].hdr.pm_callback = &usb2_bus_detach;
- bus->detach_msg[1].bus = bus;
-
- bus->attach_msg[0].hdr.pm_callback = &usb2_bus_attach;
- bus->attach_msg[0].bus = bus;
- bus->attach_msg[1].hdr.pm_callback = &usb2_bus_attach;
- bus->attach_msg[1].bus = bus;
-
- bus->roothub_msg[0].hdr.pm_callback = &usb2_bus_roothub;
- bus->roothub_msg[0].bus = bus;
- bus->roothub_msg[1].hdr.pm_callback = &usb2_bus_roothub;
- bus->roothub_msg[1].bus = bus;
-
- /* Create USB explore, roothub and callback processes */
-
- if (usb2_proc_create(&bus->giant_callback_proc,
- &bus->bus_mtx, pname, USB_PRI_MED)) {
- printf("WARNING: Creation of USB Giant "
- "callback process failed.\n");
- } else if (usb2_proc_create(&bus->non_giant_callback_proc,
- &bus->bus_mtx, pname, USB_PRI_HIGH)) {
- printf("WARNING: Creation of USB non-Giant "
- "callback process failed.\n");
- } else if (usb2_proc_create(&bus->roothub_proc,
- &bus->bus_mtx, pname, USB_PRI_HIGH)) {
- printf("WARNING: Creation of USB roothub "
- "process failed.\n");
- } else if (usb2_proc_create(&bus->explore_proc,
- &bus->bus_mtx, pname, USB_PRI_MED)) {
- printf("WARNING: Creation of USB explore "
- "process failed.\n");
- } else {
- /* Get final attach going */
- USB_BUS_LOCK(bus);
- if (usb2_proc_msignal(&bus->explore_proc,
- &bus->attach_msg[0], &bus->attach_msg[1])) {
- /* ignore */
- }
- USB_BUS_UNLOCK(bus);
- }
-}
-
-/*------------------------------------------------------------------------*
- * usb2_post_init
- *
- * This function is called to attach all USB busses that were found
- * during bootup.
- *------------------------------------------------------------------------*/
-static void
-usb2_post_init(void *arg)
-{
- struct usb2_bus *bus;
- devclass_t dc;
- device_t dev;
- int max;
- int n;
-
- mtx_lock(&Giant);
-
- usb2_devclass_ptr = devclass_find("usbus");
-
- dc = usb2_devclass_ptr;
- if (dc) {
- max = devclass_get_maxunit(dc) + 1;
- for (n = 0; n != max; n++) {
- dev = devclass_get_device(dc, n);
- if (dev && device_is_attached(dev)) {
- bus = device_get_ivars(dev);
- if (bus) {
- mtx_lock(&Giant);
- usb2_attach_sub(dev, bus);
- mtx_unlock(&Giant);
- }
- }
- }
- } else {
- DPRINTFN(0, "no devclass\n");
- }
- usb2_post_init_called = 1;
-
- /* explore all USB busses in parallell */
-
- usb2_needs_explore_all();
-
- mtx_unlock(&Giant);
-}
-
-SYSINIT(usb2_post_init, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, usb2_post_init, NULL);
-SYSUNINIT(usb2_bus_unload, SI_SUB_KLD, SI_ORDER_ANY, usb2_bus_unload, NULL);
-
-/*------------------------------------------------------------------------*
- * usb2_bus_mem_flush_all_cb
- *------------------------------------------------------------------------*/
-static void
-usb2_bus_mem_flush_all_cb(struct usb2_bus *bus, struct usb2_page_cache *pc,
- struct usb2_page *pg, uint32_t size, uint32_t align)
-{
- usb2_pc_cpu_flush(pc);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_mem_flush_all - factored out code
- *------------------------------------------------------------------------*/
-void
-usb2_bus_mem_flush_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb)
-{
- if (cb) {
- cb(bus, &usb2_bus_mem_flush_all_cb);
- }
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_mem_alloc_all_cb
- *------------------------------------------------------------------------*/
-static void
-usb2_bus_mem_alloc_all_cb(struct usb2_bus *bus, struct usb2_page_cache *pc,
- struct usb2_page *pg, uint32_t size, uint32_t align)
-{
- /* need to initialize the page cache */
- pc->tag_parent = bus->dma_parent_tag;
-
- if (usb2_pc_alloc_mem(pc, pg, size, align)) {
- bus->alloc_failed = 1;
- }
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_mem_alloc_all - factored out code
- *
- * Returns:
- * 0: Success
- * Else: Failure
- *------------------------------------------------------------------------*/
-uint8_t
-usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat,
- usb2_bus_mem_cb_t *cb)
-{
- bus->alloc_failed = 0;
-
- mtx_init(&bus->bus_mtx, device_get_nameunit(bus->parent),
- NULL, MTX_DEF | MTX_RECURSE);
-
- usb2_callout_init_mtx(&bus->power_wdog,
- &bus->bus_mtx, CALLOUT_RETURNUNLOCKED);
-
- TAILQ_INIT(&bus->intr_q.head);
-
- usb2_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
- dmat, &bus->bus_mtx, NULL, NULL, 32, USB_BUS_DMA_TAG_MAX);
-
- if ((bus->devices_max > USB_MAX_DEVICES) ||
- (bus->devices_max < USB_MIN_DEVICES) ||
- (bus->devices == NULL)) {
- DPRINTFN(0, "Devices field has not been "
- "initialised properly!\n");
- bus->alloc_failed = 1; /* failure */
- }
- if (cb) {
- cb(bus, &usb2_bus_mem_alloc_all_cb);
- }
- if (bus->alloc_failed) {
- usb2_bus_mem_free_all(bus, cb);
- }
- return (bus->alloc_failed);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_mem_free_all_cb
- *------------------------------------------------------------------------*/
-static void
-usb2_bus_mem_free_all_cb(struct usb2_bus *bus, struct usb2_page_cache *pc,
- struct usb2_page *pg, uint32_t size, uint32_t align)
-{
- usb2_pc_free_mem(pc);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_mem_free_all - factored out code
- *------------------------------------------------------------------------*/
-void
-usb2_bus_mem_free_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb)
-{
- if (cb) {
- cb(bus, &usb2_bus_mem_free_all_cb);
- }
- usb2_dma_tag_unsetup(bus->dma_parent_tag);
-
- mtx_destroy(&bus->bus_mtx);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_roothub
- *
- * This function is used to execute roothub control requests on the
- * roothub and is called from the roothub process.
- *------------------------------------------------------------------------*/
-static void
-usb2_bus_roothub(struct usb2_proc_msg *pm)
-{
- struct usb2_bus *bus;
-
- bus = ((struct usb2_bus_msg *)pm)->bus;
-
- USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
-
- (bus->methods->roothub_exec) (bus);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_roothub_exec
- *
- * This function is used to schedule the "roothub_done" bus callback
- * method. The bus lock must be locked when calling this function.
- *------------------------------------------------------------------------*/
-void
-usb2_bus_roothub_exec(struct usb2_bus *bus)
-{
- USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
-
- if (usb2_proc_msignal(&bus->roothub_proc,
- &bus->roothub_msg[0], &bus->roothub_msg[1])) {
- /* ignore */
- }
-}
diff --git a/sys/dev/usb2/controller/usb2_controller.h b/sys/dev/usb2/controller/usb2_controller.h
deleted file mode 100644
index 80633d9..0000000
--- a/sys/dev/usb2/controller/usb2_controller.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-#ifndef _USB2_CONTROLLER_H_
-#define _USB2_CONTROLLER_H_
-
-/* defines */
-
-#define USB_BUS_DMA_TAG_MAX 8
-
-/* structure prototypes */
-
-struct usb2_bus;
-struct usb2_page;
-struct usb2_pipe;
-struct usb2_page_cache;
-struct usb2_setup_params;
-struct usb2_hw_ep_profile;
-struct usb2_fs_isoc_schedule;
-struct usb2_config_descriptor;
-struct usb2_endpoint_descriptor;
-
-/* typedefs */
-
-typedef void (usb2_bus_mem_sub_cb_t)(struct usb2_bus *bus, struct usb2_page_cache *pc, struct usb2_page *pg, uint32_t size, uint32_t align);
-typedef void (usb2_bus_mem_cb_t)(struct usb2_bus *bus, usb2_bus_mem_sub_cb_t *scb);
-
-/*
- * The following structure is used to define all the USB BUS
- * callbacks.
- */
-struct usb2_bus_methods {
-
- /* USB Device and Host mode - Mandatory */
-
- void (*pipe_init) (struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc, struct usb2_pipe *pipe);
- void (*do_poll) (struct usb2_bus *);
- void (*xfer_setup) (struct usb2_setup_params *parm);
- void (*xfer_unsetup) (struct usb2_xfer *xfer);
- void (*get_dma_delay) (struct usb2_bus *, uint32_t *pdelay);
- void (*device_suspend) (struct usb2_device *udev);
- void (*device_resume) (struct usb2_device *udev);
- void (*set_hw_power) (struct usb2_bus *bus);
- /*
- * The following flag is set if one or more control transfers are
- * active:
- */
-#define USB_HW_POWER_CONTROL 0x01
- /*
- * The following flag is set if one or more bulk transfers are
- * active:
- */
-#define USB_HW_POWER_BULK 0x02
- /*
- * The following flag is set if one or more interrupt transfers are
- * active:
- */
-#define USB_HW_POWER_INTERRUPT 0x04
- /*
- * The following flag is set if one or more isochronous transfers
- * are active:
- */
-#define USB_HW_POWER_ISOC 0x08
- /*
- * The following flag is set if one or more non-root-HUB devices
- * are present on the given USB bus:
- */
-#define USB_HW_POWER_NON_ROOT_HUB 0x10
-
- /* USB Device mode only - Mandatory */
-
- void (*get_hw_ep_profile) (struct usb2_device *udev, const struct usb2_hw_ep_profile **ppf, uint8_t ep_addr);
- void (*set_stall) (struct usb2_device *udev, struct usb2_xfer *xfer, struct usb2_pipe *pipe);
- void (*clear_stall) (struct usb2_device *udev, struct usb2_pipe *pipe);
-
- /* USB Device and Host mode - Optional */
-
- void (*roothub_exec) (struct usb2_bus *);
-};
-
-/*
- * The following structure is used to define all the USB pipe
- * callbacks.
- */
-struct usb2_pipe_methods {
-
- /* Mandatory USB Device and Host mode callbacks: */
-
- void (*open) (struct usb2_xfer *xfer);
- void (*close) (struct usb2_xfer *xfer);
-
- void (*enter) (struct usb2_xfer *xfer);
- void (*start) (struct usb2_xfer *xfer);
-
- /* Optional */
-
- void *info;
-
- /* Flags */
-
- uint8_t enter_is_cancelable:1;
- uint8_t start_is_cancelable:1;
-};
-
-/*
- * The following structure keeps information about what a hardware USB
- * endpoint supports.
- */
-struct usb2_hw_ep_profile {
- uint16_t max_in_frame_size; /* IN-token direction */
- uint16_t max_out_frame_size; /* OUT-token direction */
- uint8_t is_simplex:1;
- uint8_t support_multi_buffer:1;
- uint8_t support_bulk:1;
- uint8_t support_control:1;
- uint8_t support_interrupt:1;
- uint8_t support_isochronous:1;
- uint8_t support_in:1; /* IN-token is supported */
- uint8_t support_out:1; /* OUT-token is supported */
-};
-
-/*
- * The following structure is used when trying to allocate hardware
- * endpoints for an USB configuration in USB device side mode.
- */
-struct usb2_hw_ep_scratch_sub {
- const struct usb2_hw_ep_profile *pf;
- uint16_t max_frame_size;
- uint8_t hw_endpoint_out;
- uint8_t hw_endpoint_in;
- uint8_t needs_ep_type;
- uint8_t needs_in:1;
- uint8_t needs_out:1;
-};
-
-/*
- * The following structure is used when trying to allocate hardware
- * endpoints for an USB configuration in USB device side mode.
- */
-struct usb2_hw_ep_scratch {
- struct usb2_hw_ep_scratch_sub ep[USB_EP_MAX];
- struct usb2_hw_ep_scratch_sub *ep_max;
- struct usb2_config_descriptor *cd;
- struct usb2_device *udev;
- struct usb2_bus_methods *methods;
- uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16];
- uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16];
-};
-
-/*
- * The following structure is used when generating USB descriptors
- * from USB templates.
- */
-struct usb2_temp_setup {
- void *buf;
- uint32_t size;
- uint8_t usb2_speed;
- uint8_t self_powered;
- uint8_t bNumEndpoints;
- uint8_t bInterfaceNumber;
- uint8_t bAlternateSetting;
- uint8_t bConfigurationValue;
- usb2_error_t err;
-};
-
-/* prototypes */
-
-void usb2_bus_mem_flush_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb);
-uint8_t usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat, usb2_bus_mem_cb_t *cb);
-void usb2_bus_mem_free_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb);
-void usb2_bus_roothub_exec(struct usb2_bus *bus);
-uint16_t usb2_isoc_time_expand(struct usb2_bus *bus, uint16_t isoc_time_curr);
-uint16_t usb2_fs_isoc_schedule_isoc_time_expand(struct usb2_device *udev, struct usb2_fs_isoc_schedule **pp_start, struct usb2_fs_isoc_schedule **pp_end, uint16_t isoc_time);
-uint8_t usb2_fs_isoc_schedule_alloc(struct usb2_fs_isoc_schedule *fss, uint8_t *pstart, uint16_t len);
-
-#endif /* _USB2_CONTROLLER_H_ */
diff --git a/sys/dev/usb2/controller/usb2_pci.h b/sys/dev/usb2/controller/usb2_pci.h
deleted file mode 100644
index 9297c29..0000000
--- a/sys/dev/usb2/controller/usb2_pci.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 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:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-#ifndef _USB2_PCI_H_
-#define _USB2_PCI_H_
-
-/*
- * We don't want the following files included everywhere, that's why
- * they are in a separate file.
- */
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-
-#include <sys/rman.h>
-
-#endif /* _USB2_PCI_H_ */
diff --git a/sys/dev/usb2/controller/uss820dci.c b/sys/dev/usb2/controller/uss820dci.c
deleted file mode 100644
index 1e034bf..0000000
--- a/sys/dev/usb2/controller/uss820dci.c
+++ /dev/null
@@ -1,2489 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 Hans Petter Selasky <hselasky@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.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-/*
- * This file contains the driver for the USS820 series USB Device
- * Controller
- *
- * NOTE: The datasheet does not document everything!
- */
-
-#include <dev/usb2/include/usb2_standard.h>
-#include <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_revision.h>
-#include <dev/usb2/include/usb2_error.h>
-#include <dev/usb2/include/usb2_defs.h>
-
-#define USB_DEBUG_VAR uss820dcidebug
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_debug.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_transfer.h>
-#include <dev/usb2/core/usb2_device.h>
-#include <dev/usb2/core/usb2_hub.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/uss820dci.h>
-
-#define USS820_DCI_BUS2SC(bus) \
- ((struct uss820dci_softc *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((struct uss820dci_softc *)0)->sc_bus))))
-
-#define USS820_DCI_PC2SC(pc) \
- USS820_DCI_BUS2SC((pc)->tag_parent->info->bus)
-
-#if USB_DEBUG
-static int uss820dcidebug = 0;
-
-SYSCTL_NODE(_hw_usb2, OID_AUTO, uss820dci, CTLFLAG_RW, 0, "USB uss820dci");
-SYSCTL_INT(_hw_usb2_uss820dci, OID_AUTO, debug, CTLFLAG_RW,
- &uss820dcidebug, 0, "uss820dci debug level");
-#endif
-
-#define USS820_DCI_INTR_ENDPT 1
-
-/* prototypes */
-
-struct usb2_bus_methods uss820dci_bus_methods;
-struct usb2_pipe_methods uss820dci_device_bulk_methods;
-struct usb2_pipe_methods uss820dci_device_ctrl_methods;
-struct usb2_pipe_methods uss820dci_device_intr_methods;
-struct usb2_pipe_methods uss820dci_device_isoc_fs_methods;
-struct usb2_pipe_methods uss820dci_root_ctrl_methods;
-struct usb2_pipe_methods uss820dci_root_intr_methods;
-
-static uss820dci_cmd_t uss820dci_setup_rx;
-static uss820dci_cmd_t uss820dci_data_rx;
-static uss820dci_cmd_t uss820dci_data_tx;
-static uss820dci_cmd_t uss820dci_data_tx_sync;
-static void uss820dci_device_done(struct usb2_xfer *, usb2_error_t);
-static void uss820dci_do_poll(struct usb2_bus *);
-static void uss820dci_root_ctrl_poll(struct uss820dci_softc *);
-static void uss820dci_standard_done(struct usb2_xfer *);
-static void uss820dci_intr_set(struct usb2_xfer *, uint8_t);
-static void uss820dci_update_shared_1(struct uss820dci_softc *, uint8_t,
- uint8_t, uint8_t);
-
-static usb2_sw_transfer_func_t uss820dci_root_intr_done;
-static usb2_sw_transfer_func_t uss820dci_root_ctrl_done;
-
-/*
- * Here is a list of what the USS820D chip can support. The main
- * limitation is that the sum of the buffer sizes must be less than
- * 1120 bytes.
- */
-static const struct usb2_hw_ep_profile
- uss820dci_ep_profile[] = {
-
- [0] = {
- .max_in_frame_size = 32,
- .max_out_frame_size = 32,
- .is_simplex = 0,
- .support_control = 1,
- },
- [1] = {
- .max_in_frame_size = 64,
- .max_out_frame_size = 64,
- .is_simplex = 0,
- .support_multi_buffer = 1,
- .support_bulk = 1,
- .support_interrupt = 1,
- .support_in = 1,
- .support_out = 1,
- },
- [2] = {
- .max_in_frame_size = 8,
- .max_out_frame_size = 8,
- .is_simplex = 0,
- .support_multi_buffer = 1,
- .support_bulk = 1,
- .support_interrupt = 1,
- .support_in = 1,
- .support_out = 1,
- },
- [3] = {
- .max_in_frame_size = 256,
- .max_out_frame_size = 256,
- .is_simplex = 0,
- .support_multi_buffer = 1,
- .support_isochronous = 1,
- .support_in = 1,
- .support_out = 1,
- },
-};
-
-static void
-uss820dci_update_shared_1(struct uss820dci_softc *sc, uint8_t reg,
- uint8_t keep_mask, uint8_t set_mask)
-{
- uint8_t temp;
-
- USS820_WRITE_1(sc, USS820_PEND, 1);
- temp = USS820_READ_1(sc, reg);
- temp &= (keep_mask);
- temp |= (set_mask);
- USS820_WRITE_1(sc, reg, temp);
- USS820_WRITE_1(sc, USS820_PEND, 0);
-}
-
-static void
-uss820dci_get_hw_ep_profile(struct usb2_device *udev,
- const struct usb2_hw_ep_profile **ppf, uint8_t ep_addr)
-{
- if (ep_addr == 0) {
- *ppf = uss820dci_ep_profile + 0;
- } else if (ep_addr < 5) {
- *ppf = uss820dci_ep_profile + 1;
- } else if (ep_addr < 7) {
- *ppf = uss820dci_ep_profile + 2;
- } else if (ep_addr == 7) {
- *ppf = uss820dci_ep_profile + 3;
- } else {
- *ppf = NULL;
- }
-}
-
-static void
-uss820dci_pull_up(struct uss820dci_softc *sc)
-{
- uint8_t temp;
-
- /* pullup D+, if possible */
-
- if (!sc->sc_flags.d_pulled_up &&
- sc->sc_flags.port_powered) {
- sc->sc_flags.d_pulled_up = 1;
-
- DPRINTF("\n");
-
- temp = USS820_READ_1(sc, USS820_MCSR);
- temp |= USS820_MCSR_DPEN;
- USS820_WRITE_1(sc, USS820_MCSR, temp);
- }
-}
-
-static void
-uss820dci_pull_down(struct uss820dci_softc *sc)
-{
- uint8_t temp;
-
- /* pulldown D+, if possible */
-
- if (sc->sc_flags.d_pulled_up) {
- sc->sc_flags.d_pulled_up = 0;
-
- DPRINTF("\n");
-
- temp = USS820_READ_1(sc, USS820_MCSR);
- temp &= ~USS820_MCSR_DPEN;
- USS820_WRITE_1(sc, USS820_MCSR, temp);
- }
-}
-
-static void
-uss820dci_wakeup_peer(struct uss820dci_softc *sc)
-{
- if (!(sc->sc_flags.status_suspend)) {
- return;
- }
- DPRINTFN(0, "not supported\n");
-}
-
-static void
-uss820dci_set_address(struct uss820dci_softc *sc, uint8_t addr)
-{
- DPRINTFN(5, "addr=%d\n", addr);
-
- USS820_WRITE_1(sc, USS820_FADDR, addr);
-}
-
-static uint8_t
-uss820dci_setup_rx(struct uss820dci_td *td)
-{
- struct uss820dci_softc *sc;
- struct usb2_device_request req;
- uint16_t count;
- uint8_t rx_stat;
- uint8_t temp;
-
- /* select the correct endpoint */
- bus_space_write_1(td->io_tag, td->io_hdl,
- td->ep_reg, td->ep_index);
-
- /* read out FIFO status */
- rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_stat_reg);
-
- /* get pointer to softc */
- sc = USS820_DCI_PC2SC(td->pc);
-
- DPRINTFN(5, "rx_stat=0x%02x rem=%u\n", rx_stat, td->remainder);
-
- if (!(rx_stat & USS820_RXSTAT_RXSETUP)) {
- /* abort any ongoing transfer */
- if (!td->did_stall) {
- DPRINTFN(5, "stalling\n");
-
- /* set stall */
-
- uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF,
- (USS820_EPCON_TXSTL | USS820_EPCON_RXSTL));
-
- td->did_stall = 1;
- }
- goto not_complete;
- }
- /* clear stall and all I/O */
- uss820dci_update_shared_1(sc, USS820_EPCON,
- 0xFF ^ (USS820_EPCON_TXSTL |
- USS820_EPCON_RXSTL |
- USS820_EPCON_RXIE |
- USS820_EPCON_TXOE), 0);
-
- /* clear end overwrite flag */
- uss820dci_update_shared_1(sc, USS820_RXSTAT,
- 0xFF ^ USS820_RXSTAT_EDOVW, 0);
-
- /* get the packet byte count */
- count = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_count_low_reg);
- count |= (bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_count_high_reg) << 8);
- count &= 0x3FF;
-
- /* verify data length */
- if (count != td->remainder) {
- DPRINTFN(0, "Invalid SETUP packet "
- "length, %d bytes\n", count);
- goto not_complete;
- }
- if (count != sizeof(req)) {
- DPRINTFN(0, "Unsupported SETUP packet "
- "length, %d bytes\n", count);
- goto not_complete;
- }
- /* receive data */
- bus_space_read_multi_1(td->io_tag, td->io_hdl,
- td->rx_fifo_reg, (void *)&req, sizeof(req));
-
- /* read out FIFO status */
- rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_stat_reg);
-
- if (rx_stat & (USS820_RXSTAT_EDOVW |
- USS820_RXSTAT_STOVW)) {
- DPRINTF("new SETUP packet received\n");
- return (1); /* not complete */
- }
- /* clear receive setup bit */
- uss820dci_update_shared_1(sc, USS820_RXSTAT,
- 0xFF ^ (USS820_RXSTAT_RXSETUP |
- USS820_RXSTAT_EDOVW |
- USS820_RXSTAT_STOVW), 0);
-
- /* set RXFFRC bit */
- temp = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_cntl_reg);
- temp |= USS820_RXCON_RXFFRC;
- bus_space_write_1(td->io_tag, td->io_hdl,
- td->rx_cntl_reg, temp);
-
- /* copy data into real buffer */
- usb2_copy_in(td->pc, 0, &req, sizeof(req));
-
- td->offset = sizeof(req);
- td->remainder = 0;
-
- /* sneak peek the set address */
- if ((req.bmRequestType == UT_WRITE_DEVICE) &&
- (req.bRequest == UR_SET_ADDRESS)) {
- sc->sc_dv_addr = req.wValue[0] & 0x7F;
- } else {
- sc->sc_dv_addr = 0xFF;
- }
- return (0); /* complete */
-
-not_complete:
- /* clear end overwrite flag, if any */
- if (rx_stat & USS820_RXSTAT_RXSETUP) {
- uss820dci_update_shared_1(sc, USS820_RXSTAT,
- 0xFF ^ (USS820_RXSTAT_EDOVW |
- USS820_RXSTAT_STOVW |
- USS820_RXSTAT_RXSETUP), 0);
- }
- return (1); /* not complete */
-
-}
-
-static uint8_t
-uss820dci_data_rx(struct uss820dci_td *td)
-{
- struct usb2_page_search buf_res;
- uint16_t count;
- uint8_t rx_flag;
- uint8_t rx_stat;
- uint8_t rx_cntl;
- uint8_t to;
- uint8_t got_short;
-
- to = 2; /* don't loop forever! */
- got_short = 0;
-
- /* select the correct endpoint */
- bus_space_write_1(td->io_tag, td->io_hdl, td->ep_reg, td->ep_index);
-
- /* check if any of the FIFO banks have data */
-repeat:
- /* read out FIFO flag */
- rx_flag = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_flag_reg);
- /* read out FIFO status */
- rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_stat_reg);
-
- DPRINTFN(5, "rx_stat=0x%02x rx_flag=0x%02x rem=%u\n",
- rx_stat, rx_flag, td->remainder);
-
- if (rx_stat & (USS820_RXSTAT_RXSETUP |
- USS820_RXSTAT_RXSOVW |
- USS820_RXSTAT_EDOVW)) {
- if (td->remainder == 0) {
- /*
- * We are actually complete and have
- * received the next SETUP
- */
- DPRINTFN(5, "faking complete\n");
- return (0); /* complete */
- }
- /*
- * USB Host Aborted the transfer.
- */
- td->error = 1;
- return (0); /* complete */
- }
- /* check for errors */
- if (rx_flag & (USS820_RXFLG_RXOVF |
- USS820_RXFLG_RXURF)) {
- DPRINTFN(5, "overflow or underflow\n");
- /* should not happen */
- td->error = 1;
- return (0); /* complete */
- }
- /* check status */
- if (!(rx_flag & (USS820_RXFLG_RXFIF0 |
- USS820_RXFLG_RXFIF1))) {
-
- /* read out EPCON register */
- /* enable RX input */
- if (!td->did_stall) {
- uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc),
- USS820_EPCON, 0xFF, USS820_EPCON_RXIE);
- td->did_stall = 1;
- }
- return (1); /* not complete */
- }
- /* get the packet byte count */
- count = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_count_low_reg);
-
- count |= (bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_count_high_reg) << 8);
- count &= 0x3FF;
-
- DPRINTFN(5, "count=0x%04x\n", count);
-
- /* verify the packet byte count */
- if (count != td->max_packet_size) {
- if (count < td->max_packet_size) {
- /* we have a short packet */
- td->short_pkt = 1;
- got_short = 1;
- } else {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- }
- /* verify the packet byte count */
- if (count > td->remainder) {
- /* invalid USB packet */
- td->error = 1;
- return (0); /* we are complete */
- }
- while (count > 0) {
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* receive data */
- bus_space_read_multi_1(td->io_tag, td->io_hdl,
- td->rx_fifo_reg, buf_res.buffer, buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* set RXFFRC bit */
- rx_cntl = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_cntl_reg);
- rx_cntl |= USS820_RXCON_RXFFRC;
- bus_space_write_1(td->io_tag, td->io_hdl,
- td->rx_cntl_reg, rx_cntl);
-
- /* check if we are complete */
- if ((td->remainder == 0) || got_short) {
- if (td->short_pkt) {
- /* we are complete */
- return (0);
- }
- /* else need to receive a zero length packet */
- }
- if (--to) {
- goto repeat;
- }
- return (1); /* not complete */
-}
-
-static uint8_t
-uss820dci_data_tx(struct uss820dci_td *td)
-{
- struct usb2_page_search buf_res;
- uint16_t count;
- uint16_t count_copy;
- uint8_t rx_stat;
- uint8_t tx_flag;
- uint8_t to;
-
- /* select the correct endpoint */
- bus_space_write_1(td->io_tag, td->io_hdl,
- td->ep_reg, td->ep_index);
-
- to = 2; /* don't loop forever! */
-
-repeat:
- /* read out TX FIFO flags */
- tx_flag = bus_space_read_1(td->io_tag, td->io_hdl,
- td->tx_flag_reg);
-
- /* read out RX FIFO status last */
- rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_stat_reg);
-
- DPRINTFN(5, "rx_stat=0x%02x tx_flag=0x%02x rem=%u\n",
- rx_stat, tx_flag, td->remainder);
-
- if (rx_stat & (USS820_RXSTAT_RXSETUP |
- USS820_RXSTAT_RXSOVW |
- USS820_RXSTAT_EDOVW)) {
- /*
- * The current transfer was aborted
- * by the USB Host
- */
- td->error = 1;
- return (0); /* complete */
- }
- if (tx_flag & (USS820_TXFLG_TXOVF |
- USS820_TXFLG_TXURF)) {
- td->error = 1;
- return (0); /* complete */
- }
- if (tx_flag & USS820_TXFLG_TXFIF0) {
- if (tx_flag & USS820_TXFLG_TXFIF1) {
- return (1); /* not complete */
- }
- }
- if ((!td->support_multi_buffer) &&
- (tx_flag & (USS820_TXFLG_TXFIF0 |
- USS820_TXFLG_TXFIF1))) {
- return (1); /* not complete */
- }
- count = td->max_packet_size;
- if (td->remainder < count) {
- /* we have a short packet */
- td->short_pkt = 1;
- count = td->remainder;
- }
- count_copy = count;
- while (count > 0) {
-
- usb2_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count) {
- buf_res.length = count;
- }
- /* transmit data */
- bus_space_write_multi_1(td->io_tag, td->io_hdl,
- td->tx_fifo_reg, buf_res.buffer, buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
-
- /* post-write high packet byte count first */
- bus_space_write_1(td->io_tag, td->io_hdl,
- td->tx_count_high_reg, count_copy >> 8);
-
- /* post-write low packet byte count last */
- bus_space_write_1(td->io_tag, td->io_hdl,
- td->tx_count_low_reg, count_copy);
-
- /*
- * Enable TX output, which must happen after that we have written
- * data into the FIFO. This is undocumented.
- */
- if (!td->did_stall) {
- uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc),
- USS820_EPCON, 0xFF, USS820_EPCON_TXOE);
- td->did_stall = 1;
- }
- /* check remainder */
- if (td->remainder == 0) {
- if (td->short_pkt) {
- return (0); /* complete */
- }
- /* else we need to transmit a short packet */
- }
- if (--to) {
- goto repeat;
- }
- return (1); /* not complete */
-}
-
-static uint8_t
-uss820dci_data_tx_sync(struct uss820dci_td *td)
-{
- struct uss820dci_softc *sc;
- uint8_t rx_stat;
- uint8_t tx_flag;
-
- /* select the correct endpoint */
- bus_space_write_1(td->io_tag, td->io_hdl,
- td->ep_reg, td->ep_index);
-
- /* read out TX FIFO flag */
- tx_flag = bus_space_read_1(td->io_tag, td->io_hdl,
- td->tx_flag_reg);
-
- /* read out RX FIFO status last */
- rx_stat = bus_space_read_1(td->io_tag, td->io_hdl,
- td->rx_stat_reg);
-
- DPRINTFN(5, "rx_stat=0x%02x rem=%u\n", rx_stat, td->remainder);
-
- if (rx_stat & (USS820_RXSTAT_RXSETUP |
- USS820_RXSTAT_RXSOVW |
- USS820_RXSTAT_EDOVW)) {
- DPRINTFN(5, "faking complete\n");
- /* Race condition */
- return (0); /* complete */
- }
- DPRINTFN(5, "tx_flag=0x%02x rem=%u\n",
- tx_flag, td->remainder);
-
- if (tx_flag & (USS820_TXFLG_TXOVF |
- USS820_TXFLG_TXURF)) {
- td->error = 1;
- return (0); /* complete */
- }
- if (tx_flag & (USS820_TXFLG_TXFIF0 |
- USS820_TXFLG_TXFIF1)) {
- return (1); /* not complete */
- }
- sc = USS820_DCI_PC2SC(td->pc);
- if (sc->sc_dv_addr != 0xFF) {
- /* write function address */
- uss820dci_set_address(sc, sc->sc_dv_addr);
- }
- return (0); /* complete */
-}
-
-static uint8_t
-uss820dci_xfer_do_fifo(struct usb2_xfer *xfer)
-{
- struct uss820dci_td *td;
-
- DPRINTFN(9, "\n");
-
- td = xfer->td_transfer_cache;
- while (1) {
- if ((td->func) (td)) {
- /* operation in progress */
- break;
- }
- if (((void *)td) == xfer->td_transfer_last) {
- goto done;
- }
- if (td->error) {
- goto done;
- } else if (td->remainder > 0) {
- /*
- * We had a short transfer. If there is no alternate
- * next, stop processing !
- */
- if (!td->alt_next) {
- goto done;
- }
- }
- /*
- * Fetch the next transfer descriptor.
- */
- td = td->obj_next;
- xfer->td_transfer_cache = td;
- }
- return (1); /* not complete */
-
-done:
- /* compute all actual lengths */
-
- uss820dci_standard_done(xfer);
-
- return (0); /* complete */
-}
-
-static void
-uss820dci_interrupt_poll(struct uss820dci_softc *sc)
-{
- struct usb2_xfer *xfer;
-
-repeat:
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- if (!uss820dci_xfer_do_fifo(xfer)) {
- /* queue has been modified */
- goto repeat;
- }
- }
-}
-
-static void
-uss820dci_wait_suspend(struct uss820dci_softc *sc, uint8_t on)
-{
- uint8_t scr;
- uint8_t scratch;
-
- scr = USS820_READ_1(sc, USS820_SCR);
- scratch = USS820_READ_1(sc, USS820_SCRATCH);
-
- if (on) {
- scr |= USS820_SCR_IE_SUSP;
- scratch &= ~USS820_SCRATCH_IE_RESUME;
- } else {
- scr &= ~USS820_SCR_IE_SUSP;
- scratch |= USS820_SCRATCH_IE_RESUME;
- }
-
- USS820_WRITE_1(sc, USS820_SCR, scr);
- USS820_WRITE_1(sc, USS820_SCRATCH, scratch);
-}
-
-void
-uss820dci_interrupt(struct uss820dci_softc *sc)
-{
- uint8_t ssr;
- uint8_t event;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- ssr = USS820_READ_1(sc, USS820_SSR);
-
- ssr &= (USS820_SSR_SUSPEND |
- USS820_SSR_RESUME |
- USS820_SSR_RESET);
-
- /* acknowledge all interrupts */
-
- uss820dci_update_shared_1(sc, USS820_SSR, 0, 0);
-
- /* check for any bus state change interrupts */
-
- if (ssr) {
-
- event = 0;
-
- if (ssr & USS820_SSR_RESET) {
- sc->sc_flags.status_bus_reset = 1;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- /* disable resume interrupt */
- uss820dci_wait_suspend(sc, 1);
-
- event = 1;
- }
- /*
- * If "RESUME" and "SUSPEND" is set at the same time
- * we interpret that like "RESUME". Resume is set when
- * there is at least 3 milliseconds of inactivity on
- * the USB BUS.
- */
- if (ssr & USS820_SSR_RESUME) {
- if (sc->sc_flags.status_suspend) {
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 1;
- /* disable resume interrupt */
- uss820dci_wait_suspend(sc, 1);
- event = 1;
- }
- } else if (ssr & USS820_SSR_SUSPEND) {
- if (!sc->sc_flags.status_suspend) {
- sc->sc_flags.status_suspend = 1;
- sc->sc_flags.change_suspend = 1;
- /* enable resume interrupt */
- uss820dci_wait_suspend(sc, 0);
- event = 1;
- }
- }
- if (event) {
-
- DPRINTF("real bus interrupt 0x%02x\n", ssr);
-
- /* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &uss820dci_root_intr_done);
- }
- }
- /* acknowledge all SBI interrupts */
- uss820dci_update_shared_1(sc, USS820_SBI, 0, 0);
-
- /* acknowledge all SBI1 interrupts */
- uss820dci_update_shared_1(sc, USS820_SBI1, 0, 0);
-
- /* poll all active transfers */
- uss820dci_interrupt_poll(sc);
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-static void
-uss820dci_setup_standard_chain_sub(struct uss820_std_temp *temp)
-{
- struct uss820dci_td *td;
-
- /* get current Transfer Descriptor */
- td = temp->td_next;
- temp->td = td;
-
- /* prepare for next TD */
- temp->td_next = td->obj_next;
-
- /* fill out the Transfer Descriptor */
- td->func = temp->func;
- td->pc = temp->pc;
- td->offset = temp->offset;
- td->remainder = temp->len;
- td->error = 0;
- td->did_stall = 0;
- td->short_pkt = temp->short_pkt;
- td->alt_next = temp->setup_alt_next;
-}
-
-static void
-uss820dci_setup_standard_chain(struct usb2_xfer *xfer)
-{
- struct uss820_std_temp temp;
- struct uss820dci_softc *sc;
- struct uss820dci_td *td;
- uint32_t x;
- uint8_t ep_no;
-
- DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
- xfer->address, UE_GET_ADDR(xfer->endpoint),
- xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
-
- temp.max_frame_size = xfer->max_frame_size;
-
- td = xfer->td_start[0];
- xfer->td_transfer_first = td;
- xfer->td_transfer_cache = td;
-
- /* setup temp */
-
- temp.td = NULL;
- temp.td_next = xfer->td_start[0];
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.offset = 0;
-
- sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
- ep_no = (xfer->endpoint & UE_ADDR);
-
- /* check if we should prepend a setup message */
-
- if (xfer->flags_int.control_xfr) {
- if (xfer->flags_int.control_hdr) {
-
- temp.func = &uss820dci_setup_rx;
- temp.len = xfer->frlengths[0];
- temp.pc = xfer->frbuffers + 0;
- temp.short_pkt = temp.len ? 1 : 0;
-
- uss820dci_setup_standard_chain_sub(&temp);
- }
- x = 1;
- } else {
- x = 0;
- }
-
- if (x != xfer->nframes) {
- if (xfer->endpoint & UE_DIR_IN) {
- temp.func = &uss820dci_data_tx;
- } else {
- temp.func = &uss820dci_data_rx;
- }
-
- /* setup "pc" pointer */
- temp.pc = xfer->frbuffers + x;
- }
- while (x != xfer->nframes) {
-
- /* DATA0 / DATA1 message */
-
- temp.len = xfer->frlengths[x];
-
- x++;
-
- if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
- }
- if (temp.len == 0) {
-
- /* make sure that we send an USB packet */
-
- temp.short_pkt = 0;
-
- } else {
-
- /* regular data transfer */
-
- temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1;
- }
-
- uss820dci_setup_standard_chain_sub(&temp);
-
- if (xfer->flags_int.isochronous_xfr) {
- temp.offset += temp.len;
- } else {
- /* get next Page Cache pointer */
- temp.pc = xfer->frbuffers + x;
- }
- }
-
- /* always setup a valid "pc" pointer for status and sync */
- temp.pc = xfer->frbuffers + 0;
-
- /* check if we should append a status stage */
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
- uint8_t need_sync;
-
- /*
- * Send a DATA1 message and invert the current
- * endpoint direction.
- */
- if (xfer->endpoint & UE_DIR_IN) {
- temp.func = &uss820dci_data_rx;
- need_sync = 0;
- } else {
- temp.func = &uss820dci_data_tx;
- need_sync = 1;
- }
- temp.len = 0;
- temp.short_pkt = 0;
-
- uss820dci_setup_standard_chain_sub(&temp);
- if (need_sync) {
- /* we need a SYNC point after TX */
- temp.func = &uss820dci_data_tx_sync;
- temp.len = 0;
- temp.short_pkt = 0;
-
- uss820dci_setup_standard_chain_sub(&temp);
- }
- }
- /* must have at least one frame! */
- td = temp.td;
- xfer->td_transfer_last = td;
-}
-
-static void
-uss820dci_timeout(void *arg)
-{
- struct usb2_xfer *xfer = arg;
-
- DPRINTF("xfer=%p\n", xfer);
-
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- /* transfer is transferred */
- uss820dci_device_done(xfer, USB_ERR_TIMEOUT);
-}
-
-static void
-uss820dci_intr_set(struct usb2_xfer *xfer, uint8_t set)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
- uint8_t ep_no = (xfer->endpoint & UE_ADDR);
- uint8_t ep_reg;
- uint8_t temp;
-
- DPRINTFN(15, "endpoint 0x%02x\n", xfer->endpoint);
-
- if (ep_no > 3) {
- ep_reg = USS820_SBIE1;
- } else {
- ep_reg = USS820_SBIE;
- }
-
- ep_no &= 3;
- ep_no = 1 << (2 * ep_no);
-
- if (xfer->flags_int.control_xfr) {
- if (xfer->flags_int.control_hdr) {
- ep_no <<= 1; /* RX interrupt only */
- } else {
- ep_no |= (ep_no << 1); /* RX and TX interrupt */
- }
- } else {
- if (!(xfer->endpoint & UE_DIR_IN)) {
- ep_no <<= 1;
- }
- }
- temp = USS820_READ_1(sc, ep_reg);
- if (set) {
- temp |= ep_no;
- } else {
- temp &= ~ep_no;
- }
- USS820_WRITE_1(sc, ep_reg, temp);
-}
-
-static void
-uss820dci_start_standard_chain(struct usb2_xfer *xfer)
-{
- DPRINTFN(9, "\n");
-
- /* poll one time */
- if (uss820dci_xfer_do_fifo(xfer)) {
-
- /*
- * Only enable the endpoint interrupt when we are
- * actually waiting for data, hence we are dealing
- * with level triggered interrupts !
- */
- uss820dci_intr_set(xfer, 1);
-
- /* put transfer on interrupt queue */
- usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
-
- /* start timeout, if any */
- if (xfer->timeout != 0) {
- usb2_transfer_timeout_ms(xfer,
- &uss820dci_timeout, xfer->timeout);
- }
- }
-}
-
-static void
-uss820dci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
- DPRINTFN(9, "\n");
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- uss820dci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
- /* set port bit */
- sc->sc_hub_idata[0] = 0x02; /* we only have one port */
-
-done:
- return;
-}
-
-static usb2_error_t
-uss820dci_standard_done_sub(struct usb2_xfer *xfer)
-{
- struct uss820dci_td *td;
- uint32_t len;
- uint8_t error;
-
- DPRINTFN(9, "\n");
-
- td = xfer->td_transfer_cache;
-
- do {
- len = td->remainder;
-
- if (xfer->aframes != xfer->nframes) {
- /*
- * Verify the length and subtract
- * the remainder from "frlengths[]":
- */
- if (len > xfer->frlengths[xfer->aframes]) {
- td->error = 1;
- } else {
- xfer->frlengths[xfer->aframes] -= len;
- }
- }
- /* Check for transfer error */
- if (td->error) {
- /* the transfer is finished */
- error = 1;
- td = NULL;
- break;
- }
- /* Check for short transfer */
- if (len > 0) {
- if (xfer->flags_int.short_frames_ok) {
- /* follow alt next */
- if (td->alt_next) {
- td = td->obj_next;
- } else {
- td = NULL;
- }
- } else {
- /* the transfer is finished */
- td = NULL;
- }
- error = 0;
- break;
- }
- td = td->obj_next;
-
- /* this USB frame is complete */
- error = 0;
- break;
-
- } while (0);
-
- /* update transfer cache */
-
- xfer->td_transfer_cache = td;
-
- return (error ?
- USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION);
-}
-
-static void
-uss820dci_standard_done(struct usb2_xfer *xfer)
-{
- usb2_error_t err = 0;
-
- DPRINTFN(13, "xfer=%p pipe=%p transfer done\n",
- xfer, xfer->pipe);
-
- /* reset scanner */
-
- xfer->td_transfer_cache = xfer->td_transfer_first;
-
- if (xfer->flags_int.control_xfr) {
-
- if (xfer->flags_int.control_hdr) {
-
- err = uss820dci_standard_done_sub(xfer);
- }
- xfer->aframes = 1;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
- while (xfer->aframes != xfer->nframes) {
-
- err = uss820dci_standard_done_sub(xfer);
- xfer->aframes++;
-
- if (xfer->td_transfer_cache == NULL) {
- goto done;
- }
- }
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- err = uss820dci_standard_done_sub(xfer);
- }
-done:
- uss820dci_device_done(xfer, err);
-}
-
-/*------------------------------------------------------------------------*
- * uss820dci_device_done
- *
- * NOTE: this function can be called more than one time on the
- * same USB transfer!
- *------------------------------------------------------------------------*/
-static void
-uss820dci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
-{
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
- xfer, xfer->pipe, error);
-
- if (xfer->flags_int.usb2_mode == USB_MODE_DEVICE) {
- uss820dci_intr_set(xfer, 0);
- }
- /* dequeue transfer and start next transfer */
- usb2_transfer_done(xfer, error);
-}
-
-static void
-uss820dci_set_stall(struct usb2_device *udev, struct usb2_xfer *xfer,
- struct usb2_pipe *pipe)
-{
- struct uss820dci_softc *sc;
- uint8_t ep_no;
- uint8_t ep_type;
- uint8_t ep_dir;
- uint8_t temp;
-
- USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
-
- DPRINTFN(5, "pipe=%p\n", pipe);
-
- if (xfer) {
- /* cancel any ongoing transfers */
- uss820dci_device_done(xfer, USB_ERR_STALLED);
- }
- /* set FORCESTALL */
- sc = USS820_DCI_BUS2SC(udev->bus);
- ep_no = (pipe->edesc->bEndpointAddress & UE_ADDR);
- ep_dir = (pipe->edesc->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT));
- ep_type = (pipe->edesc->bmAttributes & UE_XFERTYPE);
-
- if (ep_type == UE_CONTROL) {
- /* should not happen */
- return;
- }
- USS820_WRITE_1(sc, USS820_EPINDEX, ep_no);
-
- if (ep_dir == UE_DIR_IN) {
- temp = USS820_EPCON_TXSTL;
- } else {
- temp = USS820_EPCON_RXSTL;
- }
- uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF, temp);
-}
-
-static void
-uss820dci_clear_stall_sub(struct uss820dci_softc *sc,
- uint8_t ep_no, uint8_t ep_type, uint8_t ep_dir)
-{
- uint8_t temp;
-
- if (ep_type == UE_CONTROL) {
- /* clearing stall is not needed */
- return;
- }
- /* select endpoint index */
- USS820_WRITE_1(sc, USS820_EPINDEX, ep_no);
-
- /* clear stall and disable I/O transfers */
- if (ep_dir == UE_DIR_IN) {
- temp = 0xFF ^ (USS820_EPCON_TXOE |
- USS820_EPCON_TXSTL);
- } else {
- temp = 0xFF ^ (USS820_EPCON_RXIE |
- USS820_EPCON_RXSTL);
- }
- uss820dci_update_shared_1(sc, USS820_EPCON, temp, 0);
-
- if (ep_dir == UE_DIR_IN) {
- /* reset data toggle */
- USS820_WRITE_1(sc, USS820_TXSTAT,
- USS820_TXSTAT_TXSOVW);
-
- /* reset FIFO */
- temp = USS820_READ_1(sc, USS820_TXCON);
- temp |= USS820_TXCON_TXCLR;
- USS820_WRITE_1(sc, USS820_TXCON, temp);
- temp &= ~USS820_TXCON_TXCLR;
- USS820_WRITE_1(sc, USS820_TXCON, temp);
- } else {
-
- /* reset data toggle */
- uss820dci_update_shared_1(sc, USS820_RXSTAT,
- 0, USS820_RXSTAT_RXSOVW);
-
- /* reset FIFO */
- temp = USS820_READ_1(sc, USS820_RXCON);
- temp |= USS820_RXCON_RXCLR;
- temp &= ~USS820_RXCON_RXFFRC;
- USS820_WRITE_1(sc, USS820_RXCON, temp);
- temp &= ~USS820_RXCON_RXCLR;
- USS820_WRITE_1(sc, USS820_RXCON, temp);
- }
-}
-
-static void
-uss820dci_clear_stall(struct usb2_device *udev, struct usb2_pipe *pipe)
-{
- struct uss820dci_softc *sc;
- struct usb2_endpoint_descriptor *ed;
-
- USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
-
- DPRINTFN(5, "pipe=%p\n", pipe);
-
- /* check mode */
- if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
- /* get softc */
- sc = USS820_DCI_BUS2SC(udev->bus);
-
- /* get endpoint descriptor */
- ed = pipe->edesc;
-
- /* reset endpoint */
- uss820dci_clear_stall_sub(sc,
- (ed->bEndpointAddress & UE_ADDR),
- (ed->bmAttributes & UE_XFERTYPE),
- (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT)));
-}
-
-usb2_error_t
-uss820dci_init(struct uss820dci_softc *sc)
-{
- const struct usb2_hw_ep_profile *pf;
- uint8_t n;
- uint8_t temp;
-
- DPRINTF("start\n");
-
- /* set up the bus structure */
- sc->sc_bus.usbrev = USB_REV_1_1;
- sc->sc_bus.methods = &uss820dci_bus_methods;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* we always have VBUS */
- sc->sc_flags.status_vbus = 1;
-
- /* reset the chip */
- USS820_WRITE_1(sc, USS820_SCR, USS820_SCR_SRESET);
- DELAY(100);
- USS820_WRITE_1(sc, USS820_SCR, 0);
-
- /* wait for reset to complete */
- for (n = 0;; n++) {
-
- temp = USS820_READ_1(sc, USS820_MCSR);
-
- if (temp & USS820_MCSR_INIT) {
- break;
- }
- if (n == 100) {
- USB_BUS_UNLOCK(&sc->sc_bus);
- return (USB_ERR_INVAL);
- }
- /* wait a little for things to stabilise */
- DELAY(100);
- }
-
- /* do a pulldown */
- uss820dci_pull_down(sc);
-
- /* wait 10ms for pulldown to stabilise */
- usb2_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100);
-
- /* check hardware revision */
- temp = USS820_READ_1(sc, USS820_REV);
-
- if (temp < 0x13) {
- USB_BUS_UNLOCK(&sc->sc_bus);
- return (USB_ERR_INVAL);
- }
- /* enable interrupts */
- USS820_WRITE_1(sc, USS820_SCR,
- USS820_SCR_T_IRQ |
- USS820_SCR_IE_RESET |
- /* USS820_SCR_RWUPE | */
- USS820_SCR_IE_SUSP |
- USS820_SCR_IRQPOL);
-
- /* enable interrupts */
- USS820_WRITE_1(sc, USS820_SCRATCH,
- USS820_SCRATCH_IE_RESUME);
-
- /* enable features */
- USS820_WRITE_1(sc, USS820_MCSR,
- USS820_MCSR_BDFEAT |
- USS820_MCSR_FEAT);
-
- sc->sc_flags.mcsr_feat = 1;
-
- /* disable interrupts */
- USS820_WRITE_1(sc, USS820_SBIE, 0);
-
- /* disable interrupts */
- USS820_WRITE_1(sc, USS820_SBIE1, 0);
-
- /* disable all endpoints */
- for (n = 0; n != USS820_EP_MAX; n++) {
-
- /* select endpoint */
- USS820_WRITE_1(sc, USS820_EPINDEX, n);
-
- /* disable endpoint */
- uss820dci_update_shared_1(sc, USS820_EPCON, 0, 0);
- }
-
- /*
- * Initialise default values for some registers that cannot be
- * changed during operation!
- */
- for (n = 0; n != USS820_EP_MAX; n++) {
-
- uss820dci_get_hw_ep_profile(NULL, &pf, n);
-
- /* the maximum frame sizes should be the same */
- if (pf->max_in_frame_size != pf->max_out_frame_size) {
- DPRINTF("Max frame size mismatch %u != %u\n",
- pf->max_in_frame_size, pf->max_out_frame_size);
- }
- if (pf->support_isochronous) {
- if (pf->max_in_frame_size <= 64) {
- temp = (USS820_TXCON_FFSZ_16_64 |
- USS820_TXCON_TXISO |
- USS820_TXCON_ATM);
- } else if (pf->max_in_frame_size <= 256) {
- temp = (USS820_TXCON_FFSZ_64_256 |
- USS820_TXCON_TXISO |
- USS820_TXCON_ATM);
- } else if (pf->max_in_frame_size <= 512) {
- temp = (USS820_TXCON_FFSZ_8_512 |
- USS820_TXCON_TXISO |
- USS820_TXCON_ATM);
- } else { /* 1024 bytes */
- temp = (USS820_TXCON_FFSZ_32_1024 |
- USS820_TXCON_TXISO |
- USS820_TXCON_ATM);
- }
- } else {
- if ((pf->max_in_frame_size <= 8) &&
- (sc->sc_flags.mcsr_feat)) {
- temp = (USS820_TXCON_FFSZ_8_512 |
- USS820_TXCON_ATM);
- } else if (pf->max_in_frame_size <= 16) {
- temp = (USS820_TXCON_FFSZ_16_64 |
- USS820_TXCON_ATM);
- } else if ((pf->max_in_frame_size <= 32) &&
- (sc->sc_flags.mcsr_feat)) {
- temp = (USS820_TXCON_FFSZ_32_1024 |
- USS820_TXCON_ATM);
- } else { /* 64 bytes */
- temp = (USS820_TXCON_FFSZ_64_256 |
- USS820_TXCON_ATM);
- }
- }
-
- /* need to configure the chip early */
-
- USS820_WRITE_1(sc, USS820_EPINDEX, n);
- USS820_WRITE_1(sc, USS820_TXCON, temp);
- USS820_WRITE_1(sc, USS820_RXCON, temp);
-
- if (pf->support_control) {
- temp = USS820_EPCON_CTLEP |
- USS820_EPCON_RXSPM |
- USS820_EPCON_RXIE |
- USS820_EPCON_RXEPEN |
- USS820_EPCON_TXOE |
- USS820_EPCON_TXEPEN;
- } else {
- temp = USS820_EPCON_RXEPEN | USS820_EPCON_TXEPEN;
- }
-
- uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF, temp);
- }
-
- USB_BUS_UNLOCK(&sc->sc_bus);
-
- /* catch any lost interrupts */
-
- uss820dci_do_poll(&sc->sc_bus);
-
- return (0); /* success */
-}
-
-void
-uss820dci_uninit(struct uss820dci_softc *sc)
-{
- uint8_t temp;
-
- USB_BUS_LOCK(&sc->sc_bus);
-
- /* disable all interrupts */
- temp = USS820_READ_1(sc, USS820_SCR);
- temp &= ~USS820_SCR_T_IRQ;
- USS820_WRITE_1(sc, USS820_SCR, temp);
-
- sc->sc_flags.port_powered = 0;
- sc->sc_flags.status_vbus = 0;
- sc->sc_flags.status_bus_reset = 0;
- sc->sc_flags.status_suspend = 0;
- sc->sc_flags.change_suspend = 0;
- sc->sc_flags.change_connect = 1;
-
- uss820dci_pull_down(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-void
-uss820dci_suspend(struct uss820dci_softc *sc)
-{
- return;
-}
-
-void
-uss820dci_resume(struct uss820dci_softc *sc)
-{
- return;
-}
-
-static void
-uss820dci_do_poll(struct usb2_bus *bus)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(bus);
-
- USB_BUS_LOCK(&sc->sc_bus);
- uss820dci_interrupt_poll(sc);
- uss820dci_root_ctrl_poll(sc);
- USB_BUS_UNLOCK(&sc->sc_bus);
-}
-
-/*------------------------------------------------------------------------*
- * at91dci bulk support
- *------------------------------------------------------------------------*/
-static void
-uss820dci_device_bulk_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_device_bulk_close(struct usb2_xfer *xfer)
-{
- uss820dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uss820dci_device_bulk_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_device_bulk_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- uss820dci_setup_standard_chain(xfer);
- uss820dci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods uss820dci_device_bulk_methods =
-{
- .open = uss820dci_device_bulk_open,
- .close = uss820dci_device_bulk_close,
- .enter = uss820dci_device_bulk_enter,
- .start = uss820dci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci control support
- *------------------------------------------------------------------------*/
-static void
-uss820dci_device_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_device_ctrl_close(struct usb2_xfer *xfer)
-{
- uss820dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uss820dci_device_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_device_ctrl_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- uss820dci_setup_standard_chain(xfer);
- uss820dci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods uss820dci_device_ctrl_methods =
-{
- .open = uss820dci_device_ctrl_open,
- .close = uss820dci_device_ctrl_close,
- .enter = uss820dci_device_ctrl_enter,
- .start = uss820dci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci interrupt support
- *------------------------------------------------------------------------*/
-static void
-uss820dci_device_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_device_intr_close(struct usb2_xfer *xfer)
-{
- uss820dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uss820dci_device_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_device_intr_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- uss820dci_setup_standard_chain(xfer);
- uss820dci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods uss820dci_device_intr_methods =
-{
- .open = uss820dci_device_intr_open,
- .close = uss820dci_device_intr_close,
- .enter = uss820dci_device_intr_enter,
- .start = uss820dci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci full speed isochronous support
- *------------------------------------------------------------------------*/
-static void
-uss820dci_device_isoc_fs_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_device_isoc_fs_close(struct usb2_xfer *xfer)
-{
- uss820dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uss820dci_device_isoc_fs_enter(struct usb2_xfer *xfer)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
- uint32_t temp;
- uint32_t nframes;
-
- DPRINTFN(6, "xfer=%p next=%d nframes=%d\n",
- xfer, xfer->pipe->isoc_next, xfer->nframes);
-
- /* get the current frame index - we don't need the high bits */
-
- nframes = USS820_READ_1(sc, USS820_SOFL);
-
- /*
- * check if the frame index is within the window where the
- * frames will be inserted
- */
- temp = (nframes - xfer->pipe->isoc_next) & USS820_SOFL_MASK;
-
- if ((xfer->pipe->is_synced == 0) ||
- (temp < xfer->nframes)) {
- /*
- * If there is data underflow or the pipe queue is
- * empty we schedule the transfer a few frames ahead
- * of the current frame position. Else two isochronous
- * transfers might overlap.
- */
- xfer->pipe->isoc_next = (nframes + 3) & USS820_SOFL_MASK;
- xfer->pipe->is_synced = 1;
- DPRINTFN(3, "start next=%d\n", xfer->pipe->isoc_next);
- }
- /*
- * compute how many milliseconds the insertion is ahead of the
- * current frame position:
- */
- temp = (xfer->pipe->isoc_next - nframes) & USS820_SOFL_MASK;
-
- /*
- * pre-compute when the isochronous transfer will be finished:
- */
- xfer->isoc_time_complete =
- usb2_isoc_time_expand(&sc->sc_bus, nframes) + temp +
- xfer->nframes;
-
- /* compute frame number for next insertion */
- xfer->pipe->isoc_next += xfer->nframes;
-
- /* setup TDs */
- uss820dci_setup_standard_chain(xfer);
-}
-
-static void
-uss820dci_device_isoc_fs_start(struct usb2_xfer *xfer)
-{
- /* start TD chain */
- uss820dci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods uss820dci_device_isoc_fs_methods =
-{
- .open = uss820dci_device_isoc_fs_open,
- .close = uss820dci_device_isoc_fs_close,
- .enter = uss820dci_device_isoc_fs_enter,
- .start = uss820dci_device_isoc_fs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci root control support
- *------------------------------------------------------------------------*
- * simulate a hardware HUB by handling
- * all the necessary requests
- *------------------------------------------------------------------------*/
-
-static void
-uss820dci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- uss820dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/*
- * USB descriptors for the virtual Root HUB:
- */
-
-static const struct usb2_device_descriptor uss820dci_devd = {
- .bLength = sizeof(struct usb2_device_descriptor),
- .bDescriptorType = UDESC_DEVICE,
- .bcdUSB = {0x00, 0x02},
- .bDeviceClass = UDCLASS_HUB,
- .bDeviceSubClass = UDSUBCLASS_HUB,
- .bDeviceProtocol = UDPROTO_HSHUBSTT,
- .bMaxPacketSize = 64,
- .bcdDevice = {0x00, 0x01},
- .iManufacturer = 1,
- .iProduct = 2,
- .bNumConfigurations = 1,
-};
-
-static const struct usb2_device_qualifier uss820dci_odevd = {
- .bLength = sizeof(struct usb2_device_qualifier),
- .bDescriptorType = UDESC_DEVICE_QUALIFIER,
- .bcdUSB = {0x00, 0x02},
- .bDeviceClass = UDCLASS_HUB,
- .bDeviceSubClass = UDSUBCLASS_HUB,
- .bDeviceProtocol = UDPROTO_FSHUB,
- .bMaxPacketSize0 = 0,
- .bNumConfigurations = 0,
-};
-
-static const struct uss820dci_config_desc uss820dci_confd = {
- .confd = {
- .bLength = sizeof(struct usb2_config_descriptor),
- .bDescriptorType = UDESC_CONFIG,
- .wTotalLength[0] = sizeof(uss820dci_confd),
- .bNumInterface = 1,
- .bConfigurationValue = 1,
- .iConfiguration = 0,
- .bmAttributes = UC_SELF_POWERED,
- .bMaxPower = 0,
- },
- .ifcd = {
- .bLength = sizeof(struct usb2_interface_descriptor),
- .bDescriptorType = UDESC_INTERFACE,
- .bNumEndpoints = 1,
- .bInterfaceClass = UICLASS_HUB,
- .bInterfaceSubClass = UISUBCLASS_HUB,
- .bInterfaceProtocol = UIPROTO_HSHUBSTT,
- },
-
- .endpd = {
- .bLength = sizeof(struct usb2_endpoint_descriptor),
- .bDescriptorType = UDESC_ENDPOINT,
- .bEndpointAddress = (UE_DIR_IN | USS820_DCI_INTR_ENDPT),
- .bmAttributes = UE_INTERRUPT,
- .wMaxPacketSize[0] = 8,
- .bInterval = 255,
- },
-};
-
-static const struct usb2_hub_descriptor_min uss820dci_hubd = {
- .bDescLength = sizeof(uss820dci_hubd),
- .bDescriptorType = UDESC_HUB,
- .bNbrPorts = 1,
- .wHubCharacteristics[0] =
- (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) & 0xFF,
- .wHubCharacteristics[1] =
- (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 8,
- .bPwrOn2PwrGood = 50,
- .bHubContrCurrent = 0,
- .DeviceRemovable = {0}, /* port is removable */
-};
-
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
-#define STRING_VENDOR \
- 'A', 0, 'G', 0, 'E', 0, 'R', 0, 'E', 0
-
-#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
-
-USB_MAKE_STRING_DESC(STRING_LANG, uss820dci_langtab);
-USB_MAKE_STRING_DESC(STRING_VENDOR, uss820dci_vendor);
-USB_MAKE_STRING_DESC(STRING_PRODUCT, uss820dci_product);
-
-static void
-uss820dci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-uss820dci_root_ctrl_task(struct usb2_bus *bus)
-{
- uss820dci_root_ctrl_poll(USS820_DCI_BUS2SC(bus));
-}
-
-static void
-uss820dci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
- uint16_t value;
- uint16_t index;
- uint8_t use_polling;
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- uss820dci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* buffer reset */
- std->ptr = USB_ADD_BYTES(&sc->sc_hub_temp, 0);
- std->len = 0;
-
- value = UGETW(std->req.wValue);
- index = UGETW(std->req.wIndex);
-
- use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
-
- /* demultiplex the control request */
-
- switch (std->req.bmRequestType) {
- case UT_READ_DEVICE:
- switch (std->req.bRequest) {
- case UR_GET_DESCRIPTOR:
- goto tr_handle_get_descriptor;
- case UR_GET_CONFIG:
- goto tr_handle_get_config;
- case UR_GET_STATUS:
- goto tr_handle_get_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_DEVICE:
- switch (std->req.bRequest) {
- case UR_SET_ADDRESS:
- goto tr_handle_set_address;
- case UR_SET_CONFIG:
- goto tr_handle_set_config;
- case UR_CLEAR_FEATURE:
- goto tr_valid; /* nop */
- case UR_SET_DESCRIPTOR:
- goto tr_valid; /* nop */
- case UR_SET_FEATURE:
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_ENDPOINT:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- switch (UGETW(std->req.wValue)) {
- case UF_ENDPOINT_HALT:
- goto tr_handle_clear_halt;
- case UF_DEVICE_REMOTE_WAKEUP:
- goto tr_handle_clear_wakeup;
- default:
- goto tr_stalled;
- }
- break;
- case UR_SET_FEATURE:
- switch (UGETW(std->req.wValue)) {
- case UF_ENDPOINT_HALT:
- goto tr_handle_set_halt;
- case UF_DEVICE_REMOTE_WAKEUP:
- goto tr_handle_set_wakeup;
- default:
- goto tr_stalled;
- }
- break;
- case UR_SYNCH_FRAME:
- goto tr_valid; /* nop */
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_ENDPOINT:
- switch (std->req.bRequest) {
- case UR_GET_STATUS:
- goto tr_handle_get_ep_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_INTERFACE:
- switch (std->req.bRequest) {
- case UR_SET_INTERFACE:
- goto tr_handle_set_interface;
- case UR_CLEAR_FEATURE:
- goto tr_valid; /* nop */
- case UR_SET_FEATURE:
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_INTERFACE:
- switch (std->req.bRequest) {
- case UR_GET_INTERFACE:
- goto tr_handle_get_interface;
- case UR_GET_STATUS:
- goto tr_handle_get_iface_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_CLASS_INTERFACE:
- case UT_WRITE_VENDOR_INTERFACE:
- /* XXX forward */
- break;
-
- case UT_READ_CLASS_INTERFACE:
- case UT_READ_VENDOR_INTERFACE:
- /* XXX forward */
- break;
-
- case UT_WRITE_CLASS_DEVICE:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- goto tr_valid;
- case UR_SET_DESCRIPTOR:
- case UR_SET_FEATURE:
- break;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_WRITE_CLASS_OTHER:
- switch (std->req.bRequest) {
- case UR_CLEAR_FEATURE:
- goto tr_handle_clear_port_feature;
- case UR_SET_FEATURE:
- goto tr_handle_set_port_feature;
- case UR_CLEAR_TT_BUFFER:
- case UR_RESET_TT:
- case UR_STOP_TT:
- goto tr_valid;
-
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_CLASS_OTHER:
- switch (std->req.bRequest) {
- case UR_GET_TT_STATE:
- goto tr_handle_get_tt_state;
- case UR_GET_STATUS:
- goto tr_handle_get_port_status;
- default:
- goto tr_stalled;
- }
- break;
-
- case UT_READ_CLASS_DEVICE:
- switch (std->req.bRequest) {
- case UR_GET_DESCRIPTOR:
- goto tr_handle_get_class_descriptor;
- case UR_GET_STATUS:
- goto tr_handle_get_class_status;
-
- default:
- goto tr_stalled;
- }
- break;
- default:
- goto tr_stalled;
- }
- goto tr_valid;
-
-tr_handle_get_descriptor:
- switch (value >> 8) {
- case UDESC_DEVICE:
- if (value & 0xff) {
- goto tr_stalled;
- }
- std->len = sizeof(uss820dci_devd);
- std->ptr = USB_ADD_BYTES(&uss820dci_devd, 0);
- goto tr_valid;
- case UDESC_CONFIG:
- if (value & 0xff) {
- goto tr_stalled;
- }
- std->len = sizeof(uss820dci_confd);
- std->ptr = USB_ADD_BYTES(&uss820dci_confd, 0);
- goto tr_valid;
- case UDESC_STRING:
- switch (value & 0xff) {
- case 0: /* Language table */
- std->len = sizeof(uss820dci_langtab);
- std->ptr = USB_ADD_BYTES(&uss820dci_langtab, 0);
- goto tr_valid;
-
- case 1: /* Vendor */
- std->len = sizeof(uss820dci_vendor);
- std->ptr = USB_ADD_BYTES(&uss820dci_vendor, 0);
- goto tr_valid;
-
- case 2: /* Product */
- std->len = sizeof(uss820dci_product);
- std->ptr = USB_ADD_BYTES(&uss820dci_product, 0);
- goto tr_valid;
- default:
- break;
- }
- break;
- default:
- goto tr_stalled;
- }
- goto tr_stalled;
-
-tr_handle_get_config:
- std->len = 1;
- sc->sc_hub_temp.wValue[0] = sc->sc_conf;
- goto tr_valid;
-
-tr_handle_get_status:
- std->len = 2;
- USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED);
- goto tr_valid;
-
-tr_handle_set_address:
- if (value & 0xFF00) {
- goto tr_stalled;
- }
- sc->sc_rt_addr = value;
- goto tr_valid;
-
-tr_handle_set_config:
- if (value >= 2) {
- goto tr_stalled;
- }
- sc->sc_conf = value;
- goto tr_valid;
-
-tr_handle_get_interface:
- std->len = 1;
- sc->sc_hub_temp.wValue[0] = 0;
- goto tr_valid;
-
-tr_handle_get_tt_state:
-tr_handle_get_class_status:
-tr_handle_get_iface_status:
-tr_handle_get_ep_status:
- std->len = 2;
- USETW(sc->sc_hub_temp.wValue, 0);
- goto tr_valid;
-
-tr_handle_set_halt:
-tr_handle_set_interface:
-tr_handle_set_wakeup:
-tr_handle_clear_wakeup:
-tr_handle_clear_halt:
- goto tr_valid;
-
-tr_handle_clear_port_feature:
- if (index != 1) {
- goto tr_stalled;
- }
- DPRINTFN(9, "UR_CLEAR_PORT_FEATURE on port %d\n", index);
-
- switch (value) {
- case UHF_PORT_SUSPEND:
- uss820dci_wakeup_peer(sc);
- break;
-
- case UHF_PORT_ENABLE:
- sc->sc_flags.port_enabled = 0;
- break;
-
- case UHF_PORT_TEST:
- case UHF_PORT_INDICATOR:
- case UHF_C_PORT_ENABLE:
- case UHF_C_PORT_OVER_CURRENT:
- case UHF_C_PORT_RESET:
- /* nops */
- break;
- case UHF_PORT_POWER:
- sc->sc_flags.port_powered = 0;
- uss820dci_pull_down(sc);
- break;
- case UHF_C_PORT_CONNECTION:
- sc->sc_flags.change_connect = 0;
- break;
- case UHF_C_PORT_SUSPEND:
- sc->sc_flags.change_suspend = 0;
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- goto tr_valid;
-
-tr_handle_set_port_feature:
- if (index != 1) {
- goto tr_stalled;
- }
- DPRINTFN(9, "UR_SET_PORT_FEATURE\n");
-
- switch (value) {
- case UHF_PORT_ENABLE:
- sc->sc_flags.port_enabled = 1;
- break;
- case UHF_PORT_SUSPEND:
- case UHF_PORT_RESET:
- case UHF_PORT_TEST:
- case UHF_PORT_INDICATOR:
- /* nops */
- break;
- case UHF_PORT_POWER:
- sc->sc_flags.port_powered = 1;
- break;
- default:
- std->err = USB_ERR_IOERROR;
- goto done;
- }
- goto tr_valid;
-
-tr_handle_get_port_status:
-
- DPRINTFN(9, "UR_GET_PORT_STATUS\n");
-
- if (index != 1) {
- goto tr_stalled;
- }
- if (sc->sc_flags.status_vbus) {
- uss820dci_pull_up(sc);
- } else {
- uss820dci_pull_down(sc);
- }
-
- /* Select FULL-speed and Device Side Mode */
-
- value = UPS_PORT_MODE_DEVICE;
-
- if (sc->sc_flags.port_powered) {
- value |= UPS_PORT_POWER;
- }
- if (sc->sc_flags.port_enabled) {
- value |= UPS_PORT_ENABLED;
- }
- if (sc->sc_flags.status_vbus &&
- sc->sc_flags.status_bus_reset) {
- value |= UPS_CURRENT_CONNECT_STATUS;
- }
- if (sc->sc_flags.status_suspend) {
- value |= UPS_SUSPEND;
- }
- USETW(sc->sc_hub_temp.ps.wPortStatus, value);
-
- value = 0;
-
- if (sc->sc_flags.change_connect) {
- value |= UPS_C_CONNECT_STATUS;
- }
- if (sc->sc_flags.change_suspend) {
- value |= UPS_C_SUSPEND;
- }
- USETW(sc->sc_hub_temp.ps.wPortChange, value);
- std->len = sizeof(sc->sc_hub_temp.ps);
- goto tr_valid;
-
-tr_handle_get_class_descriptor:
- if (value & 0xFF) {
- goto tr_stalled;
- }
- std->ptr = USB_ADD_BYTES(&uss820dci_hubd, 0);
- std->len = sizeof(uss820dci_hubd);
- goto tr_valid;
-
-tr_stalled:
- std->err = USB_ERR_STALLED;
-tr_valid:
-done:
- return;
-}
-
-static void
-uss820dci_root_ctrl_poll(struct uss820dci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &uss820dci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods uss820dci_root_ctrl_methods =
-{
- .open = uss820dci_root_ctrl_open,
- .close = uss820dci_root_ctrl_close,
- .enter = uss820dci_root_ctrl_enter,
- .start = uss820dci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-uss820dci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_root_intr_close(struct usb2_xfer *xfer)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- uss820dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uss820dci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_root_intr_start(struct usb2_xfer *xfer)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods uss820dci_root_intr_methods =
-{
- .open = uss820dci_root_intr_open,
- .close = uss820dci_root_intr_close,
- .enter = uss820dci_root_intr_enter,
- .start = uss820dci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
-uss820dci_xfer_setup(struct usb2_setup_params *parm)
-{
- const struct usb2_hw_ep_profile *pf;
- struct uss820dci_softc *sc;
- struct usb2_xfer *xfer;
- void *last_obj;
- uint32_t ntd;
- uint32_t n;
- uint8_t ep_no;
-
- sc = USS820_DCI_BUS2SC(parm->udev->bus);
- xfer = parm->curr_xfer;
-
- /*
- * NOTE: This driver does not use any of the parameters that
- * are computed from the following values. Just set some
- * reasonable dummies:
- */
- parm->hc_max_packet_size = 0x500;
- parm->hc_max_packet_count = 1;
- parm->hc_max_frame_size = 0x500;
-
- usb2_transfer_setup_sub(parm);
-
- /*
- * compute maximum number of TDs
- */
- if (parm->methods == &uss820dci_device_ctrl_methods) {
-
- ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC */ ;
-
- } else if (parm->methods == &uss820dci_device_bulk_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &uss820dci_device_intr_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &uss820dci_device_isoc_fs_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else {
-
- ntd = 0;
- }
-
- /*
- * check if "usb2_transfer_setup_sub" set an error
- */
- if (parm->err) {
- return;
- }
- /*
- * allocate transfer descriptors
- */
- last_obj = NULL;
-
- /*
- * get profile stuff
- */
- if (ntd) {
-
- ep_no = xfer->endpoint & UE_ADDR;
- uss820dci_get_hw_ep_profile(parm->udev, &pf, ep_no);
-
- if (pf == NULL) {
- /* should not happen */
- parm->err = USB_ERR_INVAL;
- return;
- }
- } else {
- ep_no = 0;
- pf = NULL;
- }
-
- /* align data */
- parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
-
- for (n = 0; n != ntd; n++) {
-
- struct uss820dci_td *td;
-
- if (parm->buf) {
-
- td = USB_ADD_BYTES(parm->buf, parm->size[0]);
-
- /* init TD */
- td->io_tag = sc->sc_io_tag;
- td->io_hdl = sc->sc_io_hdl;
- td->max_packet_size = xfer->max_packet_size;
- td->rx_stat_reg = USS820_GET_REG(sc, USS820_RXSTAT);
- td->tx_stat_reg = USS820_GET_REG(sc, USS820_TXSTAT);
- td->rx_flag_reg = USS820_GET_REG(sc, USS820_RXFLG);
- td->tx_flag_reg = USS820_GET_REG(sc, USS820_TXFLG);
- td->rx_fifo_reg = USS820_GET_REG(sc, USS820_RXDAT);
- td->tx_fifo_reg = USS820_GET_REG(sc, USS820_TXDAT);
- td->rx_count_low_reg = USS820_GET_REG(sc, USS820_RXCNTL);
- td->rx_count_high_reg = USS820_GET_REG(sc, USS820_RXCNTH);
- td->tx_count_low_reg = USS820_GET_REG(sc, USS820_TXCNTL);
- td->tx_count_high_reg = USS820_GET_REG(sc, USS820_TXCNTH);
- td->rx_cntl_reg = USS820_GET_REG(sc, USS820_RXCON);
- td->tx_cntl_reg = USS820_GET_REG(sc, USS820_TXCON);
- td->pend_reg = USS820_GET_REG(sc, USS820_PEND);
- td->ep_reg = USS820_GET_REG(sc, USS820_EPINDEX);
- td->ep_index = ep_no;
- if (pf->support_multi_buffer &&
- (parm->methods != &uss820dci_device_ctrl_methods)) {
- td->support_multi_buffer = 1;
- }
- td->obj_next = last_obj;
-
- last_obj = td;
- }
- parm->size[0] += sizeof(*td);
- }
-
- xfer->td_start[0] = last_obj;
-}
-
-static void
-uss820dci_xfer_unsetup(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
- struct usb2_pipe *pipe)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(udev->bus);
-
- DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
- pipe, udev->address,
- edesc->bEndpointAddress, udev->flags.usb2_mode,
- sc->sc_rt_addr);
-
- if (udev->device_index == sc->sc_rt_addr) {
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &uss820dci_root_ctrl_methods;
- break;
- case UE_DIR_IN | USS820_DCI_INTR_ENDPT:
- pipe->methods = &uss820dci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
-
- if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
- if (udev->speed != USB_SPEED_FULL) {
- /* not supported */
- return;
- }
- switch (edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- pipe->methods = &uss820dci_device_ctrl_methods;
- break;
- case UE_INTERRUPT:
- pipe->methods = &uss820dci_device_intr_methods;
- break;
- case UE_ISOCHRONOUS:
- pipe->methods = &uss820dci_device_isoc_fs_methods;
- break;
- case UE_BULK:
- pipe->methods = &uss820dci_device_bulk_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- }
-}
-
-struct usb2_bus_methods uss820dci_bus_methods =
-{
- .pipe_init = &uss820dci_pipe_init,
- .xfer_setup = &uss820dci_xfer_setup,
- .xfer_unsetup = &uss820dci_xfer_unsetup,
- .do_poll = &uss820dci_do_poll,
- .get_hw_ep_profile = &uss820dci_get_hw_ep_profile,
- .set_stall = &uss820dci_set_stall,
- .clear_stall = &uss820dci_clear_stall,
- .roothub_exec = &uss820dci_root_ctrl_task,
-};
diff --git a/sys/dev/usb2/controller/uss820dci.h b/sys/dev/usb2/controller/uss820dci.h
deleted file mode 100644
index f99e2d5..0000000
--- a/sys/dev/usb2/controller/uss820dci.h
+++ /dev/null
@@ -1,377 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2007 Hans Petter Selasky <hselasky@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.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- */
-
-#ifndef _USS820_DCI_H_
-#define _USS820_DCI_H_
-
-#define USS820_MAX_DEVICES (USB_MIN_DEVICES + 1)
-
-#define USS820_EP_MAX 8 /* maximum number of endpoints */
-
-#define USS820_TXDAT 0x00 /* Transmit FIFO data */
-
-#define USS820_TXCNTL 0x01 /* Transmit FIFO byte count low */
-#define USS820_TXCNTL_MASK 0xFF
-
-#define USS820_TXCNTH 0x02 /* Transmit FIFO byte count high */
-#define USS820_TXCNTH_MASK 0x03
-#define USS820_TXCNTH_UNUSED 0xFC
-
-#define USS820_TXCON 0x03 /* USB transmit FIFO control */
-#define USS820_TXCON_REVRP 0x01
-#define USS820_TXCON_ADVRM 0x02
-#define USS820_TXCON_ATM 0x04 /* Automatic Transmit Management */
-#define USS820_TXCON_TXISO 0x08 /* Transmit Isochronous Data */
-#define USS820_TXCON_UNUSED 0x10
-#define USS820_TXCON_FFSZ_16_64 0x00
-#define USS820_TXCON_FFSZ_64_256 0x20
-#define USS820_TXCON_FFSZ_8_512 0x40
-#define USS820_TXCON_FFSZ_32_1024 0x60
-#define USS820_TXCON_FFSZ_MASK 0x60
-#define USS820_TXCON_TXCLR 0x80 /* Transmit FIFO clear */
-
-#define USS820_TXFLG 0x04 /* Transmit FIFO flag (Read Only) */
-#define USS820_TXFLG_TXOVF 0x01 /* TX overrun */
-#define USS820_TXFLG_TXURF 0x02 /* TX underrun */
-#define USS820_TXFLG_TXFULL 0x04 /* TX full */
-#define USS820_TXFLG_TXEMP 0x08 /* TX empty */
-#define USS820_TXFLG_UNUSED 0x30
-#define USS820_TXFLG_TXFIF0 0x40
-#define USS820_TXFLG_TXFIF1 0x80
-
-#define USS820_RXDAT 0x05 /* Receive FIFO data */
-
-#define USS820_RXCNTL 0x06 /* Receive FIFO byte count low */
-#define USS820_RXCNTL_MASK 0xFF
-
-#define USS820_RXCNTH 0x07 /* Receive FIFO byte count high */
-#define USS820_RXCNTH_MASK 0x03
-#define USS820_RXCNTH_UNUSED 0xFC
-
-#define USS820_RXCON 0x08 /* Receive FIFO control */
-#define USS820_RXCON_REVWP 0x01
-#define USS820_RXCON_ADVWM 0x02
-#define USS820_RXCON_ARM 0x04 /* Auto Receive Management */
-#define USS820_RXCON_RXISO 0x08 /* Receive Isochronous Data */
-#define USS820_RXCON_RXFFRC 0x10 /* FIFO Read Complete */
-#define USS820_RXCON_FFSZ_16_64 0x00
-#define USS820_RXCON_FFSZ_64_256 0x20
-#define USS820_RXCON_FFSZ_8_512 0x40
-#define USS820_RXCON_FFSZ_32_1024 0x60
-#define USS820_RXCON_RXCLR 0x80 /* Receive FIFO clear */
-
-#define USS820_RXFLG 0x09 /* Receive FIFO flag (Read Only) */
-#define USS820_RXFLG_RXOVF 0x01 /* RX overflow */
-#define USS820_RXFLG_RXURF 0x02 /* RX underflow */
-#define USS820_RXFLG_RXFULL 0x04 /* RX full */
-#define USS820_RXFLG_RXEMP 0x08 /* RX empty */
-#define USS820_RXFLG_RXFLUSH 0x10 /* RX flush */
-#define USS820_RXFLG_UNUSED 0x20
-#define USS820_RXFLG_RXFIF0 0x40
-#define USS820_RXFLG_RXFIF1 0x80
-
-#define USS820_EPINDEX 0x0a /* Endpoint index selection */
-#define USS820_EPINDEX_MASK 0x07
-#define USS820_EPINDEX_UNUSED 0xF8
-
-#define USS820_EPCON 0x0b /* Endpoint control */
-#define USS820_EPCON_TXEPEN 0x01 /* Transmit Endpoint Enable */
-#define USS820_EPCON_TXOE 0x02 /* Transmit Output Enable */
-#define USS820_EPCON_RXEPEN 0x04 /* Receive Endpoint Enable */
-#define USS820_EPCON_RXIE 0x08 /* Receive Input Enable */
-#define USS820_EPCON_RXSPM 0x10 /* Receive Single-Packet Mode */
-#define USS820_EPCON_CTLEP 0x20 /* Control Endpoint */
-#define USS820_EPCON_TXSTL 0x40 /* Stall Transmit Endpoint */
-#define USS820_EPCON_RXSTL 0x80 /* Stall Receive Endpoint */
-
-#define USS820_TXSTAT 0x0c /* Transmit status */
-#define USS820_TXSTAT_TXACK 0x01 /* Transmit Acknowledge */
-#define USS820_TXSTAT_TXERR 0x02 /* Transmit Error */
-#define USS820_TXSTAT_TXVOID 0x04 /* Transmit Void */
-#define USS820_TXSTAT_TXSOVW 0x08 /* Transmit Data Sequence Overwrite
- * Bit */
-#define USS820_TXSTAT_TXFLUSH 0x10 /* Transmit FIFO Packet Flushed */
-#define USS820_TXSTAT_TXNAKE 0x20 /* Transmit NAK Mode Enable */
-#define USS820_TXSTAT_TXDSAM 0x40 /* Transmit Data-Set-Available Mode */
-#define USS820_TXSTAT_TXSEQ 0x80 /* Transmitter Current Sequence Bit */
-
-#define USS820_RXSTAT 0x0d /* Receive status */
-#define USS820_RXSTAT_RXACK 0x01 /* Receive Acknowledge */
-#define USS820_RXSTAT_RXERR 0x02 /* Receive Error */
-#define USS820_RXSTAT_RXVOID 0x04 /* Receive Void */
-#define USS820_RXSTAT_RXSOVW 0x08 /* Receive Data Sequence Overwrite Bit */
-#define USS820_RXSTAT_EDOVW 0x10 /* End Overwrite Flag */
-#define USS820_RXSTAT_STOVW 0x20 /* Start Overwrite Flag */
-#define USS820_RXSTAT_RXSETUP 0x40 /* Received SETUP token */
-#define USS820_RXSTAT_RXSEQ 0x80 /* Receiver Endpoint Sequence Bit */
-
-#define USS820_SOFL 0x0e /* Start Of Frame counter low */
-#define USS820_SOFL_MASK 0xFF
-
-#define USS820_SOFH 0x0f /* Start Of Frame counter high */
-#define USS820_SOFH_MASK 0x07
-#define USS820_SOFH_SOFDIS 0x08 /* SOF Pin Output Disable */
-#define USS820_SOFH_FTLOCK 0x10 /* Frame Timer Lock */
-#define USS820_SOFH_SOFIE 0x20 /* SOF Interrupt Enable */
-#define USS820_SOFH_ASOF 0x40 /* Any Start of Frame */
-#define USS820_SOFH_SOFACK 0x80 /* SOF Token Received Without Error */
-
-#define USS820_FADDR 0x10 /* Function Address */
-#define USS820_FADDR_MASK 0x7F
-#define USS820_FADDR_UNUSED 0x80
-
-#define USS820_SCR 0x11 /* System Control */
-#define USS820_SCR_UNUSED 0x01
-#define USS820_SCR_T_IRQ 0x02 /* Global Interrupt Enable */
-#define USS820_SCR_IRQLVL 0x04 /* Interrupt Mode */
-#define USS820_SCR_SRESET 0x08 /* Software reset */
-#define USS820_SCR_IE_RESET 0x10 /* Enable Reset Interrupt */
-#define USS820_SCR_IE_SUSP 0x20 /* Enable Suspend Interrupt */
-#define USS820_SCR_RWUPE 0x40 /* Enable Remote Wake-Up Feature */
-#define USS820_SCR_IRQPOL 0x80 /* IRQ polarity */
-
-#define USS820_SSR 0x12 /* System Status */
-#define USS820_SSR_RESET 0x01 /* Reset Condition Detected on USB
- * cable */
-#define USS820_SSR_SUSPEND 0x02 /* Suspend Detected */
-#define USS820_SSR_RESUME 0x04 /* Resume Detected */
-#define USS820_SSR_SUSPDIS 0x08 /* Suspend Disable */
-#define USS820_SSR_SUSPPO 0x10 /* Suspend Power Off */
-#define USS820_SSR_UNUSED 0xE0
-
-#define USS820_UNK0 0x13 /* Unknown */
-#define USS820_UNK0_UNUSED 0xFF
-
-#define USS820_SBI 0x14 /* Serial bus interrupt low */
-#define USS820_SBI_FTXD0 0x01 /* Function Transmit Done, EP 0 */
-#define USS820_SBI_FRXD0 0x02 /* Function Receive Done, EP 0 */
-#define USS820_SBI_FTXD1 0x04
-#define USS820_SBI_FRXD1 0x08
-#define USS820_SBI_FTXD2 0x10
-#define USS820_SBI_FRXD2 0x20
-#define USS820_SBI_FTXD3 0x40
-#define USS820_SBI_FRXD3 0x80
-
-#define USS820_SBI1 0x15 /* Serial bus interrupt high */
-#define USS820_SBI1_FTXD4 0x01
-#define USS820_SBI1_FRXD4 0x02
-#define USS820_SBI1_FTXD5 0x04
-#define USS820_SBI1_FRXD5 0x08
-#define USS820_SBI1_FTXD6 0x10
-#define USS820_SBI1_FRXD6 0x20
-#define USS820_SBI1_FTXD7 0x40
-#define USS820_SBI1_FRXD7 0x80
-
-#define USS820_SBIE 0x16 /* Serial bus interrupt enable low */
-#define USS820_SBIE_FTXIE0 0x01
-#define USS820_SBIE_FRXIE0 0x02
-#define USS820_SBIE_FTXIE1 0x04
-#define USS820_SBIE_FRXIE1 0x08
-#define USS820_SBIE_FTXIE2 0x10
-#define USS820_SBIE_FRXIE2 0x20
-#define USS820_SBIE_FTXIE3 0x40
-#define USS820_SBIE_FRXIE3 0x80
-
-#define USS820_SBIE1 0x17 /* Serial bus interrupt enable high */
-#define USS820_SBIE1_FTXIE4 0x01
-#define USS820_SBIE1_FRXIE4 0x02
-#define USS820_SBIE1_FTXIE5 0x04
-#define USS820_SBIE1_FRXIE5 0x08
-#define USS820_SBIE1_FTXIE6 0x10
-#define USS820_SBIE1_FRXIE6 0x20
-#define USS820_SBIE1_FTXIE7 0x40
-#define USS820_SBIE1_FRXIE7 0x80
-
-#define USS820_REV 0x18 /* Hardware revision */
-#define USS820_REV_MIN 0x0F
-#define USS820_REV_MAJ 0xF0
-
-#define USS820_LOCK 0x19 /* Suspend power-off locking */
-#define USS820_LOCK_UNLOCKED 0x01
-#define USS820_LOCK_UNUSED 0xFE
-
-#define USS820_PEND 0x1a /* Pend hardware status update */
-#define USS820_PEND_PEND 0x01
-#define USS820_PEND_UNUSED 0xFE
-
-#define USS820_SCRATCH 0x1b /* Scratch firmware information */
-#define USS820_SCRATCH_MASK 0x7F
-#define USS820_SCRATCH_IE_RESUME 0x80 /* Enable Resume Interrupt */
-
-#define USS820_MCSR 0x1c /* Miscellaneous control and status */
-#define USS820_MCSR_DPEN 0x01 /* DPLS Pull-Up Enable */
-#define USS820_MCSR_SUSPLOE 0x02 /* Suspend Lock Out Enable */
-#define USS820_MCSR_BDFEAT 0x04 /* Board Feature Enable */
-#define USS820_MCSR_FEAT 0x08 /* Feature Enable */
-#define USS820_MCSR_PKGID 0x10 /* Package Identification */
-#define USS820_MCSR_SUSPS 0x20 /* Suspend Status */
-#define USS820_MCSR_INIT 0x40 /* Device Initialized */
-#define USS820_MCSR_RWUPR 0x80 /* Remote Wakeup-Up Remember */
-
-#define USS820_DSAV 0x1d /* Data set available low (Read Only) */
-#define USS820_DSAV_TXAV0 0x01
-#define USS820_DSAV_RXAV0 0x02
-#define USS820_DSAV_TXAV1 0x04
-#define USS820_DSAV_RXAV1 0x08
-#define USS820_DSAV_TXAV2 0x10
-#define USS820_DSAV_RXAV2 0x20
-#define USS820_DSAV_TXAV3 0x40
-#define USS820_DSAV_RXAV3 0x80
-
-#define USS820_DSAV1 0x1e /* Data set available high */
-#define USS820_DSAV1_TXAV4 0x01
-#define USS820_DSAV1_RXAV4 0x02
-#define USS820_DSAV1_TXAV5 0x04
-#define USS820_DSAV1_RXAV5 0x08
-#define USS820_DSAV1_TXAV6 0x10
-#define USS820_DSAV1_RXAV6 0x20
-#define USS820_DSAV1_TXAV7 0x40
-#define USS820_DSAV1_RXAV7 0x80
-
-#define USS820_UNK1 0x1f /* Unknown */
-#define USS820_UNK1_UNKNOWN 0xFF
-
-#define USS820_GET_REG(sc,reg) \
- ((reg) << (sc)->sc_reg_shift)
-
-#define USS820_READ_1(sc, reg) \
- bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, \
- USS820_GET_REG(sc,reg))
-
-#define USS820_WRITE_1(sc, reg, data) \
- bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, \
- USS820_GET_REG(sc,reg), data)
-
-struct uss820dci_td;
-
-typedef uint8_t (uss820dci_cmd_t)(struct uss820dci_td *td);
-
-struct uss820dci_td {
- bus_space_tag_t io_tag;
- bus_space_handle_t io_hdl;
- struct uss820dci_td *obj_next;
- uss820dci_cmd_t *func;
- struct usb2_page_cache *pc;
- uint32_t offset;
- uint32_t remainder;
- uint16_t max_packet_size;
- uint8_t rx_stat_reg;
- uint8_t tx_stat_reg;
- uint8_t rx_flag_reg;
- uint8_t tx_flag_reg;
- uint8_t rx_fifo_reg;
- uint8_t tx_fifo_reg;
- uint8_t rx_count_low_reg;
- uint8_t rx_count_high_reg;
- uint8_t tx_count_low_reg;
- uint8_t tx_count_high_reg;
- uint8_t rx_cntl_reg;
- uint8_t tx_cntl_reg;
- uint8_t ep_reg;
- uint8_t pend_reg;
- uint8_t ep_index;
- uint8_t error:1;
- uint8_t alt_next:1;
- uint8_t short_pkt:1;
- uint8_t support_multi_buffer:1;
- uint8_t did_stall:1;
-};
-
-struct uss820_std_temp {
- uss820dci_cmd_t *func;
- struct usb2_page_cache *pc;
- struct uss820dci_td *td;
- struct uss820dci_td *td_next;
- uint32_t len;
- uint32_t offset;
- uint16_t max_frame_size;
- uint8_t short_pkt;
- /*
- * short_pkt = 0: transfer should be short terminated
- * short_pkt = 1: transfer should not be short terminated
- */
- uint8_t setup_alt_next;
-};
-
-struct uss820dci_config_desc {
- struct usb2_config_descriptor confd;
- struct usb2_interface_descriptor ifcd;
- struct usb2_endpoint_descriptor endpd;
-} __packed;
-
-union uss820_hub_temp {
- uWord wValue;
- struct usb2_port_status ps;
-};
-
-struct uss820_flags {
- uint8_t change_connect:1;
- uint8_t change_suspend:1;
- uint8_t status_suspend:1; /* set if suspended */
- uint8_t status_vbus:1; /* set if present */
- uint8_t status_bus_reset:1; /* set if reset complete */
- uint8_t clocks_off:1;
- uint8_t port_powered:1;
- uint8_t port_enabled:1;
- uint8_t d_pulled_up:1;
- uint8_t mcsr_feat:1;
-};
-
-struct uss820dci_softc {
- struct usb2_bus sc_bus;
- union uss820_hub_temp sc_hub_temp;
- LIST_HEAD(, usb2_xfer) sc_interrupt_list_head;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
-
- struct usb2_device *sc_devices[USS820_MAX_DEVICES];
- struct resource *sc_io_res;
- struct resource *sc_irq_res;
- void *sc_intr_hdl;
- bus_size_t sc_io_size;
- bus_space_tag_t sc_io_tag;
- bus_space_handle_t sc_io_hdl;
-
- uint8_t sc_rt_addr; /* root HUB address */
- uint8_t sc_dv_addr; /* device address */
- uint8_t sc_conf; /* root HUB config */
- uint8_t sc_reg_shift;
-
- uint8_t sc_hub_idata[1];
-
- struct uss820_flags sc_flags;
-};
-
-/* prototypes */
-
-usb2_error_t uss820dci_init(struct uss820dci_softc *sc);
-void uss820dci_uninit(struct uss820dci_softc *sc);
-void uss820dci_suspend(struct uss820dci_softc *sc);
-void uss820dci_resume(struct uss820dci_softc *sc);
-void uss820dci_interrupt(struct uss820dci_softc *sc);
-
-#endif /* _USS820_DCI_H_ */
diff --git a/sys/dev/usb2/controller/uss820dci_atmelarm.c b/sys/dev/usb2/controller/uss820dci_atmelarm.c
deleted file mode 100644
index 387c167..0000000
--- a/sys/dev/usb2/controller/uss820dci_atmelarm.c
+++ /dev/null
@@ -1,239 +0,0 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*-
- * Copyright (c) 2008 Hans Petter Selasky <hselasky@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.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/uss820dci.h>
-
-#include <sys/rman.h>
-
-static device_probe_t uss820_atmelarm_probe;
-static device_attach_t uss820_atmelarm_attach;
-static device_detach_t uss820_atmelarm_detach;
-static device_suspend_t uss820_atmelarm_suspend;
-static device_resume_t uss820_atmelarm_resume;
-static device_shutdown_t uss820_atmelarm_shutdown;
-
-static device_method_t uss820dci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, uss820_atmelarm_probe),
- DEVMETHOD(device_attach, uss820_atmelarm_attach),
- DEVMETHOD(device_detach, uss820_atmelarm_detach),
- DEVMETHOD(device_suspend, uss820_atmelarm_suspend),
- DEVMETHOD(device_resume, uss820_atmelarm_resume),
- DEVMETHOD(device_shutdown, uss820_atmelarm_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
-};
-
-static driver_t uss820dci_driver = {
- .name = "uss820",
- .methods = uss820dci_methods,
- .size = sizeof(struct uss820dci_softc),
-};
-
-static devclass_t uss820dci_devclass;
-
-DRIVER_MODULE(uss820, atmelarm, uss820dci_driver, uss820dci_devclass, 0, 0);
-MODULE_DEPEND(uss820, usb2_controller, 1, 1, 1);
-MODULE_DEPEND(uss820, usb2_core, 1, 1, 1);
-
-static const char *const uss820_desc = "USS820 USB Device Controller";
-
-static int
-uss820_atmelarm_suspend(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- int err;
-
- err = bus_generic_suspend(dev);
- if (err == 0) {
- uss820dci_suspend(sc);
- }
- return (err);
-}
-
-static int
-uss820_atmelarm_resume(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- int err;
-
- uss820dci_resume(sc);
-
- err = bus_generic_resume(dev);
-
- return (err);
-}
-
-static int
-uss820_atmelarm_shutdown(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- int err;
-
- err = bus_generic_shutdown(dev);
- if (err)
- return (err);
-
- uss820dci_uninit(sc);
-
- return (0);
-}
-
-static int
-uss820_atmelarm_probe(device_t dev)
-{
- device_set_desc(dev, uss820_desc);
- return (0); /* success */
-}
-
-static int
-uss820_atmelarm_attach(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- int err;
- int rid;
-
- /* initialise some bus fields */
- sc->sc_bus.parent = dev;
- sc->sc_bus.devices = sc->sc_devices;
- sc->sc_bus.devices_max = USS820_MAX_DEVICES;
-
- /* get all DMA memory */
- if (usb2_bus_mem_alloc_all(&sc->sc_bus,
- USB_GET_DMA_TAG(dev), NULL)) {
- return (ENOMEM);
- }
- rid = 0;
- sc->sc_io_res =
- bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
-
- if (!sc->sc_io_res) {
- goto error;
- }
- sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
- sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
- sc->sc_io_size = rman_get_size(sc->sc_io_res);
-
- /* multiply all addresses by 4 */
- sc->sc_reg_shift = 2;
-
- rid = 0;
- sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (sc->sc_irq_res == NULL) {
- goto error;
- }
- sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
- if (!(sc->sc_bus.bdev)) {
- goto error;
- }
- device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
-
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)uss820dci_interrupt, sc, &sc->sc_intr_hdl);
-#else
- err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)uss820dci_interrupt, sc, &sc->sc_intr_hdl);
-#endif
- if (err) {
- sc->sc_intr_hdl = NULL;
- goto error;
- }
- err = uss820dci_init(sc);
- if (err) {
- device_printf(dev, "Init failed\n");
- goto error;
- }
- err = device_probe_and_attach(sc->sc_bus.bdev);
- if (err) {
- device_printf(dev, "USB probe and attach failed\n");
- goto error;
- }
- return (0);
-
-error:
- uss820_atmelarm_detach(dev);
- return (ENXIO);
-}
-
-static int
-uss820_atmelarm_detach(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- device_t bdev;
- int err;
-
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(dev);
-
- if (sc->sc_irq_res && sc->sc_intr_hdl) {
- /*
- * only call at91_udp_uninit() after at91_udp_init()
- */
- uss820dci_uninit(sc);
-
- err = bus_teardown_intr(dev, sc->sc_irq_res,
- sc->sc_intr_hdl);
- sc->sc_intr_hdl = NULL;
- }
- if (sc->sc_irq_res) {
- bus_release_resource(dev, SYS_RES_IRQ, 0,
- sc->sc_irq_res);
- sc->sc_irq_res = NULL;
- }
- if (sc->sc_io_res) {
- bus_release_resource(dev, SYS_RES_IOPORT, 0,
- sc->sc_io_res);
- sc->sc_io_res = NULL;
- }
- usb2_bus_mem_free_all(&sc->sc_bus, NULL);
-
- return (0);
-}
diff --git a/sys/dev/usb2/controller/uss820dci_pccard.c b/sys/dev/usb2/controller/uss820dci_pccard.c
deleted file mode 100644
index f57935d..0000000
--- a/sys/dev/usb2/controller/uss820dci_pccard.c
+++ /dev/null
@@ -1,266 +0,0 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*-
- * Copyright (c) 2008 Hans Petter Selasky <hselasky@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.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <dev/usb2/include/usb2_mfunc.h>
-#include <dev/usb2/include/usb2_defs.h>
-#include <dev/usb2/include/usb2_standard.h>
-
-#include <dev/usb2/core/usb2_core.h>
-#include <dev/usb2/core/usb2_busdma.h>
-#include <dev/usb2/core/usb2_process.h>
-#include <dev/usb2/core/usb2_config_td.h>
-#include <dev/usb2/core/usb2_sw_transfer.h>
-#include <dev/usb2/core/usb2_util.h>
-
-#include <dev/usb2/controller/usb2_controller.h>
-#include <dev/usb2/controller/usb2_bus.h>
-#include <dev/usb2/controller/uss820dci.h>
-
-#include <dev/pccard/pccardreg.h>
-#include <dev/pccard/pccardvar.h>
-
-#include <sys/rman.h>
-
-static device_probe_t uss820_pccard_probe;
-static device_attach_t uss820_pccard_attach;
-static device_detach_t uss820_pccard_detach;
-static device_suspend_t uss820_pccard_suspend;
-static device_resume_t uss820_pccard_resume;
-static device_shutdown_t uss820_pccard_shutdown;
-
-static uint8_t uss820_pccard_lookup(device_t dev);
-
-static device_method_t uss820dci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, uss820_pccard_probe),
- DEVMETHOD(device_attach, uss820_pccard_attach),
- DEVMETHOD(device_detach, uss820_pccard_detach),
- DEVMETHOD(device_suspend, uss820_pccard_suspend),
- DEVMETHOD(device_resume, uss820_pccard_resume),
- DEVMETHOD(device_shutdown, uss820_pccard_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
-};
-
-static driver_t uss820dci_driver = {
- .name = "uss820",
- .methods = uss820dci_methods,
- .size = sizeof(struct uss820dci_softc),
-};
-
-static devclass_t uss820dci_devclass;
-
-DRIVER_MODULE(uss820, pccard, uss820dci_driver, uss820dci_devclass, 0, 0);
-MODULE_DEPEND(uss820, usb2_core, 1, 1, 1);
-
-static const char *const uss820_desc = "USS820 USB Device Controller";
-
-static int
-uss820_pccard_suspend(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- int err;
-
- err = bus_generic_suspend(dev);
- if (err == 0) {
- uss820dci_suspend(sc);
- }
- return (err);
-}
-
-static int
-uss820_pccard_resume(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- int err;
-
- uss820dci_resume(sc);
-
- err = bus_generic_resume(dev);
-
- return (err);
-}
-
-static int
-uss820_pccard_shutdown(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- int err;
-
- err = bus_generic_shutdown(dev);
- if (err)
- return (err);
-
- uss820dci_uninit(sc);
-
- return (0);
-}
-
-static uint8_t
-uss820_pccard_lookup(device_t dev)
-{
- uint32_t prod;
- uint32_t vend;
-
- pccard_get_vendor(dev, &vend);
- pccard_get_product(dev, &prod);
-
- /* ID's will be added later */
- return (0);
-}
-
-static int
-uss820_pccard_probe(device_t dev)
-{
- if (uss820_pccard_lookup(dev)) {
- device_set_desc(dev, uss820_desc);
- return (0);
- }
- return (ENXIO);
-}
-static int
-uss820_pccard_attach(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- int err;
- int rid;
-
- if (sc == NULL) {
- return (ENXIO);
- }
- /* get all DMA memory */
-
- if (usb2_bus_mem_alloc_all(&sc->sc_bus,
- USB_GET_DMA_TAG(dev), NULL)) {
- return (ENOMEM);
- }
- rid = 0;
- sc->sc_io_res =
- bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
-
- if (!sc->sc_io_res) {
- goto error;
- }
- sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
- sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
- sc->sc_io_size = rman_get_size(sc->sc_io_res);
-
- /* multiply all addresses by 4 */
- sc->sc_reg_shift = 2;
-
- rid = 0;
- sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
- if (sc->sc_irq_res == NULL) {
- goto error;
- }
- sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
- if (!(sc->sc_bus.bdev)) {
- goto error;
- }
- device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
-
- err = usb2_config_td_setup(&sc->sc_config_td, sc,
- &sc->sc_bus.mtx, NULL, 0, 4);
- if (err) {
- device_printf(dev, "could not setup config thread!\n");
- goto error;
- }
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)uss820dci_interrupt, sc, &sc->sc_intr_hdl);
-#else
- err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)uss820dci_interrupt, sc, &sc->sc_intr_hdl);
-#endif
- if (err) {
- sc->sc_intr_hdl = NULL;
- goto error;
- }
- err = uss820dci_init(sc);
- if (err) {
- device_printf(dev, "Init failed\n");
- goto error;
- }
- err = device_probe_and_attach(sc->sc_bus.bdev);
- if (err) {
- device_printf(dev, "USB probe and attach failed\n");
- goto error;
- }
- return (0);
-
-error:
- uss820_pccard_detach(dev);
- return (ENXIO);
-}
-
-static int
-uss820_pccard_detach(device_t dev)
-{
- struct uss820dci_softc *sc = device_get_softc(dev);
- device_t bdev;
- int err;
-
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
- /* during module unload there are lots of children leftover */
- device_delete_all_children(dev);
-
- if (sc->sc_irq_res && sc->sc_intr_hdl) {
- /*
- * only call at91_udp_uninit() after at91_udp_init()
- */
- uss820dci_uninit(sc);
-
- err = bus_teardown_intr(dev, sc->sc_irq_res,
- sc->sc_intr_hdl);
- sc->sc_intr_hdl = NULL;
- }
- if (sc->sc_irq_res) {
- bus_release_resource(dev, SYS_RES_IRQ, 0,
- sc->sc_irq_res);
- sc->sc_irq_res = NULL;
- }
- if (sc->sc_io_res) {
- bus_release_resource(dev, SYS_RES_IOPORT, 0,
- sc->sc_io_res);
- sc->sc_io_res = NULL;
- }
- usb2_config_td_unsetup(&sc->sc_config_td);
-
- usb2_bus_mem_free_all(&sc->sc_bus, NULL);
-
- return (0);
-}
OpenPOWER on IntegriCloud