MFp4 //depot/projects/usb@159922
Refactor how we interface with the root HUB. This cuts around 1200 lines of code totally and saves one thread per USB bus. Submitted by: Hans Petter Selasky
This commit is contained in:
parent
4eae601ebd
commit
3930731567
@ -88,8 +88,6 @@ 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;
|
||||
@ -97,11 +95,8 @@ 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;
|
||||
static void at91dci_root_intr(struct at91dci_softc *sc);
|
||||
|
||||
/*
|
||||
* NOTE: Some of the bits in the CSR register have inverse meaning so
|
||||
@ -256,10 +251,8 @@ at91dci_pull_down(struct at91dci_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
at91dci_wakeup_peer(struct usb2_xfer *xfer)
|
||||
at91dci_wakeup_peer(struct at91dci_softc *sc)
|
||||
{
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (!(sc->sc_flags.status_suspend)) {
|
||||
return;
|
||||
}
|
||||
@ -736,9 +729,7 @@ at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on)
|
||||
sc->sc_flags.status_vbus = 1;
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&at91dci_root_intr_done);
|
||||
at91dci_root_intr(sc);
|
||||
}
|
||||
} else {
|
||||
if (sc->sc_flags.status_vbus) {
|
||||
@ -749,9 +740,7 @@ at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on)
|
||||
sc->sc_flags.change_connect = 1;
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&at91dci_root_intr_done);
|
||||
at91dci_root_intr(sc);
|
||||
}
|
||||
}
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
@ -828,9 +817,7 @@ at91dci_interrupt(struct at91dci_softc *sc)
|
||||
}
|
||||
}
|
||||
/* complete root HUB interrupt endpoint */
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&at91dci_root_intr_done);
|
||||
at91dci_root_intr(sc);
|
||||
}
|
||||
/* check for any endpoint interrupts */
|
||||
|
||||
@ -1070,31 +1057,17 @@ at91dci_start_standard_chain(struct usb2_xfer *xfer)
|
||||
}
|
||||
|
||||
static void
|
||||
at91dci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
at91dci_root_intr(struct at91dci_softc *sc)
|
||||
{
|
||||
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;
|
||||
uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
|
||||
sizeof(sc->sc_hub_idata));
|
||||
}
|
||||
|
||||
static usb2_error_t
|
||||
@ -1488,7 +1461,6 @@ at91dci_do_poll(struct usb2_bus *bus)
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
at91dci_interrupt_poll(sc);
|
||||
at91dci_root_ctrl_poll(sc);
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
@ -1696,31 +1668,9 @@ struct usb2_pipe_methods at91dci_device_isoc_fs_methods =
|
||||
/*------------------------------------------------------------------------*
|
||||
* at91dci root control support
|
||||
*------------------------------------------------------------------------*
|
||||
* simulate a hardware HUB by handling
|
||||
* all the necessary requests
|
||||
* 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,
|
||||
@ -1765,7 +1715,6 @@ static const struct at91dci_config_desc at91dci_confd = {
|
||||
.bInterfaceSubClass = UISUBCLASS_HUB,
|
||||
.bInterfaceProtocol = UIPROTO_HSHUBSTT,
|
||||
},
|
||||
|
||||
.endpd = {
|
||||
.bLength = sizeof(struct usb2_endpoint_descriptor),
|
||||
.bDescriptorType = UDESC_ENDPOINT,
|
||||
@ -1805,44 +1754,15 @@ 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)
|
||||
at91dci_roothub_exec(struct usb2_bus *bus)
|
||||
{
|
||||
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);
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(bus);
|
||||
struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
|
||||
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;
|
||||
@ -2101,7 +2021,7 @@ at91dci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
|
||||
switch (value) {
|
||||
case UHF_PORT_SUSPEND:
|
||||
at91dci_wakeup_peer(xfer);
|
||||
at91dci_wakeup_peer(sc);
|
||||
break;
|
||||
|
||||
case UHF_PORT_ENABLE:
|
||||
@ -2224,67 +2144,6 @@ at91dci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
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)
|
||||
{
|
||||
@ -2411,24 +2270,7 @@ at91dci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *ede
|
||||
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->device_index != sc->sc_rt_addr) {
|
||||
|
||||
if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
|
||||
/* not supported */
|
||||
@ -2466,5 +2308,5 @@ struct usb2_bus_methods at91dci_bus_methods =
|
||||
.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,
|
||||
.roothub_exec = &at91dci_roothub_exec,
|
||||
};
|
||||
|
@ -204,8 +204,6 @@ 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;
|
||||
|
@ -81,8 +81,6 @@ 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;
|
||||
@ -90,11 +88,8 @@ 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;
|
||||
static void atmegadci_root_intr(struct atmegadci_softc *sc);
|
||||
|
||||
/*
|
||||
* Here is a list of what the chip supports:
|
||||
@ -201,9 +196,8 @@ atmegadci_pull_down(struct atmegadci_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
atmegadci_wakeup_peer(struct usb2_xfer *xfer)
|
||||
atmegadci_wakeup_peer(struct atmegadci_softc *sc)
|
||||
{
|
||||
struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
|
||||
uint8_t temp;
|
||||
|
||||
if (!sc->sc_flags.status_suspend) {
|
||||
@ -625,8 +619,7 @@ atmegadci_vbus_interrupt(struct atmegadci_softc *sc, uint8_t is_on)
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&atmegadci_root_intr_done);
|
||||
atmegadci_root_intr(sc);
|
||||
}
|
||||
} else {
|
||||
if (sc->sc_flags.status_vbus) {
|
||||
@ -638,8 +631,7 @@ atmegadci_vbus_interrupt(struct atmegadci_softc *sc, uint8_t is_on)
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&atmegadci_root_intr_done);
|
||||
atmegadci_root_intr(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -676,8 +668,7 @@ atmegadci_interrupt(struct atmegadci_softc *sc)
|
||||
ATMEGA_UDINT_EORSTE);
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&atmegadci_root_intr_done);
|
||||
atmegadci_root_intr(sc);
|
||||
}
|
||||
/*
|
||||
* If resume and suspend is set at the same time we interpret
|
||||
@ -699,8 +690,7 @@ atmegadci_interrupt(struct atmegadci_softc *sc)
|
||||
ATMEGA_UDINT_EORSTE);
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&atmegadci_root_intr_done);
|
||||
atmegadci_root_intr(sc);
|
||||
}
|
||||
} else if (status & ATMEGA_UDINT_SUSPI) {
|
||||
|
||||
@ -717,8 +707,7 @@ atmegadci_interrupt(struct atmegadci_softc *sc)
|
||||
ATMEGA_UDINT_EORSTE);
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&atmegadci_root_intr_done);
|
||||
atmegadci_root_intr(sc);
|
||||
}
|
||||
}
|
||||
/* check VBUS */
|
||||
@ -953,32 +942,18 @@ atmegadci_start_standard_chain(struct usb2_xfer *xfer)
|
||||
}
|
||||
|
||||
static void
|
||||
atmegadci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
atmegadci_root_intr(struct atmegadci_softc *sc)
|
||||
{
|
||||
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;
|
||||
}
|
||||
uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
|
||||
sizeof(sc->sc_hub_idata));
|
||||
}
|
||||
|
||||
static usb2_error_t
|
||||
atmegadci_standard_done_sub(struct usb2_xfer *xfer)
|
||||
@ -1363,7 +1338,6 @@ atmegadci_do_poll(struct usb2_bus *bus)
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
atmegadci_interrupt_poll(sc);
|
||||
atmegadci_root_ctrl_poll(sc);
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
@ -1575,27 +1549,9 @@ struct usb2_pipe_methods atmegadci_device_isoc_fs_methods =
|
||||
/*------------------------------------------------------------------------*
|
||||
* at91dci root control support
|
||||
*------------------------------------------------------------------------*
|
||||
* simulate a hardware HUB by handling
|
||||
* all the necessary requests
|
||||
* 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:
|
||||
*/
|
||||
@ -1644,7 +1600,6 @@ static const struct atmegadci_config_desc atmegadci_confd = {
|
||||
.bInterfaceSubClass = UISUBCLASS_HUB,
|
||||
.bInterfaceProtocol = UIPROTO_HSHUBSTT,
|
||||
},
|
||||
|
||||
.endpd = {
|
||||
.bLength = sizeof(struct usb2_endpoint_descriptor),
|
||||
.bDescriptorType = UDESC_ENDPOINT,
|
||||
@ -1684,45 +1639,16 @@ 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)
|
||||
atmegadci_roothub_exec(struct usb2_bus *bus)
|
||||
{
|
||||
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);
|
||||
struct atmegadci_softc *sc = ATMEGA_BUS2SC(bus);
|
||||
struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
uint8_t temp;
|
||||
|
||||
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;
|
||||
@ -1981,7 +1907,7 @@ atmegadci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
|
||||
switch (value) {
|
||||
case UHF_PORT_SUSPEND:
|
||||
atmegadci_wakeup_peer(xfer);
|
||||
atmegadci_wakeup_peer(sc);
|
||||
break;
|
||||
|
||||
case UHF_PORT_ENABLE:
|
||||
@ -2129,67 +2055,6 @@ atmegadci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
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)
|
||||
{
|
||||
@ -2313,24 +2178,7 @@ atmegadci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *e
|
||||
edesc->bEndpointAddress, udev->flags.usb2_mode,
|
||||
sc->sc_rt_addr, udev->device_index);
|
||||
|
||||
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->device_index != sc->sc_rt_addr) {
|
||||
|
||||
if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
|
||||
/* not supported */
|
||||
@ -2368,5 +2216,5 @@ struct usb2_bus_methods atmegadci_bus_methods =
|
||||
.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,
|
||||
.roothub_exec = &atmegadci_roothub_exec,
|
||||
};
|
||||
|
@ -34,10 +34,6 @@
|
||||
|
||||
#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 */
|
||||
|
||||
@ -241,8 +237,6 @@ 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;
|
||||
@ -251,11 +245,10 @@ struct atmegadci_softc {
|
||||
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 */
|
||||
|
@ -93,17 +93,12 @@ 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;
|
||||
static void ehci_root_intr(ehci_softc_t *sc);
|
||||
|
||||
struct ehci_std_temp {
|
||||
ehci_softc_t *sc;
|
||||
@ -1415,8 +1410,7 @@ ehci_pcd_enable(ehci_softc_t *sc)
|
||||
/* acknowledge any PCD interrupt */
|
||||
EOWRITE4(sc, EHCI_USBSTS, EHCI_STS_PCD);
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&ehci_root_intr_done);
|
||||
ehci_root_intr(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1486,8 +1480,7 @@ ehci_interrupt(ehci_softc_t *sc)
|
||||
sc->sc_eintrs &= ~EHCI_STS_PCD;
|
||||
EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&ehci_root_intr_done);
|
||||
ehci_root_intr(sc);
|
||||
|
||||
/* do not allow RHSC interrupts > 1 per second */
|
||||
usb2_callout_reset(&sc->sc_tmo_pcd, hz,
|
||||
@ -1531,7 +1524,6 @@ ehci_do_poll(struct usb2_bus *bus)
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
ehci_interrupt_poll(sc);
|
||||
ehci_root_ctrl_poll(sc);
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
@ -1979,28 +1971,15 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
|
||||
}
|
||||
|
||||
static void
|
||||
ehci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
ehci_root_intr(ehci_softc_t *sc)
|
||||
{
|
||||
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));
|
||||
memset(sc->sc_hub_idata, 0, sizeof(sc->sc_hub_idata));
|
||||
|
||||
/* set bits */
|
||||
m = (sc->sc_noport + 1);
|
||||
@ -2014,8 +1993,8 @@ ehci_root_intr_done(struct usb2_xfer *xfer,
|
||||
DPRINTF("port %d changed\n", i);
|
||||
}
|
||||
}
|
||||
done:
|
||||
return;
|
||||
uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
|
||||
sizeof(sc->sc_hub_idata));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2932,31 +2911,9 @@ struct usb2_pipe_methods ehci_device_isoc_hs_methods =
|
||||
/*------------------------------------------------------------------------*
|
||||
* ehci root control support
|
||||
*------------------------------------------------------------------------*
|
||||
* simulate a hardware hub by handling
|
||||
* all the necessary requests
|
||||
* 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 =
|
||||
{
|
||||
@ -2997,7 +2954,6 @@ static const struct ehci_config_desc ehci_confd = {
|
||||
.bmAttributes = UC_SELF_POWERED,
|
||||
.bMaxPower = 0 /* max power */
|
||||
},
|
||||
|
||||
.ifcd = {
|
||||
.bLength = sizeof(struct usb2_interface_descriptor),
|
||||
.bDescriptorType = UDESC_INTERFACE,
|
||||
@ -3007,7 +2963,6 @@ static const struct ehci_config_desc ehci_confd = {
|
||||
.bInterfaceProtocol = UIPROTO_HSHUBSTT,
|
||||
0
|
||||
},
|
||||
|
||||
.endpd = {
|
||||
.bLength = sizeof(struct usb2_endpoint_descriptor),
|
||||
.bDescriptorType = UDESC_ENDPOINT,
|
||||
@ -3044,34 +2999,10 @@ ehci_disown(ehci_softc_t *sc, uint16_t index, uint8_t lowspeed)
|
||||
}
|
||||
|
||||
static void
|
||||
ehci_root_ctrl_enter(struct usb2_xfer *xfer)
|
||||
ehci_roothub_exec(struct usb2_bus *bus)
|
||||
{
|
||||
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);
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(bus);
|
||||
struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
|
||||
char *ptr;
|
||||
uint32_t port;
|
||||
uint32_t v;
|
||||
@ -3082,13 +3013,6 @@ ehci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
|
||||
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;
|
||||
@ -3461,67 +3385,6 @@ ehci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
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)
|
||||
{
|
||||
@ -3794,19 +3657,8 @@ ehci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
|
||||
/* 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->device_index != sc->sc_addr) {
|
||||
|
||||
if ((udev->speed != USB_SPEED_HIGH) &&
|
||||
((udev->hs_hub_addr == 0) ||
|
||||
(udev->hs_port_no == 0) ||
|
||||
@ -3964,5 +3816,5 @@ struct usb2_bus_methods ehci_bus_methods =
|
||||
.device_resume = ehci_device_resume,
|
||||
.device_suspend = ehci_device_suspend,
|
||||
.set_hw_power = ehci_set_hw_power,
|
||||
.roothub_exec = ehci_root_ctrl_task,
|
||||
.roothub_exec = ehci_roothub_exec,
|
||||
};
|
||||
|
@ -457,8 +457,6 @@ typedef struct ehci_softc {
|
||||
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;
|
||||
|
@ -80,8 +80,6 @@ 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;
|
||||
@ -91,12 +89,9 @@ 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;
|
||||
static void musbotg_root_intr(struct musbotg_softc *);
|
||||
|
||||
/*
|
||||
* Here is a configuration that the chip supports.
|
||||
@ -201,9 +196,8 @@ musbotg_pull_down(struct musbotg_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
musbotg_wakeup_peer(struct usb2_xfer *xfer)
|
||||
musbotg_wakeup_peer(struct musbotg_softc *sc)
|
||||
{
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
uint8_t temp;
|
||||
|
||||
if (!(sc->sc_flags.status_suspend)) {
|
||||
@ -965,9 +959,7 @@ musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on)
|
||||
sc->sc_flags.status_vbus = 1;
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&musbotg_root_intr_done);
|
||||
musbotg_root_intr(sc);
|
||||
}
|
||||
} else {
|
||||
if (sc->sc_flags.status_vbus) {
|
||||
@ -978,9 +970,7 @@ musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on)
|
||||
sc->sc_flags.change_connect = 1;
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&musbotg_root_intr_done);
|
||||
musbotg_root_intr(sc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1074,9 +1064,7 @@ musbotg_interrupt(struct musbotg_softc *sc)
|
||||
}
|
||||
}
|
||||
/* complete root HUB interrupt endpoint */
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&musbotg_root_intr_done);
|
||||
musbotg_root_intr(sc);
|
||||
}
|
||||
/* check for any endpoint interrupts */
|
||||
|
||||
@ -1320,31 +1308,17 @@ musbotg_start_standard_chain(struct usb2_xfer *xfer)
|
||||
}
|
||||
|
||||
static void
|
||||
musbotg_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
musbotg_root_intr(struct musbotg_softc *sc)
|
||||
{
|
||||
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;
|
||||
uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
|
||||
sizeof(sc->sc_hub_idata));
|
||||
}
|
||||
|
||||
static usb2_error_t
|
||||
@ -1887,7 +1861,6 @@ musbotg_do_poll(struct usb2_bus *bus)
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
musbotg_interrupt_poll(sc);
|
||||
musbotg_root_ctrl_poll(sc);
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
@ -2102,29 +2075,8 @@ struct usb2_pipe_methods musbotg_device_isoc_methods =
|
||||
/*------------------------------------------------------------------------*
|
||||
* musbotg root control support
|
||||
*------------------------------------------------------------------------*
|
||||
* simulate a hardware HUB by handling
|
||||
* all the necessary requests
|
||||
* 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),
|
||||
@ -2170,7 +2122,6 @@ static const struct musbotg_config_desc musbotg_confd = {
|
||||
.bInterfaceSubClass = UISUBCLASS_HUB,
|
||||
.bInterfaceProtocol = UIPROTO_HSHUBSTT,
|
||||
},
|
||||
|
||||
.endpd = {
|
||||
.bLength = sizeof(struct usb2_endpoint_descriptor),
|
||||
.bDescriptorType = UDESC_ENDPOINT,
|
||||
@ -2211,44 +2162,15 @@ 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)
|
||||
musbotg_roothub_exec(struct usb2_bus *bus)
|
||||
{
|
||||
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);
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(bus);
|
||||
struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
|
||||
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;
|
||||
@ -2507,7 +2429,7 @@ musbotg_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
|
||||
switch (value) {
|
||||
case UHF_PORT_SUSPEND:
|
||||
musbotg_wakeup_peer(xfer);
|
||||
musbotg_wakeup_peer(sc);
|
||||
break;
|
||||
|
||||
case UHF_PORT_ENABLE:
|
||||
@ -2633,67 +2555,6 @@ musbotg_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
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)
|
||||
{
|
||||
@ -2818,24 +2679,7 @@ musbotg_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *ede
|
||||
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->device_index != sc->sc_rt_addr) {
|
||||
|
||||
if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
|
||||
/* not supported */
|
||||
@ -2874,5 +2718,5 @@ struct usb2_bus_methods musbotg_bus_methods =
|
||||
.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,
|
||||
.roothub_exec = &musbotg_roothub_exec,
|
||||
};
|
||||
|
@ -363,8 +363,6 @@ struct musbotg_flags {
|
||||
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];
|
||||
|
@ -93,17 +93,12 @@ 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);
|
||||
static void ohci_root_intr(ohci_softc_t *sc);
|
||||
|
||||
struct ohci_std_temp {
|
||||
struct usb2_page_cache *pc;
|
||||
@ -1104,8 +1099,7 @@ ohci_rhsc_enable(ohci_softc_t *sc)
|
||||
/* acknowledge any RHSC interrupt */
|
||||
OWRITE4(sc, OHCI_INTERRUPT_STATUS, OHCI_RHSC);
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&ohci_root_intr_done);
|
||||
ohci_root_intr(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1219,8 +1213,7 @@ ohci_interrupt(ohci_softc_t *sc)
|
||||
sc->sc_eintrs &= ~OHCI_RHSC;
|
||||
OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_RHSC);
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&ohci_root_intr_done);
|
||||
ohci_root_intr(sc);
|
||||
|
||||
/* do not allow RHSC interrupts > 1 per second */
|
||||
usb2_callout_reset(&sc->sc_tmo_rhsc, hz,
|
||||
@ -1265,7 +1258,6 @@ ohci_do_poll(struct usb2_bus *bus)
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
ohci_interrupt_poll(sc);
|
||||
ohci_root_ctrl_poll(sc);
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
@ -1618,33 +1610,20 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
|
||||
}
|
||||
|
||||
static void
|
||||
ohci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
ohci_root_intr(ohci_softc_t *sc)
|
||||
{
|
||||
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));
|
||||
memset(sc->sc_hub_idata, 0, sizeof(sc->sc_hub_idata));
|
||||
|
||||
hstatus = OREAD4(sc, OHCI_RH_STATUS);
|
||||
DPRINTF("sc=%p xfer=%p hstatus=0x%08x\n",
|
||||
sc, xfer, hstatus);
|
||||
DPRINTF("sc=%p hstatus=0x%08x\n",
|
||||
sc, hstatus);
|
||||
|
||||
/* set bits */
|
||||
m = (sc->sc_noport + 1);
|
||||
@ -1658,8 +1637,9 @@ ohci_root_intr_done(struct usb2_xfer *xfer,
|
||||
DPRINTF("port %d changed\n", i);
|
||||
}
|
||||
}
|
||||
done:
|
||||
return;
|
||||
|
||||
uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
|
||||
sizeof(sc->sc_hub_idata));
|
||||
}
|
||||
|
||||
/* NOTE: "done" can be run two times in a row,
|
||||
@ -2074,30 +2054,9 @@ struct usb2_pipe_methods ohci_device_isoc_methods =
|
||||
/*------------------------------------------------------------------------*
|
||||
* ohci root control support
|
||||
*------------------------------------------------------------------------*
|
||||
* simulate a hardware hub by handling
|
||||
* all the necessary requests
|
||||
* 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 =
|
||||
{
|
||||
@ -2126,7 +2085,6 @@ struct ohci_config_desc ohci_confd =
|
||||
.bmAttributes = UC_SELF_POWERED,
|
||||
.bMaxPower = 0, /* max power */
|
||||
},
|
||||
|
||||
.ifcd = {
|
||||
.bLength = sizeof(struct usb2_interface_descriptor),
|
||||
.bDescriptorType = UDESC_INTERFACE,
|
||||
@ -2135,7 +2093,6 @@ struct ohci_config_desc ohci_confd =
|
||||
.bInterfaceSubClass = UISUBCLASS_HUB,
|
||||
.bInterfaceProtocol = UIPROTO_FSHUB,
|
||||
},
|
||||
|
||||
.endpd = {
|
||||
.bLength = sizeof(struct usb2_endpoint_descriptor),
|
||||
.bDescriptorType = UDESC_ENDPOINT,
|
||||
@ -2159,32 +2116,10 @@ struct usb2_hub_descriptor ohci_hubd =
|
||||
};
|
||||
|
||||
static void
|
||||
ohci_root_ctrl_enter(struct usb2_xfer *xfer)
|
||||
ohci_roothub_exec(struct usb2_bus *bus)
|
||||
{
|
||||
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);
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(bus);
|
||||
struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
|
||||
char *ptr;
|
||||
uint32_t port;
|
||||
uint32_t v;
|
||||
@ -2194,13 +2129,6 @@ ohci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
|
||||
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;
|
||||
@ -2473,67 +2401,6 @@ ohci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
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)
|
||||
{
|
||||
@ -2713,19 +2580,7 @@ ohci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
|
||||
/* 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 {
|
||||
if (udev->device_index != sc->sc_addr) {
|
||||
switch (edesc->bmAttributes & UE_XFERTYPE) {
|
||||
case UE_CONTROL:
|
||||
pipe->methods = &ohci_device_ctrl_methods;
|
||||
@ -2884,5 +2739,5 @@ struct usb2_bus_methods ohci_bus_methods =
|
||||
.device_resume = ohci_device_resume,
|
||||
.device_suspend = ohci_device_suspend,
|
||||
.set_hw_power = ohci_set_hw_power,
|
||||
.roothub_exec = ohci_root_ctrl_task,
|
||||
.roothub_exec = ohci_roothub_exec,
|
||||
};
|
||||
|
@ -322,8 +322,6 @@ typedef struct ohci_softc {
|
||||
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;
|
||||
|
@ -132,16 +132,13 @@ 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 *);
|
||||
static void uhci_root_intr(uhci_softc_t *sc);
|
||||
|
||||
void
|
||||
uhci_iterate_hw_softc(struct usb2_bus *bus, usb2_bus_mem_sub_cb_t *cb)
|
||||
@ -317,6 +314,13 @@ uhci_reset(uhci_softc_t *sc)
|
||||
UWRITE4(sc, UHCI_FLBASEADDR, buf_res.physaddr);
|
||||
UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum);
|
||||
UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof);
|
||||
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
|
||||
/* stop root interrupt */
|
||||
usb2_callout_drain(&sc->sc_root_intr);
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -358,7 +362,8 @@ uhci_start(uhci_softc_t *sc)
|
||||
"cannot start HC controller\n");
|
||||
|
||||
done:
|
||||
return;
|
||||
/* start root interrupt */
|
||||
uhci_root_intr(sc);
|
||||
}
|
||||
|
||||
static struct uhci_qh *
|
||||
@ -408,12 +413,13 @@ uhci_init(uhci_softc_t *sc)
|
||||
|
||||
DPRINTF("start\n");
|
||||
|
||||
usb2_callout_init_mtx(&sc->sc_root_intr, &sc->sc_bus.bus_mtx, 0);
|
||||
|
||||
#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 */
|
||||
|
||||
@ -1505,7 +1511,6 @@ uhci_do_poll(struct usb2_bus *bus)
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
uhci_interrupt_poll(sc);
|
||||
uhci_root_ctrl_poll(sc);
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
@ -2307,31 +2312,9 @@ struct usb2_pipe_methods uhci_device_isoc_methods =
|
||||
/*------------------------------------------------------------------------*
|
||||
* uhci root control support
|
||||
*------------------------------------------------------------------------*
|
||||
* simulate a hardware hub by handling
|
||||
* all the necessary requests
|
||||
* 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 =
|
||||
{
|
||||
@ -2358,7 +2341,6 @@ static const struct uhci_config_desc uhci_confd = {
|
||||
.bmAttributes = UC_SELF_POWERED,
|
||||
.bMaxPower = 0 /* max power */
|
||||
},
|
||||
|
||||
.ifcd = {
|
||||
.bLength = sizeof(struct usb2_interface_descriptor),
|
||||
.bDescriptorType = UDESC_INTERFACE,
|
||||
@ -2367,7 +2349,6 @@ static const struct uhci_config_desc uhci_confd = {
|
||||
.bInterfaceSubClass = UISUBCLASS_HUB,
|
||||
.bInterfaceProtocol = UIPROTO_FSHUB,
|
||||
},
|
||||
|
||||
.endpd = {
|
||||
.bLength = sizeof(struct usb2_endpoint_descriptor),
|
||||
.bDescriptorType = UDESC_ENDPOINT,
|
||||
@ -2511,34 +2492,10 @@ uhci_portreset(uhci_softc_t *sc, uint16_t index)
|
||||
}
|
||||
|
||||
static void
|
||||
uhci_root_ctrl_enter(struct usb2_xfer *xfer)
|
||||
uhci_roothub_exec(struct usb2_bus *bus)
|
||||
{
|
||||
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);
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(bus);
|
||||
struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
|
||||
char *ptr;
|
||||
uint16_t x;
|
||||
uint16_t port;
|
||||
@ -2549,13 +2506,6 @@ uhci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
|
||||
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;
|
||||
@ -2856,92 +2806,13 @@ uhci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
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
|
||||
* 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)
|
||||
uhci_root_intr(uhci_softc_t *sc)
|
||||
{
|
||||
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);
|
||||
@ -2956,27 +2827,17 @@ uhci_root_intr_check(void *arg)
|
||||
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);
|
||||
|
||||
/* restart timer */
|
||||
usb2_callout_reset(&sc->sc_root_intr, hz,
|
||||
(void *)&uhci_root_intr, sc);
|
||||
|
||||
if (sc->sc_hub_idata[0] != 0) {
|
||||
uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
|
||||
sizeof(sc->sc_hub_idata));
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -3188,19 +3049,7 @@ uhci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
|
||||
/* 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 {
|
||||
if (udev->device_index != sc->sc_addr) {
|
||||
switch (edesc->bmAttributes & UE_XFERTYPE) {
|
||||
case UE_CONTROL:
|
||||
pipe->methods = &uhci_device_ctrl_methods;
|
||||
@ -3374,5 +3223,5 @@ struct usb2_bus_methods uhci_bus_methods =
|
||||
.device_resume = uhci_device_resume,
|
||||
.device_suspend = uhci_device_suspend,
|
||||
.set_hw_power = uhci_set_hw_power,
|
||||
.roothub_exec = uhci_root_ctrl_task,
|
||||
.roothub_exec = uhci_roothub_exec,
|
||||
};
|
||||
|
@ -271,19 +271,19 @@ 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_callout 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 */
|
||||
/* pointer to last TD for isochronous */
|
||||
struct uhci_td *sc_isoc_p_last[UHCI_VFRAMELIST_COUNT];
|
||||
/* pointer to last QH for interrupt */
|
||||
struct uhci_qh *sc_intr_p_last[UHCI_IFRAMELIST_COUNT];
|
||||
/* pointer to last QH for low speed control */
|
||||
struct uhci_qh *sc_ls_ctl_p_last;
|
||||
/* pointer to last QH for full speed control */
|
||||
struct uhci_qh *sc_fs_ctl_p_last;
|
||||
/* pointer to last QH for bulk */
|
||||
struct uhci_qh *sc_bulk_p_last;
|
||||
struct uhci_qh *sc_reclaim_qh_p;
|
||||
struct uhci_qh *sc_last_qh_p;
|
||||
struct uhci_td *sc_last_td_p;
|
||||
|
@ -49,7 +49,6 @@ 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_roothub(struct usb2_proc_msg *pm);
|
||||
|
||||
/* static variables */
|
||||
|
||||
@ -166,10 +165,6 @@ usb2_detach(device_t dev)
|
||||
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);
|
||||
@ -403,12 +398,7 @@ usb2_attach_sub(device_t dev, struct usb2_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 */
|
||||
/* Create USB explore and callback processes */
|
||||
|
||||
if (usb2_proc_create(&bus->giant_callback_proc,
|
||||
&bus->bus_mtx, pname, USB_PRI_MED)) {
|
||||
@ -418,10 +408,6 @@ usb2_attach_sub(device_t dev, struct usb2_bus *bus)
|
||||
&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 "
|
||||
@ -597,38 +583,3 @@ usb2_bus_mem_free_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb)
|
||||
|
||||
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 */
|
||||
}
|
||||
}
|
||||
|
@ -77,8 +77,6 @@ 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;
|
||||
@ -86,14 +84,11 @@ 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;
|
||||
static void uss820dci_root_intr(struct uss820dci_softc *);
|
||||
|
||||
/*
|
||||
* Here is a list of what the USS820D chip can support. The main
|
||||
@ -786,9 +781,7 @@ uss820dci_interrupt(struct uss820dci_softc *sc)
|
||||
DPRINTF("real bus interrupt 0x%02x\n", ssr);
|
||||
|
||||
/* complete root HUB interrupt endpoint */
|
||||
|
||||
usb2_sw_transfer(&sc->sc_root_intr,
|
||||
&uss820dci_root_intr_done);
|
||||
uss820dci_root_intr(sc);
|
||||
}
|
||||
}
|
||||
/* acknowledge all SBI interrupts */
|
||||
@ -1047,31 +1040,17 @@ uss820dci_start_standard_chain(struct usb2_xfer *xfer)
|
||||
}
|
||||
|
||||
static void
|
||||
uss820dci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
uss820dci_root_intr(struct uss820dci_softc *sc)
|
||||
{
|
||||
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;
|
||||
uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
|
||||
sizeof(sc->sc_hub_idata));
|
||||
}
|
||||
|
||||
static usb2_error_t
|
||||
@ -1525,7 +1504,6 @@ uss820dci_do_poll(struct usb2_bus *bus)
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
uss820dci_interrupt_poll(sc);
|
||||
uss820dci_root_ctrl_poll(sc);
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
@ -1733,31 +1711,9 @@ struct usb2_pipe_methods uss820dci_device_isoc_fs_methods =
|
||||
/*------------------------------------------------------------------------*
|
||||
* at91dci root control support
|
||||
*------------------------------------------------------------------------*
|
||||
* simulate a hardware HUB by handling
|
||||
* all the necessary requests
|
||||
* 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,
|
||||
@ -1842,44 +1798,15 @@ 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)
|
||||
uss820dci_roothub_exec(struct usb2_bus *bus)
|
||||
{
|
||||
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);
|
||||
struct uss820dci_softc *sc = USS820_DCI_BUS2SC(bus);
|
||||
struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
|
||||
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;
|
||||
@ -2252,67 +2179,6 @@ uss820dci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
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)
|
||||
{
|
||||
@ -2452,24 +2318,7 @@ uss820dci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *e
|
||||
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->device_index != sc->sc_rt_addr) {
|
||||
|
||||
if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
|
||||
/* not supported */
|
||||
@ -2507,5 +2356,5 @@ struct usb2_bus_methods uss820dci_bus_methods =
|
||||
.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,
|
||||
.roothub_exec = &uss820dci_roothub_exec,
|
||||
};
|
||||
|
@ -345,8 +345,6 @@ 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;
|
||||
|
@ -44,6 +44,17 @@ struct usb2_bus_stat {
|
||||
uint32_t uds_requests[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure is used to keep the state of a standard
|
||||
* root transfer.
|
||||
*/
|
||||
struct usb2_sw_transfer {
|
||||
struct usb2_device_request req;
|
||||
uint8_t *ptr;
|
||||
uint16_t len;
|
||||
usb2_error_t err;
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure defines an USB BUS. There is one USB BUS
|
||||
* for every Host or Device controller.
|
||||
@ -52,7 +63,7 @@ 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 usb2_sw_transfer roothub_req;
|
||||
struct root_hold_token *bus_roothold;
|
||||
/*
|
||||
* There are two callback processes. One for Giant locked
|
||||
@ -64,7 +75,6 @@ struct usb2_bus {
|
||||
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:
|
||||
*/
|
||||
|
@ -190,7 +190,6 @@ struct usb2_temp_setup {
|
||||
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);
|
||||
|
@ -114,7 +114,7 @@
|
||||
|
||||
/*
|
||||
* The following macro defines if USB transaction translator support
|
||||
* shall be compiled for the USB HUB and USB controller drivers.
|
||||
* shall be supported for the USB HUB and USB controller drivers.
|
||||
*/
|
||||
#ifndef USB_HAVE_TT_SUPPORT
|
||||
#define USB_HAVE_TT_SUPPORT 1
|
||||
@ -122,12 +122,20 @@
|
||||
|
||||
/*
|
||||
* The following macro defines if the USB power daemon shall
|
||||
* be compiled for the USB core.
|
||||
* be supported in the USB core.
|
||||
*/
|
||||
#ifndef USB_HAVE_POWERD
|
||||
#define USB_HAVE_POWERD 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following macro defines if the USB autoinstall detection shall
|
||||
* be supported in the USB core.
|
||||
*/
|
||||
#ifndef USB_HAVE_MSCTEST
|
||||
#define USB_HAVE_MSCTEST 1
|
||||
#endif
|
||||
|
||||
#ifndef USB_TD_GET_PROC
|
||||
#define USB_TD_GET_PROC(td) (td)->td_proc
|
||||
#endif
|
||||
|
@ -305,16 +305,16 @@ usb2_init_pipe(struct usb2_device *udev, uint8_t iface_index,
|
||||
|
||||
(methods->pipe_init) (udev, edesc, pipe);
|
||||
|
||||
/* check for invalid pipe */
|
||||
if (pipe->methods == NULL)
|
||||
return;
|
||||
|
||||
/* initialise USB pipe structure */
|
||||
pipe->edesc = edesc;
|
||||
pipe->iface_index = iface_index;
|
||||
TAILQ_INIT(&pipe->pipe_q.head);
|
||||
pipe->pipe_q.command = &usb2_pipe_start;
|
||||
|
||||
/* the pipe is not supported by the hardware */
|
||||
if (pipe->methods == NULL)
|
||||
return;
|
||||
|
||||
/* clear stall, if any */
|
||||
if (methods->clear_stall != NULL) {
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
|
@ -62,10 +62,12 @@ SYSCTL_INT(_hw_usb2_uhub, OID_AUTO, debug, CTLFLAG_RW, &uhub_debug, 0,
|
||||
"Debug level");
|
||||
#endif
|
||||
|
||||
#if USB_HAVE_POWERD
|
||||
static int usb2_power_timeout = 30; /* seconds */
|
||||
|
||||
SYSCTL_INT(_hw_usb2, OID_AUTO, power_timeout, CTLFLAG_RW,
|
||||
&usb2_power_timeout, 0, "USB power timeout");
|
||||
#endif
|
||||
|
||||
struct uhub_current_state {
|
||||
uint16_t port_change;
|
||||
@ -123,23 +125,24 @@ static const struct usb2_config uhub_config[UHUB_N_TRANSFER] = {
|
||||
*/
|
||||
static devclass_t uhub_devclass;
|
||||
|
||||
static driver_t uhub_driver =
|
||||
{
|
||||
static device_method_t uhub_methods[] = {
|
||||
DEVMETHOD(device_probe, uhub_probe),
|
||||
DEVMETHOD(device_attach, uhub_attach),
|
||||
DEVMETHOD(device_detach, uhub_detach),
|
||||
|
||||
DEVMETHOD(device_suspend, uhub_suspend),
|
||||
DEVMETHOD(device_resume, uhub_resume),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
|
||||
DEVMETHOD(bus_child_location_str, uhub_child_location_string),
|
||||
DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_string),
|
||||
DEVMETHOD(bus_driver_added, uhub_driver_added),
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static driver_t uhub_driver = {
|
||||
.name = "uhub",
|
||||
.methods = (device_method_t[]){
|
||||
DEVMETHOD(device_probe, uhub_probe),
|
||||
DEVMETHOD(device_attach, uhub_attach),
|
||||
DEVMETHOD(device_detach, uhub_detach),
|
||||
|
||||
DEVMETHOD(device_suspend, uhub_suspend),
|
||||
DEVMETHOD(device_resume, uhub_resume),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
|
||||
DEVMETHOD(bus_child_location_str, uhub_child_location_string),
|
||||
DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_string),
|
||||
DEVMETHOD(bus_driver_added, uhub_driver_added),
|
||||
{0, 0}
|
||||
},
|
||||
.methods = uhub_methods,
|
||||
.size = sizeof(struct uhub_softc)
|
||||
};
|
||||
|
||||
@ -500,6 +503,21 @@ uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno)
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* uhub_root_interrupt
|
||||
*
|
||||
* This function is called when a Root HUB interrupt has
|
||||
* happened. "ptr" and "len" makes up the Root HUB interrupt
|
||||
* packet. This function is called having the "bus_mtx" locked.
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
uhub_root_intr(struct usb2_bus *bus, const uint8_t *ptr, uint8_t len)
|
||||
{
|
||||
USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
|
||||
|
||||
usb2_needs_explore(bus, 0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* uhub_explore
|
||||
*
|
||||
@ -731,8 +749,14 @@ uhub_attach(device_t dev)
|
||||
|
||||
/* set up interrupt pipe */
|
||||
iface_index = 0;
|
||||
err = usb2_transfer_setup(udev, &iface_index, sc->sc_xfer,
|
||||
uhub_config, UHUB_N_TRANSFER, sc, &Giant);
|
||||
if (udev->parent_hub == NULL) {
|
||||
/* root HUB is special */
|
||||
err = 0;
|
||||
} else {
|
||||
/* normal HUB */
|
||||
err = usb2_transfer_setup(udev, &iface_index, sc->sc_xfer,
|
||||
uhub_config, UHUB_N_TRANSFER, sc, &Giant);
|
||||
}
|
||||
if (err) {
|
||||
DPRINTFN(0, "cannot setup interrupt transfer, "
|
||||
"errstr=%s!\n", usb2_errstr(err));
|
||||
@ -804,11 +828,13 @@ uhub_attach(device_t dev)
|
||||
"removable, %s powered\n", nports, (nports != 1) ? "s" : "",
|
||||
removable, udev->flags.self_powered ? "self" : "bus");
|
||||
|
||||
/* start the interrupt endpoint */
|
||||
/* Start the interrupt endpoint, if any */
|
||||
|
||||
USB_XFER_LOCK(sc->sc_xfer[0]);
|
||||
usb2_transfer_start(sc->sc_xfer[0]);
|
||||
USB_XFER_UNLOCK(sc->sc_xfer[0]);
|
||||
if (sc->sc_xfer[0] != NULL) {
|
||||
USB_XFER_LOCK(sc->sc_xfer[0]);
|
||||
usb2_transfer_start(sc->sc_xfer[0]);
|
||||
USB_XFER_UNLOCK(sc->sc_xfer[0]);
|
||||
}
|
||||
|
||||
/* Enable automatic power save on all USB HUBs */
|
||||
|
||||
@ -1359,13 +1385,25 @@ usb2_bus_port_set_device(struct usb2_bus *bus, struct usb2_port *up,
|
||||
void
|
||||
usb2_needs_explore(struct usb2_bus *bus, uint8_t do_probe)
|
||||
{
|
||||
uint8_t do_unlock;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
if (bus == NULL) {
|
||||
DPRINTF("No bus pointer!\n");
|
||||
return;
|
||||
}
|
||||
USB_BUS_LOCK(bus);
|
||||
if ((bus->devices == NULL) ||
|
||||
(bus->devices[USB_ROOT_HUB_ADDR] == NULL)) {
|
||||
DPRINTF("No root HUB\n");
|
||||
return;
|
||||
}
|
||||
if (mtx_owned(&bus->bus_mtx)) {
|
||||
do_unlock = 0;
|
||||
} else {
|
||||
USB_BUS_LOCK(bus);
|
||||
do_unlock = 1;
|
||||
}
|
||||
if (do_probe) {
|
||||
bus->do_probe = 1;
|
||||
}
|
||||
@ -1373,7 +1411,9 @@ usb2_needs_explore(struct usb2_bus *bus, uint8_t do_probe)
|
||||
&bus->explore_msg[0], &bus->explore_msg[1])) {
|
||||
/* ignore */
|
||||
}
|
||||
USB_BUS_UNLOCK(bus);
|
||||
if (do_unlock) {
|
||||
USB_BUS_UNLOCK(bus);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
|
@ -78,5 +78,6 @@ void usb2_needs_explore(struct usb2_bus *bus, uint8_t do_probe);
|
||||
void usb2_needs_explore_all(void);
|
||||
void usb2_bus_power_update(struct usb2_bus *bus);
|
||||
void usb2_bus_powerd(struct usb2_bus *bus);
|
||||
void uhub_root_intr(struct usb2_bus *, const uint8_t *, uint8_t);
|
||||
|
||||
#endif /* _USB2_HUB_H_ */
|
||||
|
@ -262,9 +262,9 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
|
||||
* Set "actlen" to a known value in case the caller does not
|
||||
* check the return value:
|
||||
*/
|
||||
if (actlen) {
|
||||
if (actlen)
|
||||
*actlen = 0;
|
||||
}
|
||||
|
||||
#if (USB_HAVE_USER_IO == 0)
|
||||
if (flags & USB_USER_DATA_PTR)
|
||||
return (USB_ERR_INVAL);
|
||||
@ -273,14 +273,13 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
|
||||
DPRINTF("USB device mode\n");
|
||||
(usb2_temp_get_desc_p) (udev, req, &desc, &temp);
|
||||
if (length > temp) {
|
||||
if (!(flags & USB_SHORT_XFER_OK)) {
|
||||
if (!(flags & USB_SHORT_XFER_OK))
|
||||
return (USB_ERR_SHORT_XFER);
|
||||
}
|
||||
length = temp;
|
||||
}
|
||||
if (actlen) {
|
||||
if (actlen)
|
||||
*actlen = length;
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
#if USB_HAVE_USER_IO
|
||||
if (flags & USB_USER_DATA_PTR) {
|
||||
@ -306,6 +305,59 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
|
||||
|
||||
sx_xlock(udev->default_sx);
|
||||
|
||||
if (udev->parent_hub == NULL) {
|
||||
struct usb2_sw_transfer *std = &udev->bus->roothub_req;
|
||||
|
||||
/* root HUB code - stripped down */
|
||||
|
||||
if (req->bmRequestType & UT_READ) {
|
||||
std->ptr = NULL;
|
||||
} else {
|
||||
if (length != 0) {
|
||||
DPRINTFN(1, "Root HUB does not support "
|
||||
"writing data!\n");
|
||||
err = USB_ERR_INVAL;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
/* setup request */
|
||||
std->req = *req;
|
||||
std->err = 0;
|
||||
std->len = 0;
|
||||
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
(udev->bus->methods->roothub_exec) (udev->bus);
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
err = std->err;
|
||||
if (err)
|
||||
goto done;
|
||||
|
||||
if (length > std->len) {
|
||||
length = std->len;
|
||||
if (!(flags & USB_SHORT_XFER_OK)) {
|
||||
err = USB_ERR_SHORT_XFER;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (actlen)
|
||||
*actlen = length;
|
||||
|
||||
if (length > 0) {
|
||||
#if USB_HAVE_USER_IO
|
||||
if (flags & USB_USER_DATA_PTR) {
|
||||
if (copyout(std->ptr, data, length)) {
|
||||
err = USB_ERR_INVAL;
|
||||
goto done;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
bcopy(std->ptr, data, length);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup a new USB transfer or use the existing one, if any:
|
||||
*/
|
||||
|
@ -24,146 +24,3 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <dev/usb/usb_mfunc.h>
|
||||
#include <dev/usb/usb.h>
|
||||
#include <dev/usb/usb_error.h>
|
||||
|
||||
#define USB_DEBUG_VAR usb2_debug
|
||||
|
||||
#include <dev/usb/usb_core.h>
|
||||
#include <dev/usb/usb_process.h>
|
||||
#include <dev/usb/usb_busdma.h>
|
||||
#include <dev/usb/usb_transfer.h>
|
||||
#include <dev/usb/usb_sw_transfer.h>
|
||||
#include <dev/usb/usb_device.h>
|
||||
#include <dev/usb/usb_debug.h>
|
||||
|
||||
#include <dev/usb/usb_controller.h>
|
||||
#include <dev/usb/usb_bus.h>
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_sw_transfer - factored out code
|
||||
*
|
||||
* This function is basically used for the Virtual Root HUB, and can
|
||||
* emulate control, bulk and interrupt endpoints. Data is exchanged
|
||||
* using the "std->ptr" and "std->len" fields, that allows kernel
|
||||
* virtual memory to be transferred. All state is kept in the
|
||||
* structure pointed to by the "std" argument passed to this
|
||||
* function. The "func" argument points to a function that is called
|
||||
* back in the various states, so that the application using this
|
||||
* function can get a chance to select the outcome. The "func"
|
||||
* function is allowed to sleep, exiting all mutexes. If this function
|
||||
* will sleep the "enter" and "start" methods must be marked
|
||||
* non-cancelable, hence there is no extra cancelled checking in this
|
||||
* function.
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
usb2_sw_transfer(struct usb2_sw_transfer *std,
|
||||
usb2_sw_transfer_func_t *func)
|
||||
{
|
||||
struct usb2_xfer *xfer;
|
||||
usb2_frlength_t len;
|
||||
uint8_t shortpkt = 0;
|
||||
|
||||
xfer = std->xfer;
|
||||
if (xfer == NULL) {
|
||||
/* the transfer is gone */
|
||||
DPRINTF("xfer gone\n");
|
||||
return;
|
||||
}
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
std->xfer = NULL;
|
||||
|
||||
/* check for control transfer */
|
||||
if (xfer->flags_int.control_xfr) {
|
||||
/* check if we are transferring the SETUP packet */
|
||||
if (xfer->flags_int.control_hdr) {
|
||||
|
||||
/* copy out the USB request */
|
||||
|
||||
if (xfer->frlengths[0] == sizeof(std->req)) {
|
||||
usb2_copy_out(xfer->frbuffers, 0,
|
||||
&std->req, sizeof(std->req));
|
||||
} else {
|
||||
std->err = USB_ERR_INVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
xfer->aframes = 1;
|
||||
|
||||
std->err = 0;
|
||||
std->state = USB_SW_TR_SETUP;
|
||||
|
||||
(func) (xfer, std);
|
||||
|
||||
if (std->err) {
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
/* skip the first frame in this case */
|
||||
xfer->aframes = 1;
|
||||
}
|
||||
}
|
||||
std->err = 0;
|
||||
std->state = USB_SW_TR_PRE_DATA;
|
||||
|
||||
(func) (xfer, std);
|
||||
|
||||
if (std->err) {
|
||||
goto done;
|
||||
}
|
||||
/* Transfer data. Iterate accross all frames. */
|
||||
while (xfer->aframes != xfer->nframes) {
|
||||
|
||||
len = xfer->frlengths[xfer->aframes];
|
||||
|
||||
if (len > std->len) {
|
||||
len = std->len;
|
||||
shortpkt = 1;
|
||||
}
|
||||
if (len > 0) {
|
||||
if ((xfer->endpoint & (UE_DIR_IN | UE_DIR_OUT)) == UE_DIR_IN) {
|
||||
usb2_copy_in(xfer->frbuffers + xfer->aframes, 0,
|
||||
std->ptr, len);
|
||||
} else {
|
||||
usb2_copy_out(xfer->frbuffers + xfer->aframes, 0,
|
||||
std->ptr, len);
|
||||
}
|
||||
}
|
||||
std->ptr += len;
|
||||
std->len -= len;
|
||||
xfer->frlengths[xfer->aframes] = len;
|
||||
xfer->aframes++;
|
||||
|
||||
if (shortpkt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std->err = 0;
|
||||
std->state = USB_SW_TR_POST_DATA;
|
||||
|
||||
(func) (xfer, std);
|
||||
|
||||
if (std->err) {
|
||||
goto done;
|
||||
}
|
||||
/* check if the control transfer is complete */
|
||||
if (xfer->flags_int.control_xfr &&
|
||||
!xfer->flags_int.control_act) {
|
||||
|
||||
std->err = 0;
|
||||
std->state = USB_SW_TR_STATUS;
|
||||
|
||||
(func) (xfer, std);
|
||||
|
||||
if (std->err) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
done:
|
||||
DPRINTF("done err=%s\n", usb2_errstr(std->err));
|
||||
std->state = USB_SW_TR_PRE_CALLBACK;
|
||||
(func) (xfer, std);
|
||||
}
|
||||
|
@ -27,36 +27,4 @@
|
||||
#ifndef _USB2_SW_TRANSFER_H_
|
||||
#define _USB2_SW_TRANSFER_H_
|
||||
|
||||
/* Software transfer function state argument values */
|
||||
|
||||
enum {
|
||||
USB_SW_TR_SETUP,
|
||||
USB_SW_TR_STATUS,
|
||||
USB_SW_TR_PRE_DATA,
|
||||
USB_SW_TR_POST_DATA,
|
||||
USB_SW_TR_PRE_CALLBACK,
|
||||
};
|
||||
|
||||
struct usb2_sw_transfer;
|
||||
|
||||
typedef void (usb2_sw_transfer_func_t)(struct usb2_xfer *, struct usb2_sw_transfer *);
|
||||
|
||||
/*
|
||||
* The following structure is used to keep the state of a standard
|
||||
* root transfer.
|
||||
*/
|
||||
struct usb2_sw_transfer {
|
||||
struct usb2_device_request req;
|
||||
struct usb2_xfer *xfer;
|
||||
uint8_t *ptr;
|
||||
uint16_t len;
|
||||
uint8_t state;
|
||||
usb2_error_t err;
|
||||
};
|
||||
|
||||
/* prototypes */
|
||||
|
||||
void usb2_sw_transfer(struct usb2_sw_transfer *std,
|
||||
usb2_sw_transfer_func_t *func);
|
||||
|
||||
#endif /* _USB2_SW_TRANSFER_H_ */
|
||||
|
@ -846,7 +846,7 @@ usb2_transfer_setup(struct usb2_device *udev,
|
||||
pipe = usb2_get_pipe(udev,
|
||||
ifaces[setup->if_index], setup);
|
||||
|
||||
if (!pipe) {
|
||||
if ((pipe == NULL) || (pipe->methods == NULL)) {
|
||||
if (setup->flags.no_pipe_ok)
|
||||
continue;
|
||||
if ((setup->usb_mode != USB_MODE_MAX) &&
|
||||
@ -2547,6 +2547,9 @@ usb2_default_transfer_setup(struct usb2_device *udev)
|
||||
uint8_t no_resetup;
|
||||
uint8_t iface_index;
|
||||
|
||||
/* check for root HUB */
|
||||
if (udev->parent_hub == NULL)
|
||||
return;
|
||||
repeat:
|
||||
|
||||
xfer = udev->default_xfer[0];
|
||||
|
Loading…
Reference in New Issue
Block a user