Sync with usb4bsd:
src/lib/libusb20/libusb20_desc.c Make "libusb20_desc_foreach()" more readable. src/sys/dev/usb2/controller/*.[ch] src/sys/dev/usb2/core/*.[ch] Implement support for USB power save for all HC's. Implement support for Big-endian EHCI. Move Huawei quirks back into "u3g" driver. Improve device enumeration. src/sys/dev/usb2/ethernet/*[ch] Patches for supporting new AXE Gigabit chipset. src/sys/dev/usb2/serial/*[ch] Fix IOCTL return code. src/sys/dev/usb2/wlan/*[ch] Sync with old USB stack. Submitted by: hps
This commit is contained in:
parent
17c98d6dab
commit
d5474fd85f
@ -238,23 +238,37 @@ const uint8_t *
|
||||
libusb20_desc_foreach(const struct libusb20_me_struct *pdesc,
|
||||
const uint8_t *psubdesc)
|
||||
{
|
||||
const void *end;
|
||||
const uint8_t *start;
|
||||
const uint8_t *end;
|
||||
const uint8_t *desc_next;
|
||||
|
||||
if (pdesc == NULL) {
|
||||
/* be NULL safe */
|
||||
if (pdesc == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
end = LIBUSB20_ADD_BYTES(pdesc->ptr, pdesc->len);
|
||||
|
||||
if (psubdesc == NULL) {
|
||||
psubdesc = LIBUSB20_ADD_BYTES(pdesc->ptr, 0);
|
||||
} else {
|
||||
psubdesc = LIBUSB20_ADD_BYTES(psubdesc, psubdesc[0]);
|
||||
}
|
||||
return (((((const void *)psubdesc) >= ((void *)(pdesc->ptr))) &&
|
||||
(((const void *)psubdesc) < end) &&
|
||||
(LIBUSB20_ADD_BYTES(psubdesc, psubdesc[0]) >= ((void *)(pdesc->ptr))) &&
|
||||
(LIBUSB20_ADD_BYTES(psubdesc, psubdesc[0]) <= end) &&
|
||||
(psubdesc[0] >= 3)) ? psubdesc : NULL);
|
||||
start = (const uint8_t *)pdesc->ptr;
|
||||
end = LIBUSB20_ADD_BYTES(start, pdesc->len);
|
||||
|
||||
/* get start of next descriptor */
|
||||
if (psubdesc == NULL)
|
||||
psubdesc = start;
|
||||
else
|
||||
psubdesc = psubdesc + psubdesc[0];
|
||||
|
||||
/* check that the next USB descriptor is within the range */
|
||||
if ((psubdesc < start) || (psubdesc >= end))
|
||||
return (NULL); /* out of range, or EOD */
|
||||
|
||||
/* check start of the second next USB descriptor, if any */
|
||||
desc_next = psubdesc + psubdesc[0];
|
||||
if ((desc_next < start) || (desc_next > end))
|
||||
return (NULL); /* out of range */
|
||||
|
||||
/* check minimum descriptor length */
|
||||
if (psubdesc[0] < 3)
|
||||
return (NULL); /* too short descriptor */
|
||||
|
||||
return (psubdesc); /* return start of next descriptor */
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
|
@ -261,42 +261,28 @@ at91dci_pull_down(struct at91dci_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
at91dci_wakeup_peer(struct at91dci_softc *sc)
|
||||
at91dci_wakeup_peer(struct usb2_xfer *xfer)
|
||||
{
|
||||
uint32_t temp;
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
uint8_t use_polling;
|
||||
|
||||
if (!(sc->sc_flags.status_suspend)) {
|
||||
return;
|
||||
}
|
||||
temp = AT91_UDP_READ_4(sc, AT91_UDP_GSTATE);
|
||||
use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0;
|
||||
|
||||
if (!(temp & AT91_UDP_GSTATE_ESR)) {
|
||||
return;
|
||||
}
|
||||
AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, temp);
|
||||
}
|
||||
AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, AT91_UDP_GSTATE_ESR);
|
||||
|
||||
static void
|
||||
at91dci_rem_wakeup_set(struct usb2_device *udev, uint8_t is_on)
|
||||
{
|
||||
struct at91dci_softc *sc;
|
||||
uint32_t temp;
|
||||
|
||||
DPRINTFN(5, "is_on=%u\n", is_on);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
|
||||
|
||||
sc = AT9100_DCI_BUS2SC(udev->bus);
|
||||
|
||||
temp = AT91_UDP_READ_4(sc, AT91_UDP_GSTATE);
|
||||
|
||||
if (is_on) {
|
||||
temp |= AT91_UDP_GSTATE_ESR;
|
||||
/* wait 8 milliseconds */
|
||||
if (use_polling) {
|
||||
/* polling */
|
||||
DELAY(8000);
|
||||
} else {
|
||||
temp &= ~AT91_UDP_GSTATE_ESR;
|
||||
/* Wait for reset to complete. */
|
||||
usb2_pause_mtx(&sc->sc_bus.bus_mtx, 8);
|
||||
}
|
||||
|
||||
AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, temp);
|
||||
AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2120,7 +2106,7 @@ tr_handle_clear_port_feature:
|
||||
|
||||
switch (value) {
|
||||
case UHF_PORT_SUSPEND:
|
||||
at91dci_wakeup_peer(sc);
|
||||
at91dci_wakeup_peer(xfer);
|
||||
break;
|
||||
|
||||
case UHF_PORT_ENABLE:
|
||||
@ -2492,5 +2478,4 @@ struct usb2_bus_methods at91dci_bus_methods =
|
||||
.set_stall = &at91dci_set_stall,
|
||||
.clear_stall = &at91dci_clear_stall,
|
||||
.vbus_interrupt = &at91dci_vbus_interrupt,
|
||||
.rem_wakeup_set = &at91dci_rem_wakeup_set,
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -160,6 +160,15 @@
|
||||
#define EHCI_PS_CS 0x00000001 /* RO connect status */
|
||||
#define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC)
|
||||
|
||||
#define EHCI_USBMODE 0x68 /* RW USB Device mode register */
|
||||
#define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */
|
||||
#define EHCI_UM_CM_IDLE 0x0 /* Idle */
|
||||
#define EHCI_UM_CM_HOST 0x3 /* Host Controller */
|
||||
#define EHCI_UM_ES 0x00000004 /* R/WO Endian Select */
|
||||
#define EHCI_UM_ES_LE 0x0 /* Little-endian byte alignment */
|
||||
#define EHCI_UM_ES_BE 0x4 /* Big-endian byte alignment */
|
||||
#define EHCI_UM_SDIS 0x00000010 /* R/WO Stream Disable Mode */
|
||||
|
||||
#define EHCI_PORT_RESET_COMPLETE 2 /* ms */
|
||||
|
||||
/*
|
||||
@ -469,11 +478,12 @@ typedef struct ehci_softc {
|
||||
uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT];
|
||||
uint16_t sc_id_vendor; /* vendor ID for root hub */
|
||||
uint16_t sc_flags; /* chip specific flags */
|
||||
#define EHCI_SCFLG_SETMODE 0x0001 /* set bridge mode again after init
|
||||
* (Marvell) */
|
||||
#define EHCI_SCFLG_FORCESPEED 0x0002 /* force speed (Marvell) */
|
||||
#define EHCI_SCFLG_NORESTERM 0x0004 /* don't terminate reset sequence
|
||||
* (Marvell) */
|
||||
#define EHCI_SCFLG_SETMODE 0x0001 /* set bridge mode again after init */
|
||||
#define EHCI_SCFLG_FORCESPEED 0x0002 /* force speed */
|
||||
#define EHCI_SCFLG_NORESTERM 0x0004 /* don't terminate reset sequence */
|
||||
#define EHCI_SCFLG_BIGEDESC 0x0008 /* big-endian byte order descriptors */
|
||||
#define EHCI_SCFLG_BIGEMMIO 0x0010 /* big-endian byte order MMIO */
|
||||
#define EHCI_SCFLG_TT 0x0020 /* transaction translator present */
|
||||
|
||||
uint8_t sc_offs; /* offset to operational registers */
|
||||
uint8_t sc_doorbell_disable; /* set on doorbell failure */
|
||||
|
@ -235,12 +235,6 @@ musbotg_wakeup_peer(struct usb2_xfer *xfer)
|
||||
MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
|
||||
}
|
||||
|
||||
static void
|
||||
musbotg_rem_wakeup_set(struct usb2_device *udev, uint8_t is_on)
|
||||
{
|
||||
DPRINTFN(4, "is_on=%u\n", is_on);
|
||||
}
|
||||
|
||||
static void
|
||||
musbotg_set_address(struct musbotg_softc *sc, uint8_t addr)
|
||||
{
|
||||
@ -2891,5 +2885,4 @@ struct usb2_bus_methods musbotg_bus_methods =
|
||||
.set_stall = &musbotg_set_stall,
|
||||
.clear_stall = &musbotg_clear_stall,
|
||||
.vbus_interrupt = &musbotg_vbus_interrupt,
|
||||
.rem_wakeup_set = &musbotg_rem_wakeup_set,
|
||||
};
|
||||
|
@ -681,18 +681,22 @@ ohci_transfer_intr_enqueue(struct usb2_xfer *xfer)
|
||||
}
|
||||
}
|
||||
|
||||
#define OHCI_APPEND_QH(sed,td_self,last) (last) = _ohci_append_qh(sed,td_self,last)
|
||||
#define OHCI_APPEND_QH(sed,last) (last) = _ohci_append_qh(sed,last)
|
||||
static ohci_ed_t *
|
||||
_ohci_append_qh(ohci_ed_t *sed, uint32_t td_self, ohci_ed_t *last)
|
||||
_ohci_append_qh(ohci_ed_t *sed, ohci_ed_t *last)
|
||||
{
|
||||
DPRINTFN(11, "%p to %p\n", sed, last);
|
||||
|
||||
if (sed->prev != NULL) {
|
||||
/* should not happen */
|
||||
DPRINTFN(0, "ED already linked!\n");
|
||||
return (last);
|
||||
}
|
||||
/* (sc->sc_bus.bus_mtx) must be locked */
|
||||
|
||||
sed->next = last->next;
|
||||
sed->ed_next = last->ed_next;
|
||||
sed->ed_tailp = 0;
|
||||
sed->ed_headp = td_self;
|
||||
|
||||
sed->prev = last;
|
||||
|
||||
@ -730,13 +734,6 @@ _ohci_remove_qh(ohci_ed_t *sed, ohci_ed_t *last)
|
||||
sed->next->prev = sed->prev;
|
||||
usb2_pc_cpu_flush(sed->next->page_cache);
|
||||
}
|
||||
/*
|
||||
* terminate transfer in case the transferred packet was
|
||||
* short so that the ED still points at the last used TD
|
||||
*/
|
||||
sed->ed_flags |= htole32(OHCI_ED_SKIP);
|
||||
sed->ed_headp = sed->ed_tailp;
|
||||
|
||||
last = ((last == sed) ? sed->prev : last);
|
||||
|
||||
sed->prev = 0;
|
||||
@ -1565,17 +1562,23 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
|
||||
|
||||
td = xfer->td_transfer_first;
|
||||
|
||||
OHCI_APPEND_QH(ed, td->td_self, *ed_last);
|
||||
ed->ed_headp = td->td_self;
|
||||
|
||||
if (methods == &ohci_device_bulk_methods) {
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
if (xfer->udev->pwr_save.suspended == 0) {
|
||||
OHCI_APPEND_QH(ed, *ed_last);
|
||||
|
||||
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
|
||||
}
|
||||
if (methods == &ohci_device_ctrl_methods) {
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
if (methods == &ohci_device_bulk_methods) {
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
|
||||
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
|
||||
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
|
||||
}
|
||||
if (methods == &ohci_device_ctrl_methods) {
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
|
||||
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
|
||||
}
|
||||
} else {
|
||||
usb2_pc_cpu_flush(ed->page_cache);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2010,7 +2013,11 @@ ohci_device_isoc_enter(struct usb2_xfer *xfer)
|
||||
|
||||
td = xfer->td_transfer_first;
|
||||
|
||||
OHCI_APPEND_QH(ed, td->itd_self, sc->sc_isoc_p_last);
|
||||
ed->ed_headp = td->itd_self;
|
||||
|
||||
/* isochronous transfers are not affected by suspend / resume */
|
||||
|
||||
OHCI_APPEND_QH(ed, sc->sc_isoc_p_last);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2740,6 +2747,115 @@ ohci_get_dma_delay(struct usb2_bus *bus, uint32_t *pus)
|
||||
*pus = (1125); /* microseconds */
|
||||
}
|
||||
|
||||
static void
|
||||
ohci_device_resume(struct usb2_device *udev)
|
||||
{
|
||||
struct ohci_softc *sc = OHCI_BUS2SC(udev->bus);
|
||||
struct usb2_xfer *xfer;
|
||||
struct usb2_pipe_methods *methods;
|
||||
ohci_ed_t *ed;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
|
||||
if (methods == &ohci_device_bulk_methods) {
|
||||
OHCI_APPEND_QH(ed, sc->sc_bulk_p_last);
|
||||
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
|
||||
}
|
||||
if (methods == &ohci_device_ctrl_methods) {
|
||||
OHCI_APPEND_QH(ed, sc->sc_ctrl_p_last);
|
||||
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
|
||||
}
|
||||
if (methods == &ohci_device_intr_methods) {
|
||||
OHCI_APPEND_QH(ed, sc->sc_intr_p_last[xfer->qh_pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ohci_device_suspend(struct usb2_device *udev)
|
||||
{
|
||||
struct ohci_softc *sc = OHCI_BUS2SC(udev->bus);
|
||||
struct usb2_xfer *xfer;
|
||||
struct usb2_pipe_methods *methods;
|
||||
ohci_ed_t *ed;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
|
||||
if (methods == &ohci_device_bulk_methods) {
|
||||
OHCI_REMOVE_QH(ed, sc->sc_bulk_p_last);
|
||||
}
|
||||
if (methods == &ohci_device_ctrl_methods) {
|
||||
OHCI_REMOVE_QH(ed, sc->sc_ctrl_p_last);
|
||||
}
|
||||
if (methods == &ohci_device_intr_methods) {
|
||||
OHCI_REMOVE_QH(ed, sc->sc_intr_p_last[xfer->qh_pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ohci_set_hw_power(struct usb2_bus *bus)
|
||||
{
|
||||
struct ohci_softc *sc = OHCI_BUS2SC(bus);
|
||||
uint32_t temp;
|
||||
uint32_t flags;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
USB_BUS_LOCK(bus);
|
||||
|
||||
flags = bus->hw_power_state;
|
||||
|
||||
temp = OREAD4(sc, OHCI_CONTROL);
|
||||
temp &= ~(OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE);
|
||||
|
||||
if (flags & USB_HW_POWER_CONTROL)
|
||||
temp |= OHCI_CLE;
|
||||
|
||||
if (flags & USB_HW_POWER_BULK)
|
||||
temp |= OHCI_BLE;
|
||||
|
||||
if (flags & USB_HW_POWER_INTERRUPT)
|
||||
temp |= OHCI_PLE;
|
||||
|
||||
if (flags & USB_HW_POWER_ISOC)
|
||||
temp |= OHCI_IE | OHCI_PLE;
|
||||
|
||||
OWRITE4(sc, OHCI_CONTROL, temp);
|
||||
|
||||
USB_BUS_UNLOCK(bus);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
struct usb2_bus_methods ohci_bus_methods =
|
||||
{
|
||||
.pipe_init = ohci_pipe_init,
|
||||
@ -2747,4 +2863,7 @@ struct usb2_bus_methods ohci_bus_methods =
|
||||
.xfer_unsetup = ohci_xfer_unsetup,
|
||||
.do_poll = ohci_do_poll,
|
||||
.get_dma_delay = ohci_get_dma_delay,
|
||||
.device_resume = ohci_device_resume,
|
||||
.device_suspend = ohci_device_suspend,
|
||||
.set_hw_power = ohci_set_hw_power,
|
||||
};
|
||||
|
@ -916,17 +916,19 @@ _uhci_append_td(uhci_td_t *std, uhci_td_t *last)
|
||||
return (std);
|
||||
}
|
||||
|
||||
#define UHCI_APPEND_QH(sqh,td,last) (last) = _uhci_append_qh(sqh,td,last)
|
||||
#define UHCI_APPEND_QH(sqh,last) (last) = _uhci_append_qh(sqh,last)
|
||||
static uhci_qh_t *
|
||||
_uhci_append_qh(uhci_qh_t *sqh, uhci_td_t *td, uhci_qh_t *last)
|
||||
_uhci_append_qh(uhci_qh_t *sqh, uhci_qh_t *last)
|
||||
{
|
||||
DPRINTFN(11, "%p to %p\n", sqh, last);
|
||||
|
||||
if (sqh->h_prev != NULL) {
|
||||
/* should not happen */
|
||||
DPRINTFN(0, "QH already linked!\n");
|
||||
return (last);
|
||||
}
|
||||
/* (sc->sc_bus.mtx) must be locked */
|
||||
|
||||
sqh->e_next = td;
|
||||
sqh->qh_e_next = td->td_self;
|
||||
|
||||
sqh->h_next = last->h_next;
|
||||
sqh->qh_h_next = last->qh_h_next;
|
||||
|
||||
@ -990,13 +992,6 @@ _uhci_remove_qh(uhci_qh_t *sqh, uhci_qh_t *last)
|
||||
sqh->h_next->h_prev = sqh->h_prev;
|
||||
usb2_pc_cpu_flush(sqh->h_next->page_cache);
|
||||
}
|
||||
/*
|
||||
* set the Terminate-bit in the e_next of the QH, in case
|
||||
* the transferred packet was short so that the QH still
|
||||
* points at the last used TD
|
||||
*/
|
||||
sqh->qh_e_next = htole32(UHCI_PTR_T);
|
||||
|
||||
last = ((last == sqh) ? sqh->h_prev : last);
|
||||
|
||||
sqh->h_prev = 0;
|
||||
@ -1459,10 +1454,12 @@ uhci_interrupt(uhci_softc_t *sc)
|
||||
}
|
||||
if (status & UHCI_STS_HCH) {
|
||||
/* no acknowledge needed */
|
||||
printf("%s: host controller halted\n",
|
||||
DPRINTF("%s: host controller halted\n",
|
||||
__FUNCTION__);
|
||||
#if USB_DEBUG
|
||||
uhci_dump_all(sc);
|
||||
if (uhcidebug > 0) {
|
||||
uhci_dump_all(sc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1834,11 +1831,6 @@ uhci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
if (qh) {
|
||||
usb2_pc_cpu_invalidate(qh->page_cache);
|
||||
|
||||
qh->e_next = 0;
|
||||
qh->qh_e_next = htole32(UHCI_PTR_T);
|
||||
|
||||
usb2_pc_cpu_flush(qh->page_cache);
|
||||
}
|
||||
if (xfer->flags_int.bandwidth_reclaimed) {
|
||||
xfer->flags_int.bandwidth_reclaimed = 0;
|
||||
@ -1907,9 +1899,16 @@ uhci_device_bulk_start(struct usb2_xfer *xfer)
|
||||
/* setup QH */
|
||||
qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
|
||||
UHCI_APPEND_QH(qh, td, sc->sc_bulk_p_last);
|
||||
uhci_add_loop(sc);
|
||||
xfer->flags_int.bandwidth_reclaimed = 1;
|
||||
qh->e_next = td;
|
||||
qh->qh_e_next = td->td_self;
|
||||
|
||||
if (xfer->udev->pwr_save.suspended == 0) {
|
||||
UHCI_APPEND_QH(qh, sc->sc_bulk_p_last);
|
||||
uhci_add_loop(sc);
|
||||
xfer->flags_int.bandwidth_reclaimed = 1;
|
||||
} else {
|
||||
usb2_pc_cpu_flush(qh->page_cache);
|
||||
}
|
||||
|
||||
/* put transfer on interrupt queue */
|
||||
uhci_transfer_intr_enqueue(xfer);
|
||||
@ -1959,14 +1958,21 @@ uhci_device_ctrl_start(struct usb2_xfer *xfer)
|
||||
/* setup QH */
|
||||
qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
|
||||
qh->e_next = td;
|
||||
qh->qh_e_next = td->td_self;
|
||||
|
||||
/*
|
||||
* NOTE: some devices choke on bandwidth- reclamation for control
|
||||
* transfers
|
||||
*/
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
UHCI_APPEND_QH(qh, td, sc->sc_ls_ctl_p_last);
|
||||
if (xfer->udev->pwr_save.suspended == 0) {
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
UHCI_APPEND_QH(qh, sc->sc_ls_ctl_p_last);
|
||||
} else {
|
||||
UHCI_APPEND_QH(qh, sc->sc_fs_ctl_p_last);
|
||||
}
|
||||
} else {
|
||||
UHCI_APPEND_QH(qh, td, sc->sc_fs_ctl_p_last);
|
||||
usb2_pc_cpu_flush(qh->page_cache);
|
||||
}
|
||||
/* put transfer on interrupt queue */
|
||||
uhci_transfer_intr_enqueue(xfer);
|
||||
@ -2047,8 +2053,17 @@ uhci_device_intr_start(struct usb2_xfer *xfer)
|
||||
/* setup QH */
|
||||
qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
|
||||
/* enter QHs into the controller data structures */
|
||||
UHCI_APPEND_QH(qh, td, sc->sc_intr_p_last[xfer->qh_pos]);
|
||||
qh->e_next = td;
|
||||
qh->qh_e_next = td->td_self;
|
||||
|
||||
if (xfer->udev->pwr_save.suspended == 0) {
|
||||
|
||||
/* enter QHs into the controller data structures */
|
||||
UHCI_APPEND_QH(qh, sc->sc_intr_p_last[xfer->qh_pos]);
|
||||
|
||||
} else {
|
||||
usb2_pc_cpu_flush(qh->page_cache);
|
||||
}
|
||||
|
||||
/* put transfer on interrupt queue */
|
||||
uhci_transfer_intr_enqueue(xfer);
|
||||
@ -2659,7 +2674,7 @@ uhci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
break;
|
||||
case UHF_PORT_SUSPEND:
|
||||
x = URWMASK(UREAD2(sc, port));
|
||||
UWRITE2(sc, port, x & ~UHCI_PORTSC_SUSP);
|
||||
UWRITE2(sc, port, x & ~(UHCI_PORTSC_SUSP));
|
||||
break;
|
||||
case UHF_PORT_RESET:
|
||||
x = URWMASK(UREAD2(sc, port));
|
||||
@ -2681,11 +2696,13 @@ uhci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
sc->sc_isreset = 0;
|
||||
std->err = USB_ERR_NORMAL_COMPLETION;
|
||||
goto done;
|
||||
case UHF_C_PORT_SUSPEND:
|
||||
sc->sc_isresumed &= ~(1 << index);
|
||||
break;
|
||||
case UHF_PORT_CONNECTION:
|
||||
case UHF_PORT_OVER_CURRENT:
|
||||
case UHF_PORT_POWER:
|
||||
case UHF_PORT_LOW_SPEED:
|
||||
case UHF_C_PORT_SUSPEND:
|
||||
default:
|
||||
std->err = USB_ERR_IOERROR;
|
||||
goto done;
|
||||
@ -2740,11 +2757,35 @@ uhci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
status |= UPS_OVERCURRENT_INDICATOR;
|
||||
if (x & UHCI_PORTSC_OCIC)
|
||||
change |= UPS_C_OVERCURRENT_INDICATOR;
|
||||
if (x & UHCI_PORTSC_SUSP)
|
||||
status |= UPS_SUSPEND;
|
||||
if (x & UHCI_PORTSC_LSDA)
|
||||
status |= UPS_LOW_SPEED;
|
||||
if ((x & UHCI_PORTSC_PE) && (x & UHCI_PORTSC_RD)) {
|
||||
/* need to do a write back */
|
||||
UWRITE2(sc, port, URWMASK(x));
|
||||
|
||||
/* wait 20ms for resume sequence to complete */
|
||||
if (use_polling) {
|
||||
/* polling */
|
||||
DELAY(20 * 1000);
|
||||
} else {
|
||||
usb2_pause_mtx(&sc->sc_bus.bus_mtx, 20);
|
||||
}
|
||||
|
||||
/* clear suspend and resume detect */
|
||||
UWRITE2(sc, port, URWMASK(x) & ~(UHCI_PORTSC_RD |
|
||||
UHCI_PORTSC_SUSP));
|
||||
|
||||
/* wait a little bit */
|
||||
usb2_pause_mtx(&sc->sc_bus.bus_mtx, 2);
|
||||
|
||||
sc->sc_isresumed |= (1 << index);
|
||||
|
||||
} else if (x & UHCI_PORTSC_SUSP) {
|
||||
status |= UPS_SUSPEND;
|
||||
}
|
||||
status |= UPS_PORT_POWER;
|
||||
if (sc->sc_isresumed & (1 << index))
|
||||
change |= UPS_C_SUSPEND;
|
||||
if (sc->sc_isreset)
|
||||
change |= UPS_C_PORT_RESET;
|
||||
USETW(sc->sc_hub_desc.ps.wPortStatus, status);
|
||||
@ -2894,13 +2935,15 @@ uhci_root_intr_check(void *arg)
|
||||
|
||||
sc->sc_hub_idata[0] = 0;
|
||||
|
||||
if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC | UHCI_PORTSC_OCIC)) {
|
||||
if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC |
|
||||
UHCI_PORTSC_OCIC | UHCI_PORTSC_RD)) {
|
||||
sc->sc_hub_idata[0] |= 1 << 1;
|
||||
}
|
||||
if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC | UHCI_PORTSC_OCIC)) {
|
||||
if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC |
|
||||
UHCI_PORTSC_OCIC | UHCI_PORTSC_RD)) {
|
||||
sc->sc_hub_idata[0] |= 1 << 2;
|
||||
}
|
||||
if ((sc->sc_hub_idata[0] == 0) || !(UREAD2(sc, UHCI_CMD) & UHCI_CMD_RS)) {
|
||||
if (sc->sc_hub_idata[0] == 0) {
|
||||
/*
|
||||
* no change or controller not running, try again in a while
|
||||
*/
|
||||
@ -3190,6 +3233,124 @@ uhci_get_dma_delay(struct usb2_bus *bus, uint32_t *pus)
|
||||
*pus = (1125); /* microseconds */
|
||||
}
|
||||
|
||||
static void
|
||||
uhci_device_resume(struct usb2_device *udev)
|
||||
{
|
||||
struct uhci_softc *sc = UHCI_BUS2SC(udev->bus);
|
||||
struct usb2_xfer *xfer;
|
||||
struct usb2_pipe_methods *methods;
|
||||
uhci_qh_t *qh;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
|
||||
if (methods == &uhci_device_bulk_methods) {
|
||||
UHCI_APPEND_QH(qh, sc->sc_bulk_p_last);
|
||||
uhci_add_loop(sc);
|
||||
xfer->flags_int.bandwidth_reclaimed = 1;
|
||||
}
|
||||
if (methods == &uhci_device_ctrl_methods) {
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
UHCI_APPEND_QH(qh, sc->sc_ls_ctl_p_last);
|
||||
} else {
|
||||
UHCI_APPEND_QH(qh, sc->sc_fs_ctl_p_last);
|
||||
}
|
||||
}
|
||||
if (methods == &uhci_device_intr_methods) {
|
||||
UHCI_APPEND_QH(qh, sc->sc_intr_p_last[xfer->qh_pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
uhci_device_suspend(struct usb2_device *udev)
|
||||
{
|
||||
struct uhci_softc *sc = UHCI_BUS2SC(udev->bus);
|
||||
struct usb2_xfer *xfer;
|
||||
struct usb2_pipe_methods *methods;
|
||||
uhci_qh_t *qh;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
|
||||
if (xfer->flags_int.bandwidth_reclaimed) {
|
||||
xfer->flags_int.bandwidth_reclaimed = 0;
|
||||
uhci_rem_loop(sc);
|
||||
}
|
||||
if (methods == &uhci_device_bulk_methods) {
|
||||
UHCI_REMOVE_QH(qh, sc->sc_bulk_p_last);
|
||||
}
|
||||
if (methods == &uhci_device_ctrl_methods) {
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
UHCI_REMOVE_QH(qh, sc->sc_ls_ctl_p_last);
|
||||
} else {
|
||||
UHCI_REMOVE_QH(qh, sc->sc_fs_ctl_p_last);
|
||||
}
|
||||
}
|
||||
if (methods == &uhci_device_intr_methods) {
|
||||
UHCI_REMOVE_QH(qh, sc->sc_intr_p_last[xfer->qh_pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
uhci_set_hw_power(struct usb2_bus *bus)
|
||||
{
|
||||
struct uhci_softc *sc = UHCI_BUS2SC(bus);
|
||||
uint32_t flags;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
USB_BUS_LOCK(bus);
|
||||
|
||||
flags = bus->hw_power_state;
|
||||
|
||||
if (flags & (USB_HW_POWER_CONTROL |
|
||||
USB_HW_POWER_BULK |
|
||||
USB_HW_POWER_INTERRUPT |
|
||||
USB_HW_POWER_ISOC)) {
|
||||
DPRINTF("Some USB transfer is "
|
||||
"active on %u.\n",
|
||||
device_get_unit(sc->sc_bus.bdev));
|
||||
UHCICMD(sc, (UHCI_CMD_MAXP | UHCI_CMD_RS));
|
||||
} else {
|
||||
DPRINTF("Power save on %u.\n",
|
||||
device_get_unit(sc->sc_bus.bdev));
|
||||
UHCICMD(sc, UHCI_CMD_MAXP);
|
||||
}
|
||||
|
||||
USB_BUS_UNLOCK(bus);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
struct usb2_bus_methods uhci_bus_methods =
|
||||
{
|
||||
.pipe_init = uhci_pipe_init,
|
||||
@ -3197,4 +3358,7 @@ struct usb2_bus_methods uhci_bus_methods =
|
||||
.xfer_unsetup = uhci_xfer_unsetup,
|
||||
.do_poll = uhci_do_poll,
|
||||
.get_dma_delay = uhci_get_dma_delay,
|
||||
.device_resume = uhci_device_resume,
|
||||
.device_suspend = uhci_device_suspend,
|
||||
.set_hw_power = uhci_set_hw_power,
|
||||
};
|
||||
|
@ -300,7 +300,8 @@ typedef struct uhci_softc {
|
||||
|
||||
uint8_t sc_addr; /* device address */
|
||||
uint8_t sc_conf; /* device configuration */
|
||||
uint8_t sc_isreset;
|
||||
uint8_t sc_isreset; /* bits set if a root hub is reset */
|
||||
uint8_t sc_isresumed; /* bits set if a port was resumed */
|
||||
uint8_t sc_saved_sof;
|
||||
uint8_t sc_hub_idata[1];
|
||||
|
||||
|
@ -54,10 +54,14 @@ struct usb2_bus {
|
||||
struct usb2_process explore_proc;
|
||||
struct usb2_bus_msg explore_msg[2];
|
||||
struct usb2_bus_msg detach_msg[2];
|
||||
struct mtx bus_mtx; /* This mutex protects the USB
|
||||
* hardware */
|
||||
struct usb2_bus_msg attach_msg[2];
|
||||
/*
|
||||
* This mutex protects the USB hardware:
|
||||
*/
|
||||
struct mtx bus_mtx;
|
||||
struct usb2_perm perm;
|
||||
struct usb2_xfer_queue intr_q;
|
||||
struct usb2_callout power_wdog; /* power management */
|
||||
|
||||
device_t parent;
|
||||
device_t bdev; /* filled by HC driver */
|
||||
@ -68,6 +72,7 @@ struct usb2_bus {
|
||||
struct usb2_bus_methods *methods; /* filled by HC driver */
|
||||
struct usb2_device *devices[USB_MAX_DEVICES];
|
||||
|
||||
uint32_t hw_power_state; /* see USB_HW_POWER_XXX */
|
||||
uint32_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
|
||||
uint32_t transfer_count[4];
|
||||
uint16_t isoc_time_last; /* in milliseconds */
|
||||
|
@ -148,6 +148,9 @@ usb2_detach(device_t dev)
|
||||
/* was never setup properly */
|
||||
return (0);
|
||||
}
|
||||
/* Stop power watchdog */
|
||||
usb2_callout_drain(&bus->power_wdog);
|
||||
|
||||
/* Let the USB explore process detach all devices. */
|
||||
|
||||
USB_BUS_LOCK(bus);
|
||||
@ -197,6 +200,11 @@ usb2_bus_explore(struct usb2_proc_msg *pm)
|
||||
|
||||
mtx_lock(&Giant);
|
||||
|
||||
/*
|
||||
* First update the USB power state!
|
||||
*/
|
||||
usb2_bus_powerd(bus);
|
||||
|
||||
/*
|
||||
* Explore the Root USB HUB. This call can sleep,
|
||||
* exiting Giant, which is actually Giant.
|
||||
@ -246,24 +254,41 @@ usb2_bus_detach(struct usb2_proc_msg *pm)
|
||||
bus->bdev = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_power_wdog(void *arg)
|
||||
{
|
||||
struct usb2_bus *bus = arg;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
|
||||
|
||||
usb2_callout_reset(&bus->power_wdog,
|
||||
4 * hz, usb2_power_wdog, arg);
|
||||
|
||||
USB_BUS_UNLOCK(bus);
|
||||
|
||||
usb2_bus_power_update(bus);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_attach_sub
|
||||
* usb2_bus_attach
|
||||
*
|
||||
* This function is the real USB bus attach code. It is factored out,
|
||||
* hence it can be called at two different places in time. During
|
||||
* bootup this function is called from "usb2_post_init". During
|
||||
* hot-plug it is called directly from the "usb2_attach()" method.
|
||||
* This function attaches USB in context of the explore thread.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb2_attach_sub(device_t dev, struct usb2_bus *bus)
|
||||
usb2_bus_attach(struct usb2_proc_msg *pm)
|
||||
{
|
||||
struct usb2_bus *bus;
|
||||
struct usb2_device *child;
|
||||
device_t dev;
|
||||
usb2_error_t err;
|
||||
uint8_t speed;
|
||||
|
||||
DPRINTF("\n");
|
||||
bus = ((struct usb2_bus_msg *)pm)->bus;
|
||||
dev = bus->bdev;
|
||||
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
DPRINTF("\n");
|
||||
|
||||
switch (bus->usbrev) {
|
||||
case USB_REV_1_0:
|
||||
@ -291,6 +316,9 @@ usb2_attach_sub(device_t dev, struct usb2_bus *bus)
|
||||
return;
|
||||
}
|
||||
|
||||
USB_BUS_UNLOCK(bus);
|
||||
mtx_lock(&Giant); /* XXX not required by USB */
|
||||
|
||||
/* Allocate the Root USB device */
|
||||
|
||||
child = usb2_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
|
||||
@ -307,10 +335,36 @@ usb2_attach_sub(device_t dev, struct usb2_bus *bus)
|
||||
err = USB_ERR_NOMEM;
|
||||
}
|
||||
|
||||
mtx_unlock(&Giant);
|
||||
USB_BUS_LOCK(bus);
|
||||
|
||||
if (err) {
|
||||
device_printf(bus->bdev, "Root HUB problem, error=%s\n",
|
||||
usb2_errstr(err));
|
||||
}
|
||||
|
||||
/* set softc - we are ready */
|
||||
device_set_softc(dev, bus);
|
||||
|
||||
/* start watchdog - this function will unlock the BUS lock ! */
|
||||
usb2_power_wdog(bus);
|
||||
|
||||
/* need to return locked */
|
||||
USB_BUS_LOCK(bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_attach_sub
|
||||
*
|
||||
* This function creates a thread which runs the USB attach code. It
|
||||
* is factored out, hence it can be called at two different places in
|
||||
* time. During bootup this function is called from
|
||||
* "usb2_post_init". During hot-plug it is called directly from the
|
||||
* "usb2_attach()" method.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb2_attach_sub(device_t dev, struct usb2_bus *bus)
|
||||
{
|
||||
/* Initialise USB process messages */
|
||||
bus->explore_msg[0].hdr.pm_callback = &usb2_bus_explore;
|
||||
bus->explore_msg[0].bus = bus;
|
||||
@ -322,13 +376,24 @@ usb2_attach_sub(device_t dev, struct usb2_bus *bus)
|
||||
bus->detach_msg[1].hdr.pm_callback = &usb2_bus_detach;
|
||||
bus->detach_msg[1].bus = bus;
|
||||
|
||||
bus->attach_msg[0].hdr.pm_callback = &usb2_bus_attach;
|
||||
bus->attach_msg[0].bus = bus;
|
||||
bus->attach_msg[1].hdr.pm_callback = &usb2_bus_attach;
|
||||
bus->attach_msg[1].bus = bus;
|
||||
|
||||
/* Create a new USB process */
|
||||
if (usb2_proc_setup(&bus->explore_proc,
|
||||
&bus->bus_mtx, USB_PRI_MED)) {
|
||||
printf("WARNING: Creation of USB explore process failed.\n");
|
||||
} else {
|
||||
/* Get final attach going */
|
||||
USB_BUS_LOCK(bus);
|
||||
if (usb2_proc_msignal(&bus->explore_proc,
|
||||
&bus->attach_msg[0], &bus->attach_msg[1])) {
|
||||
/* ignore */
|
||||
}
|
||||
USB_BUS_UNLOCK(bus);
|
||||
}
|
||||
/* set softc - we are ready */
|
||||
device_set_softc(dev, bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -433,6 +498,9 @@ usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat,
|
||||
mtx_init(&bus->bus_mtx, device_get_nameunit(bus->parent),
|
||||
NULL, MTX_DEF | MTX_RECURSE);
|
||||
|
||||
usb2_callout_init_mtx(&bus->power_wdog,
|
||||
&bus->bus_mtx, CALLOUT_RETURNUNLOCKED);
|
||||
|
||||
TAILQ_INIT(&bus->intr_q.head);
|
||||
|
||||
usb2_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
|
||||
|
@ -61,13 +61,35 @@ struct usb2_bus_methods {
|
||||
void (*xfer_setup) (struct usb2_setup_params *parm);
|
||||
void (*xfer_unsetup) (struct usb2_xfer *xfer);
|
||||
void (*get_dma_delay) (struct usb2_bus *, uint32_t *pdelay);
|
||||
void (*device_suspend) (struct usb2_device *udev);
|
||||
void (*device_resume) (struct usb2_device *udev);
|
||||
void (*set_hw_power) (struct usb2_bus *bus);
|
||||
/*
|
||||
* The following flag is set if one or more control transfers are
|
||||
* active:
|
||||
*/
|
||||
#define USB_HW_POWER_CONTROL 0x01
|
||||
/*
|
||||
* The following flag is set if one or more bulk transfers are
|
||||
* active:
|
||||
*/
|
||||
#define USB_HW_POWER_BULK 0x02
|
||||
/*
|
||||
* The following flag is set if one or more interrupt transfers are
|
||||
* active:
|
||||
*/
|
||||
#define USB_HW_POWER_INTERRUPT 0x04
|
||||
/*
|
||||
* The following flag is set if one or more isochronous transfers
|
||||
* are active:
|
||||
*/
|
||||
#define USB_HW_POWER_ISOC 0x08
|
||||
|
||||
/* USB Device mode only - Mandatory */
|
||||
|
||||
void (*get_hw_ep_profile) (struct usb2_device *udev, const struct usb2_hw_ep_profile **ppf, uint8_t ep_addr);
|
||||
void (*set_stall) (struct usb2_device *udev, struct usb2_xfer *xfer, struct usb2_pipe *pipe);
|
||||
void (*clear_stall) (struct usb2_device *udev, struct usb2_pipe *pipe);
|
||||
void (*rem_wakeup_set) (struct usb2_device *udev, uint8_t is_on);
|
||||
|
||||
/* USB Device mode only - Optional */
|
||||
|
||||
@ -90,7 +112,6 @@ struct usb2_pipe_methods {
|
||||
|
||||
/* Optional */
|
||||
|
||||
uint8_t (*isdone) (struct usb2_xfer *xfer);
|
||||
void *info;
|
||||
|
||||
/* Flags */
|
||||
|
@ -222,29 +222,6 @@ uss820dci_wakeup_peer(struct uss820dci_softc *sc)
|
||||
DPRINTFN(0, "not supported\n");
|
||||
}
|
||||
|
||||
static void
|
||||
uss820dci_rem_wakeup_set(struct usb2_device *udev, uint8_t is_on)
|
||||
{
|
||||
struct uss820dci_softc *sc;
|
||||
uint8_t temp;
|
||||
|
||||
DPRINTFN(5, "is_on=%u\n", is_on);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
|
||||
|
||||
sc = USS820_DCI_BUS2SC(udev->bus);
|
||||
|
||||
temp = USS820_READ_1(sc, USS820_SCR);
|
||||
|
||||
if (is_on) {
|
||||
temp |= USS820_SCR_RWUPE;
|
||||
} else {
|
||||
temp &= ~USS820_SCR_RWUPE;
|
||||
}
|
||||
|
||||
USS820_WRITE_1(sc, USS820_SCR, temp);
|
||||
}
|
||||
|
||||
static void
|
||||
uss820dci_set_address(struct uss820dci_softc *sc, uint8_t addr)
|
||||
{
|
||||
@ -1375,6 +1352,7 @@ uss820dci_init(struct uss820dci_softc *sc)
|
||||
USS820_WRITE_1(sc, USS820_SCR,
|
||||
USS820_SCR_T_IRQ |
|
||||
USS820_SCR_IE_RESET |
|
||||
/* USS820_SCR_RWUPE | */
|
||||
USS820_SCR_IE_SUSP |
|
||||
USS820_SCR_IRQPOL);
|
||||
|
||||
@ -2518,5 +2496,4 @@ 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,
|
||||
.rem_wakeup_set = &uss820dci_rem_wakeup_set,
|
||||
};
|
||||
|
@ -29,12 +29,15 @@
|
||||
#include <dev/usb2/include/usb2_standard.h>
|
||||
#include <dev/usb2/include/usb2_defs.h>
|
||||
|
||||
#define USB_DEBUG_VAR usb2_debug
|
||||
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_transfer.h>
|
||||
#include <dev/usb2/core/usb2_device.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
|
||||
#include <dev/usb2/controller/usb2_controller.h>
|
||||
#include <dev/usb2/controller/usb2_bus.h>
|
||||
@ -418,7 +421,16 @@ usb2_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
|
||||
pc->page_offset_buf = rem;
|
||||
pc->page_offset_end += rem;
|
||||
nseg--;
|
||||
|
||||
#if (USB_DEBUG != 0)
|
||||
if (rem != (USB_P2U(pc->buffer) & (USB_PAGE_SIZE - 1))) {
|
||||
/*
|
||||
* This check verifies that the physical address is correct:
|
||||
*/
|
||||
DPRINTFN(0, "Page offset was not preserved!\n");
|
||||
error = 1;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
while (nseg > 0) {
|
||||
nseg--;
|
||||
segs++;
|
||||
@ -788,7 +800,16 @@ usb2_pc_common_mem_cb(struct usb2_page_cache *pc, bus_dma_segment_t *segs,
|
||||
ext_seg = 0;
|
||||
}
|
||||
nseg--;
|
||||
|
||||
#if (USB_DEBUG != 0)
|
||||
if (rem != (USB_P2U(pc->buffer) & (USB_PAGE_SIZE - 1))) {
|
||||
/*
|
||||
* This check verifies that the physical address is correct:
|
||||
*/
|
||||
DPRINTFN(0, "Page offset was not preserved!\n");
|
||||
error = 1;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
while (nseg > 0) {
|
||||
nseg--;
|
||||
segs++;
|
||||
|
@ -440,6 +440,7 @@ uint8_t usb2_get_interface_altindex(struct usb2_interface *iface);
|
||||
usb2_error_t usb2_set_alt_interface_index(struct usb2_device *udev,
|
||||
uint8_t iface_index, uint8_t alt_index);
|
||||
uint8_t usb2_get_speed(struct usb2_device *udev);
|
||||
uint32_t usb2_get_isoc_fps(struct usb2_device *udev);
|
||||
usb2_error_t usb2_transfer_setup(struct usb2_device *udev,
|
||||
const uint8_t *ifaces, struct usb2_xfer **pxfer,
|
||||
const struct usb2_config *setup_start, uint16_t n_setup,
|
||||
@ -464,5 +465,6 @@ void usb2_set_iface_perm(struct usb2_device *udev, uint8_t iface_index,
|
||||
uint32_t uid, uint32_t gid, uint16_t mode);
|
||||
uint8_t usb2_get_bus_index(struct usb2_device *udev);
|
||||
uint8_t usb2_get_device_index(struct usb2_device *udev);
|
||||
void usb2_set_power_mode(struct usb2_device *udev, uint8_t power_mode);
|
||||
|
||||
#endif /* _USB2_CORE_H_ */
|
||||
|
@ -1186,7 +1186,7 @@ usb2_suspend_resume_sub(struct usb2_device *udev, device_t dev, uint8_t do_suspe
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_suspend_resume_device
|
||||
* usb2_suspend_resume
|
||||
*
|
||||
* The following function will suspend or resume the USB device.
|
||||
*
|
||||
@ -1339,7 +1339,13 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
|
||||
udev->bus = bus;
|
||||
udev->address = USB_START_ADDR; /* default value */
|
||||
udev->plugtime = (uint32_t)ticks;
|
||||
/*
|
||||
* We need to force the power mode to "on" because there are plenty
|
||||
* of USB devices out there that do not work very well with
|
||||
* automatic suspend and resume!
|
||||
*/
|
||||
udev->power_mode = USB_POWER_MODE_ON;
|
||||
udev->pwr_save.last_xfer_time = ticks;
|
||||
|
||||
/* we are not ready yet */
|
||||
udev->refcount = 1;
|
||||
@ -1450,7 +1456,11 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
|
||||
if (err) {
|
||||
DPRINTFN(0, "getting device descriptor "
|
||||
"at addr %d failed!\n", udev->address);
|
||||
goto done;
|
||||
/* XXX try to re-enumerate the device */
|
||||
err = usb2_req_re_enumerate(udev, &Giant);
|
||||
if (err) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
DPRINTF("adding unit addr=%d, rev=%02x, class=%d, "
|
||||
"subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n",
|
||||
@ -1546,6 +1556,7 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
|
||||
if (udev->flags.usb2_mode == USB_MODE_HOST) {
|
||||
uint8_t config_index;
|
||||
uint8_t config_quirk;
|
||||
uint8_t set_config_failed = 0;
|
||||
|
||||
/*
|
||||
* Most USB devices should attach to config index 0 by
|
||||
@ -1580,11 +1591,27 @@ repeat_set_config:
|
||||
err = usb2_set_config_index(udev, config_index);
|
||||
sx_unlock(udev->default_sx + 1);
|
||||
if (err) {
|
||||
DPRINTFN(0, "Failure selecting "
|
||||
"configuration index %u: %s, port %u, addr %u\n",
|
||||
config_index, usb2_errstr(err), udev->port_no,
|
||||
udev->address);
|
||||
|
||||
if (udev->ddesc.bNumConfigurations != 0) {
|
||||
if (!set_config_failed) {
|
||||
set_config_failed = 1;
|
||||
/* XXX try to re-enumerate the device */
|
||||
err = usb2_req_re_enumerate(
|
||||
udev, &Giant);
|
||||
if (err == 0)
|
||||
goto repeat_set_config;
|
||||
}
|
||||
DPRINTFN(0, "Failure selecting "
|
||||
"configuration index %u: %s, port %u, "
|
||||
"addr %u (ignored)\n",
|
||||
config_index, usb2_errstr(err), udev->port_no,
|
||||
udev->address);
|
||||
}
|
||||
/*
|
||||
* Some USB devices do not have any
|
||||
* configurations. Ignore any set config
|
||||
* failures!
|
||||
*/
|
||||
err = 0;
|
||||
} else if (config_quirk) {
|
||||
/* user quirk selects configuration index */
|
||||
} else if ((config_index + 1) < udev->ddesc.bNumConfigurations) {
|
||||
@ -1608,7 +1635,7 @@ repeat_set_config:
|
||||
goto repeat_set_config;
|
||||
}
|
||||
}
|
||||
} else if (usb2_test_huawei(udev, &uaa) == 0) {
|
||||
} else if (usb2_test_huawei_autoinst_p(udev, &uaa) == 0) {
|
||||
DPRINTFN(0, "Found Huawei auto-install disk!\n");
|
||||
err = USB_ERR_STALLED; /* fake an error */
|
||||
}
|
||||
@ -1670,6 +1697,11 @@ usb2_free_device(struct usb2_device *udev)
|
||||
|
||||
bus = udev->bus;
|
||||
|
||||
printf("ugen%u.%u: <%s> at %s (disconnected)\n",
|
||||
device_get_unit(bus->bdev),
|
||||
udev->device_index, udev->manufacturer,
|
||||
device_get_nameunit(bus->bdev));
|
||||
|
||||
/*
|
||||
* Destroy UGEN symlink, if any
|
||||
*/
|
||||
@ -1937,6 +1969,19 @@ usb2_get_speed(struct usb2_device *udev)
|
||||
return (udev->speed);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
usb2_get_isoc_fps(struct usb2_device *udev)
|
||||
{
|
||||
; /* indent fix */
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_LOW:
|
||||
case USB_SPEED_FULL:
|
||||
return (1000);
|
||||
default:
|
||||
return (8000);
|
||||
}
|
||||
}
|
||||
|
||||
struct usb2_device_descriptor *
|
||||
usb2_get_device_descriptor(struct usb2_device *udev)
|
||||
{
|
||||
@ -2123,3 +2168,22 @@ usb2_fifo_free_wrap(struct usb2_device *udev,
|
||||
usb2_fifo_free(f);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_peer_can_wakeup
|
||||
*
|
||||
* Return values:
|
||||
* 0: Peer cannot do resume signalling.
|
||||
* Else: Peer can do resume signalling.
|
||||
*------------------------------------------------------------------------*/
|
||||
uint8_t
|
||||
usb2_peer_can_wakeup(struct usb2_device *udev)
|
||||
{
|
||||
const struct usb2_config_descriptor *cdp;
|
||||
|
||||
cdp = udev->cdesc;
|
||||
if ((cdp != NULL) && (udev->flags.usb2_mode == USB_MODE_HOST)) {
|
||||
return (cdp->bmAttributes & UC_REMOTE_WAKEUP);
|
||||
}
|
||||
return (0); /* not supported */
|
||||
}
|
||||
|
@ -82,6 +82,18 @@ struct usb2_device_flags {
|
||||
uint8_t uq_power_claim:1; /* set if power claim quirk is present */
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure is used for power-save purposes. The data
|
||||
* in this structure is protected by the USB BUS lock.
|
||||
*/
|
||||
struct usb2_power_save {
|
||||
int last_xfer_time; /* copy of "ticks" */
|
||||
uint32_t type_refs[4]; /* transfer reference count */
|
||||
uint32_t read_refs; /* data read references */
|
||||
uint32_t write_refs; /* data write references */
|
||||
uint8_t suspended; /* set if USB device is suspended */
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure defines an USB device. There exists one of
|
||||
* these structures for every USB device.
|
||||
@ -96,6 +108,7 @@ struct usb2_device {
|
||||
struct usb2_interface ifaces[USB_IFACE_MAX];
|
||||
struct usb2_pipe default_pipe; /* Control Endpoint 0 */
|
||||
struct usb2_pipe pipes[USB_EP_MAX];
|
||||
struct usb2_power_save pwr_save;/* power save data */
|
||||
|
||||
struct usb2_bus *bus; /* our USB BUS */
|
||||
device_t parent_dev; /* parent device */
|
||||
@ -169,5 +182,6 @@ void *usb2_find_descriptor(struct usb2_device *udev, void *id,
|
||||
uint8_t iface_index, uint8_t type, uint8_t type_mask,
|
||||
uint8_t subtype, uint8_t subtype_mask);
|
||||
void usb_linux_free_device(struct usb_device *dev);
|
||||
uint8_t usb2_peer_can_wakeup(struct usb2_device *udev);
|
||||
|
||||
#endif /* _USB2_DEVICE_H_ */
|
||||
|
@ -39,6 +39,7 @@ static usb2_temp_get_desc_t usb2_temp_get_desc_w;
|
||||
static usb2_temp_setup_by_index_t usb2_temp_setup_by_index_w;
|
||||
static usb2_temp_unsetup_t usb2_temp_unsetup_w;
|
||||
static usb2_test_quirk_t usb2_test_quirk_w;
|
||||
static usb2_test_huawei_autoinst_t usb2_test_huawei_autoinst_w;
|
||||
static usb2_quirk_ioctl_t usb2_quirk_ioctl_w;
|
||||
|
||||
/* global variables */
|
||||
@ -46,6 +47,7 @@ usb2_temp_get_desc_t *usb2_temp_get_desc_p = &usb2_temp_get_desc_w;
|
||||
usb2_temp_setup_by_index_t *usb2_temp_setup_by_index_p = &usb2_temp_setup_by_index_w;
|
||||
usb2_temp_unsetup_t *usb2_temp_unsetup_p = &usb2_temp_unsetup_w;
|
||||
usb2_test_quirk_t *usb2_test_quirk_p = &usb2_test_quirk_w;
|
||||
usb2_test_huawei_autoinst_t *usb2_test_huawei_autoinst_p = &usb2_test_huawei_autoinst_w;
|
||||
usb2_quirk_ioctl_t *usb2_quirk_ioctl_p = &usb2_quirk_ioctl_w;
|
||||
devclass_t usb2_devclass_ptr = NULL;
|
||||
|
||||
@ -86,6 +88,13 @@ usb2_temp_unsetup_w(struct usb2_device *udev)
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
usb2_test_huawei_autoinst_w(struct usb2_device *udev,
|
||||
struct usb2_attach_arg *uaa)
|
||||
{
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
|
||||
void
|
||||
usb2_quirk_unload(void *arg)
|
||||
{
|
||||
@ -130,3 +139,17 @@ usb2_bus_unload(void *arg)
|
||||
|
||||
pause("WAIT", hz);
|
||||
}
|
||||
|
||||
void
|
||||
usb2_test_huawei_unload(void *arg)
|
||||
{
|
||||
/* reset function pointers */
|
||||
|
||||
usb2_test_huawei_autoinst_p = &usb2_test_huawei_autoinst_w;
|
||||
|
||||
/* wait for CPU to exit the loaded functions, if any */
|
||||
|
||||
/* XXX this is a tradeoff */
|
||||
|
||||
pause("WAIT", 16*hz);
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ struct usb2_device_request;
|
||||
|
||||
typedef usb2_error_t (usb2_temp_setup_by_index_t)(struct usb2_device *udev,
|
||||
uint16_t index);
|
||||
typedef usb2_error_t (usb2_test_huawei_autoinst_t)(struct usb2_device *udev,
|
||||
struct usb2_attach_arg *uaa);
|
||||
typedef uint8_t (usb2_test_quirk_t)(const struct usb2_lookup_info *info,
|
||||
uint16_t quirk);
|
||||
typedef int (usb2_quirk_ioctl_t)(unsigned long cmd, caddr_t data,
|
||||
@ -52,11 +54,13 @@ extern usb2_temp_get_desc_t *usb2_temp_get_desc_p;
|
||||
extern usb2_temp_setup_by_index_t *usb2_temp_setup_by_index_p;
|
||||
extern usb2_temp_unsetup_t *usb2_temp_unsetup_p;
|
||||
extern usb2_test_quirk_t *usb2_test_quirk_p;
|
||||
extern usb2_test_huawei_autoinst_t *usb2_test_huawei_autoinst_p;
|
||||
extern usb2_quirk_ioctl_t *usb2_quirk_ioctl_p;
|
||||
extern devclass_t usb2_devclass_ptr;
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
void usb2_test_huawei_unload(void *);
|
||||
void usb2_temp_unload(void *);
|
||||
void usb2_quirk_unload(void *);
|
||||
void usb2_bus_unload(void *);
|
||||
|
@ -1711,24 +1711,21 @@ ugen_set_power_mode(struct usb2_fifo *f, int mode)
|
||||
break;
|
||||
|
||||
case USB_POWER_MODE_ON:
|
||||
/* enable port */
|
||||
err = usb2_req_set_port_feature(udev->parent_hub,
|
||||
NULL, udev->port_no, UHF_PORT_ENABLE);
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case USB_POWER_MODE_SAVE:
|
||||
break;
|
||||
|
||||
case USB_POWER_MODE_RESUME:
|
||||
/* TODO: implement USB power save */
|
||||
err = usb2_req_clear_port_feature(udev->parent_hub,
|
||||
NULL, udev->port_no, UHF_PORT_SUSPEND);
|
||||
mode = USB_POWER_MODE_SAVE;
|
||||
break;
|
||||
|
||||
case USB_POWER_MODE_SUSPEND:
|
||||
/* TODO: implement USB power save */
|
||||
err = usb2_req_set_port_feature(udev->parent_hub,
|
||||
NULL, udev->port_no, UHF_PORT_SUSPEND);
|
||||
mode = USB_POWER_MODE_SAVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
@ -1736,7 +1733,8 @@ ugen_set_power_mode(struct usb2_fifo *f, int mode)
|
||||
if (err)
|
||||
return (ENXIO); /* I/O failure */
|
||||
|
||||
udev->power_mode = mode; /* update copy of power mode */
|
||||
/* set new power mode */
|
||||
usb2_set_power_mode(udev, mode);
|
||||
|
||||
return (0); /* success */
|
||||
}
|
||||
|
@ -390,10 +390,12 @@ usb2_handle_remote_wakeup(struct usb2_xfer *xfer, uint8_t is_on)
|
||||
udev->flags.remote_wakeup = 0;
|
||||
}
|
||||
|
||||
(bus->methods->rem_wakeup_set) (xfer->udev, is_on);
|
||||
|
||||
USB_BUS_UNLOCK(bus);
|
||||
|
||||
/* In case we are out of sync, update the power state. */
|
||||
|
||||
usb2_bus_power_update(udev->bus);
|
||||
|
||||
return (0); /* success */
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <dev/usb2/include/usb2_mfunc.h>
|
||||
#include <dev/usb2/include/usb2_error.h>
|
||||
#include <dev/usb2/include/usb2_standard.h>
|
||||
#include <dev/usb2/include/usb2_ioctl.h>
|
||||
|
||||
#define USB_DEBUG_VAR uhub_debug
|
||||
|
||||
@ -61,6 +62,11 @@ SYSCTL_INT(_hw_usb2_uhub, OID_AUTO, debug, CTLFLAG_RW, &uhub_debug, 0,
|
||||
"Debug level");
|
||||
#endif
|
||||
|
||||
static int usb2_power_timeout = 30; /* seconds */
|
||||
|
||||
SYSCTL_INT(_hw_usb2, OID_AUTO, power_timeout, CTLFLAG_RW,
|
||||
&usb2_power_timeout, 0, "USB power timeout");
|
||||
|
||||
struct uhub_current_state {
|
||||
uint16_t port_change;
|
||||
uint16_t port_status;
|
||||
@ -86,6 +92,8 @@ struct uhub_softc {
|
||||
static device_probe_t uhub_probe;
|
||||
static device_attach_t uhub_attach;
|
||||
static device_detach_t uhub_detach;
|
||||
static device_suspend_t uhub_suspend;
|
||||
static device_resume_t uhub_resume;
|
||||
|
||||
static bus_driver_added_t uhub_driver_added;
|
||||
static bus_child_location_str_t uhub_child_location_string;
|
||||
@ -94,6 +102,9 @@ static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
|
||||
static usb2_callback_t uhub_intr_callback;
|
||||
static usb2_callback_t uhub_intr_clear_stall_callback;
|
||||
|
||||
static void usb2_dev_resume_peer(struct usb2_device *udev);
|
||||
static void usb2_dev_suspend_peer(struct usb2_device *udev);
|
||||
|
||||
static const struct usb2_config uhub_config[2] = {
|
||||
|
||||
[0] = {
|
||||
@ -133,8 +144,8 @@ static driver_t uhub_driver =
|
||||
DEVMETHOD(device_attach, uhub_attach),
|
||||
DEVMETHOD(device_detach, uhub_detach),
|
||||
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
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),
|
||||
@ -302,8 +313,8 @@ repeat:
|
||||
|
||||
/* first clear the port connection change bit */
|
||||
|
||||
err = usb2_req_clear_port_feature
|
||||
(udev, &Giant, portno, UHF_C_PORT_CONNECTION);
|
||||
err = usb2_req_clear_port_feature(udev, &Giant,
|
||||
portno, UHF_C_PORT_CONNECTION);
|
||||
|
||||
if (err) {
|
||||
goto error;
|
||||
@ -338,6 +349,12 @@ repeat:
|
||||
|
||||
DPRINTF("Port %d is in Host Mode\n", portno);
|
||||
|
||||
if (sc->sc_st.port_status & UPS_SUSPEND) {
|
||||
DPRINTF("Port %d was still "
|
||||
"suspended, clearing.\n", portno);
|
||||
err = usb2_req_clear_port_feature(sc->sc_udev,
|
||||
&Giant, portno, UHF_PORT_SUSPEND);
|
||||
}
|
||||
/* USB Host Mode */
|
||||
|
||||
/* wait for maximum device power up time */
|
||||
@ -346,8 +363,7 @@ repeat:
|
||||
|
||||
/* reset port, which implies enabling it */
|
||||
|
||||
err = usb2_req_reset_port
|
||||
(udev, &Giant, portno);
|
||||
err = usb2_req_reset_port(udev, &Giant, portno);
|
||||
|
||||
if (err) {
|
||||
DPRINTFN(0, "port %d reset "
|
||||
@ -411,8 +427,8 @@ error:
|
||||
}
|
||||
if (err == 0) {
|
||||
if (sc->sc_st.port_status & UPS_PORT_ENABLED) {
|
||||
err = usb2_req_clear_port_feature
|
||||
(sc->sc_udev, &Giant,
|
||||
err = usb2_req_clear_port_feature(
|
||||
sc->sc_udev, &Giant,
|
||||
portno, UHF_PORT_ENABLE);
|
||||
}
|
||||
}
|
||||
@ -446,16 +462,17 @@ uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno)
|
||||
|
||||
/* first clear the port suspend change bit */
|
||||
|
||||
err = usb2_req_clear_port_feature
|
||||
(udev, &Giant, portno, UHF_C_PORT_SUSPEND);
|
||||
|
||||
err = usb2_req_clear_port_feature(udev, &Giant,
|
||||
portno, UHF_C_PORT_SUSPEND);
|
||||
if (err) {
|
||||
DPRINTF("clearing suspend failed.\n");
|
||||
goto done;
|
||||
}
|
||||
/* get fresh status */
|
||||
|
||||
err = uhub_read_port_status(sc, portno);
|
||||
if (err) {
|
||||
DPRINTF("reading port status failed.\n");
|
||||
goto done;
|
||||
}
|
||||
/* get current state */
|
||||
@ -465,12 +482,21 @@ uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno)
|
||||
} else {
|
||||
is_suspend = 0;
|
||||
}
|
||||
|
||||
DPRINTF("suspended=%u\n", is_suspend);
|
||||
|
||||
/* do the suspend or resume */
|
||||
|
||||
if (child) {
|
||||
sx_xlock(child->default_sx + 1);
|
||||
err = usb2_suspend_resume(child, is_suspend);
|
||||
sx_unlock(child->default_sx + 1);
|
||||
/*
|
||||
* This code handle two cases: 1) Host Mode - we can only
|
||||
* receive resume here 2) Device Mode - we can receive
|
||||
* suspend and resume here
|
||||
*/
|
||||
if (is_suspend == 0)
|
||||
usb2_dev_resume_peer(child);
|
||||
else if (child->flags.usb2_mode == USB_MODE_DEVICE)
|
||||
usb2_dev_suspend_peer(child);
|
||||
}
|
||||
done:
|
||||
return (err);
|
||||
@ -502,6 +528,11 @@ uhub_explore(struct usb2_device *udev)
|
||||
if (udev->depth > USB_HUB_MAX_DEPTH) {
|
||||
return (USB_ERR_TOO_DEEP);
|
||||
}
|
||||
if (udev->pwr_save.suspended) {
|
||||
/* need to wait until the child signals resume */
|
||||
DPRINTF("Device is suspended!\n");
|
||||
return (0);
|
||||
}
|
||||
for (x = 0; x != hub->nports; x++) {
|
||||
up = hub->ports + x;
|
||||
portno = x + 1;
|
||||
@ -511,6 +542,15 @@ uhub_explore(struct usb2_device *udev)
|
||||
/* most likely the HUB is gone */
|
||||
break;
|
||||
}
|
||||
if (sc->sc_st.port_change & UPS_C_OVERCURRENT_INDICATOR) {
|
||||
DPRINTF("Overcurrent on port %u.\n", portno);
|
||||
err = usb2_req_clear_port_feature(
|
||||
udev, &Giant, portno, UHF_C_PORT_OVER_CURRENT);
|
||||
if (err) {
|
||||
/* most likely the HUB is gone */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(sc->sc_flags & UHUB_FLAG_DID_EXPLORE)) {
|
||||
/*
|
||||
* Fake a connect status change so that the
|
||||
@ -750,8 +790,8 @@ uhub_attach(device_t dev)
|
||||
}
|
||||
if (!err) {
|
||||
/* turn the power on */
|
||||
err = usb2_req_set_port_feature
|
||||
(udev, &Giant, portno, UHF_PORT_POWER);
|
||||
err = usb2_req_set_port_feature(udev, &Giant,
|
||||
portno, UHF_PORT_POWER);
|
||||
}
|
||||
if (err) {
|
||||
DPRINTFN(0, "port %d power on failed, %s\n",
|
||||
@ -774,6 +814,10 @@ uhub_attach(device_t dev)
|
||||
usb2_transfer_start(sc->sc_xfer[0]);
|
||||
USB_XFER_UNLOCK(sc->sc_xfer[0]);
|
||||
|
||||
/* Enable automatic power save on all USB HUBs */
|
||||
|
||||
usb2_set_power_mode(udev, USB_POWER_MODE_SAVE);
|
||||
|
||||
return (0);
|
||||
|
||||
error:
|
||||
@ -827,6 +871,22 @@ uhub_detach(device_t dev)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
uhub_suspend(device_t dev)
|
||||
{
|
||||
DPRINTF("\n");
|
||||
/* Sub-devices are not suspended here! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
uhub_resume(device_t dev)
|
||||
{
|
||||
DPRINTF("\n");
|
||||
/* Sub-devices are not resumed here! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
uhub_driver_added(device_t dev, driver_t *driver)
|
||||
{
|
||||
@ -1334,3 +1394,441 @@ usb2_needs_explore_all(void)
|
||||
max--;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_bus_power_update
|
||||
*
|
||||
* This function will ensure that all USB devices on the given bus are
|
||||
* properly suspended or resumed according to the device transfer
|
||||
* state.
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
usb2_bus_power_update(struct usb2_bus *bus)
|
||||
{
|
||||
usb2_needs_explore(bus, 0 /* no probe */ );
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_transfer_power_ref
|
||||
*
|
||||
* This function will modify the power save reference counts and
|
||||
* wakeup the USB device associated with the given USB transfer, if
|
||||
* needed.
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
usb2_transfer_power_ref(struct usb2_xfer *xfer, int val)
|
||||
{
|
||||
static const uint32_t power_mask[4] = {
|
||||
[UE_CONTROL] = USB_HW_POWER_CONTROL,
|
||||
[UE_BULK] = USB_HW_POWER_BULK,
|
||||
[UE_INTERRUPT] = USB_HW_POWER_INTERRUPT,
|
||||
[UE_ISOCHRONOUS] = USB_HW_POWER_ISOC,
|
||||
};
|
||||
struct usb2_device *udev;
|
||||
uint8_t needs_explore;
|
||||
uint8_t needs_hw_power;
|
||||
uint8_t xfer_type;
|
||||
|
||||
udev = xfer->udev;
|
||||
|
||||
if (udev->device_index == USB_ROOT_HUB_ADDR) {
|
||||
/* no power save for root HUB */
|
||||
return;
|
||||
}
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
|
||||
xfer_type = xfer->pipe->edesc->bmAttributes & UE_XFERTYPE;
|
||||
|
||||
udev->pwr_save.last_xfer_time = ticks;
|
||||
udev->pwr_save.type_refs[xfer_type] += val;
|
||||
|
||||
if (xfer->flags_int.control_xfr) {
|
||||
udev->pwr_save.read_refs += val;
|
||||
if (xfer->flags_int.usb2_mode == USB_MODE_HOST) {
|
||||
/*
|
||||
* it is not allowed to suspend during a control
|
||||
* transfer
|
||||
*/
|
||||
udev->pwr_save.write_refs += val;
|
||||
}
|
||||
} else if (USB_GET_DATA_ISREAD(xfer)) {
|
||||
udev->pwr_save.read_refs += val;
|
||||
} else {
|
||||
udev->pwr_save.write_refs += val;
|
||||
}
|
||||
|
||||
if (udev->pwr_save.suspended)
|
||||
needs_explore =
|
||||
(udev->pwr_save.write_refs != 0) ||
|
||||
((udev->pwr_save.read_refs != 0) &&
|
||||
(usb2_peer_can_wakeup(udev) == 0));
|
||||
else
|
||||
needs_explore = 0;
|
||||
|
||||
if (!(udev->bus->hw_power_state & power_mask[xfer_type])) {
|
||||
DPRINTF("Adding type %u to power state\n", xfer_type);
|
||||
udev->bus->hw_power_state |= power_mask[xfer_type];
|
||||
needs_hw_power = 1;
|
||||
} else {
|
||||
needs_hw_power = 0;
|
||||
}
|
||||
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
if (needs_explore) {
|
||||
DPRINTF("update\n");
|
||||
usb2_bus_power_update(udev->bus);
|
||||
} else if (needs_hw_power) {
|
||||
DPRINTF("needs power\n");
|
||||
if (udev->bus->methods->set_hw_power != NULL) {
|
||||
(udev->bus->methods->set_hw_power) (udev->bus);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_bus_powerd
|
||||
*
|
||||
* This function implements the USB power daemon and is called
|
||||
* regularly from the USB explore thread.
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
usb2_bus_powerd(struct usb2_bus *bus)
|
||||
{
|
||||
struct usb2_device *udev;
|
||||
unsigned int temp;
|
||||
unsigned int limit;
|
||||
unsigned int mintime;
|
||||
uint32_t type_refs[4];
|
||||
uint8_t x;
|
||||
uint8_t rem_wakeup;
|
||||
|
||||
limit = usb2_power_timeout;
|
||||
if (limit == 0)
|
||||
limit = hz;
|
||||
else if (limit > 255)
|
||||
limit = 255 * hz;
|
||||
else
|
||||
limit = limit * hz;
|
||||
|
||||
DPRINTF("bus=%p\n", bus);
|
||||
|
||||
USB_BUS_LOCK(bus);
|
||||
|
||||
/*
|
||||
* The root HUB device is never suspended
|
||||
* and we simply skip it.
|
||||
*/
|
||||
for (x = USB_ROOT_HUB_ADDR + 1;
|
||||
x != USB_MAX_DEVICES; x++) {
|
||||
|
||||
udev = bus->devices[x];
|
||||
if (udev == NULL)
|
||||
continue;
|
||||
|
||||
rem_wakeup = usb2_peer_can_wakeup(udev);
|
||||
|
||||
temp = ticks - udev->pwr_save.last_xfer_time;
|
||||
|
||||
if ((udev->power_mode == USB_POWER_MODE_ON) ||
|
||||
(udev->pwr_save.type_refs[UE_ISOCHRONOUS] != 0) ||
|
||||
(udev->pwr_save.write_refs != 0) ||
|
||||
((udev->pwr_save.read_refs != 0) &&
|
||||
(rem_wakeup == 0))) {
|
||||
|
||||
/* check if we are suspended */
|
||||
if (udev->pwr_save.suspended != 0) {
|
||||
USB_BUS_UNLOCK(bus);
|
||||
usb2_dev_resume_peer(udev);
|
||||
USB_BUS_LOCK(bus);
|
||||
}
|
||||
} else if (temp >= limit) {
|
||||
|
||||
/* check if we are not suspended */
|
||||
if (udev->pwr_save.suspended == 0) {
|
||||
USB_BUS_UNLOCK(bus);
|
||||
usb2_dev_suspend_peer(udev);
|
||||
USB_BUS_LOCK(bus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* reset counters */
|
||||
|
||||
mintime = 0 - 1;
|
||||
type_refs[0] = 0;
|
||||
type_refs[1] = 0;
|
||||
type_refs[2] = 0;
|
||||
type_refs[3] = 0;
|
||||
|
||||
/* Re-loop all the devices to get the actual state */
|
||||
|
||||
for (x = USB_ROOT_HUB_ADDR + 1;
|
||||
x != USB_MAX_DEVICES; x++) {
|
||||
|
||||
udev = bus->devices[x];
|
||||
if (udev == NULL)
|
||||
continue;
|
||||
|
||||
/* "last_xfer_time" can be updated by a resume */
|
||||
temp = ticks - udev->pwr_save.last_xfer_time;
|
||||
|
||||
/*
|
||||
* Compute minimum time since last transfer for the complete
|
||||
* bus:
|
||||
*/
|
||||
if (temp < mintime)
|
||||
mintime = temp;
|
||||
|
||||
if (udev->pwr_save.suspended == 0) {
|
||||
type_refs[0] += udev->pwr_save.type_refs[0];
|
||||
type_refs[1] += udev->pwr_save.type_refs[1];
|
||||
type_refs[2] += udev->pwr_save.type_refs[2];
|
||||
type_refs[3] += udev->pwr_save.type_refs[3];
|
||||
}
|
||||
}
|
||||
|
||||
if (mintime >= (1 * hz)) {
|
||||
/* recompute power masks */
|
||||
DPRINTF("Recomputing power masks\n");
|
||||
bus->hw_power_state = 0;
|
||||
if (type_refs[UE_CONTROL] != 0)
|
||||
bus->hw_power_state |= USB_HW_POWER_CONTROL;
|
||||
if (type_refs[UE_BULK] != 0)
|
||||
bus->hw_power_state |= USB_HW_POWER_BULK;
|
||||
if (type_refs[UE_INTERRUPT] != 0)
|
||||
bus->hw_power_state |= USB_HW_POWER_INTERRUPT;
|
||||
if (type_refs[UE_ISOCHRONOUS] != 0)
|
||||
bus->hw_power_state |= USB_HW_POWER_ISOC;
|
||||
}
|
||||
USB_BUS_UNLOCK(bus);
|
||||
|
||||
if (bus->methods->set_hw_power != NULL) {
|
||||
/* always update hardware power! */
|
||||
(bus->methods->set_hw_power) (bus);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_dev_resume_peer
|
||||
*
|
||||
* This function will resume an USB peer and do the required USB
|
||||
* signalling to get an USB device out of the suspended state.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb2_dev_resume_peer(struct usb2_device *udev)
|
||||
{
|
||||
struct usb2_bus *bus;
|
||||
int err;
|
||||
|
||||
/* be NULL safe */
|
||||
if (udev == NULL)
|
||||
return;
|
||||
|
||||
/* check if already resumed */
|
||||
if (udev->pwr_save.suspended == 0)
|
||||
return;
|
||||
|
||||
/* we need a parent HUB to do resume */
|
||||
if (udev->parent_hub == NULL)
|
||||
return;
|
||||
|
||||
DPRINTF("udev=%p\n", udev);
|
||||
|
||||
if ((udev->flags.usb2_mode == USB_MODE_DEVICE) &&
|
||||
(udev->flags.remote_wakeup == 0)) {
|
||||
/*
|
||||
* If the host did not set the remote wakeup feature, we can
|
||||
* not wake it up either!
|
||||
*/
|
||||
DPRINTF("remote wakeup is not set!\n");
|
||||
return;
|
||||
}
|
||||
/* get bus pointer */
|
||||
bus = udev->bus;
|
||||
|
||||
/* resume parent hub first */
|
||||
usb2_dev_resume_peer(udev->parent_hub);
|
||||
|
||||
/* resume current port (Valid in Host and Device Mode) */
|
||||
err = usb2_req_clear_port_feature(udev->parent_hub,
|
||||
&Giant, udev->port_no, UHF_PORT_SUSPEND);
|
||||
if (err) {
|
||||
DPRINTFN(0, "Resuming port failed!\n");
|
||||
return;
|
||||
}
|
||||
/* resume settle time */
|
||||
usb2_pause_mtx(&Giant, USB_PORT_RESUME_DELAY);
|
||||
|
||||
if (bus->methods->device_resume != NULL) {
|
||||
/* resume USB device on the USB controller */
|
||||
(bus->methods->device_resume) (udev);
|
||||
}
|
||||
USB_BUS_LOCK(bus);
|
||||
/* set that this device is now resumed */
|
||||
udev->pwr_save.suspended = 0;
|
||||
/* make sure that we don't go into suspend right away */
|
||||
udev->pwr_save.last_xfer_time = ticks;
|
||||
|
||||
/* make sure the needed power masks are on */
|
||||
if (udev->pwr_save.type_refs[UE_CONTROL] != 0)
|
||||
bus->hw_power_state |= USB_HW_POWER_CONTROL;
|
||||
if (udev->pwr_save.type_refs[UE_BULK] != 0)
|
||||
bus->hw_power_state |= USB_HW_POWER_BULK;
|
||||
if (udev->pwr_save.type_refs[UE_INTERRUPT] != 0)
|
||||
bus->hw_power_state |= USB_HW_POWER_INTERRUPT;
|
||||
if (udev->pwr_save.type_refs[UE_ISOCHRONOUS] != 0)
|
||||
bus->hw_power_state |= USB_HW_POWER_ISOC;
|
||||
USB_BUS_UNLOCK(bus);
|
||||
|
||||
if (bus->methods->set_hw_power != NULL) {
|
||||
/* always update hardware power! */
|
||||
(bus->methods->set_hw_power) (bus);
|
||||
}
|
||||
sx_xlock(udev->default_sx + 1);
|
||||
/* notify all sub-devices about resume */
|
||||
err = usb2_suspend_resume(udev, 0);
|
||||
sx_unlock(udev->default_sx + 1);
|
||||
|
||||
/* check if peer has wakeup capability */
|
||||
if (usb2_peer_can_wakeup(udev)) {
|
||||
/* clear remote wakeup */
|
||||
err = usb2_req_clear_device_feature(udev,
|
||||
&Giant, UF_DEVICE_REMOTE_WAKEUP);
|
||||
if (err) {
|
||||
DPRINTFN(0, "Clearing device "
|
||||
"remote wakeup failed: %s!\n",
|
||||
usb2_errstr(err));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_dev_suspend_peer
|
||||
*
|
||||
* This function will suspend an USB peer and do the required USB
|
||||
* signalling to get an USB device into the suspended state.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb2_dev_suspend_peer(struct usb2_device *udev)
|
||||
{
|
||||
struct usb2_device *hub;
|
||||
struct usb2_device *child;
|
||||
uint32_t temp;
|
||||
int err;
|
||||
uint8_t x;
|
||||
uint8_t nports;
|
||||
uint8_t suspend_parent;
|
||||
|
||||
repeat:
|
||||
/* be NULL safe */
|
||||
if (udev == NULL)
|
||||
return;
|
||||
|
||||
/* check if already suspended */
|
||||
if (udev->pwr_save.suspended)
|
||||
return;
|
||||
|
||||
/* we need a parent HUB to do suspend */
|
||||
if (udev->parent_hub == NULL)
|
||||
return;
|
||||
|
||||
DPRINTF("udev=%p\n", udev);
|
||||
|
||||
/* check if all devices on the parent hub are suspended */
|
||||
hub = udev->parent_hub;
|
||||
if (hub != NULL) {
|
||||
nports = hub->hub->nports;
|
||||
suspend_parent = 1;
|
||||
|
||||
for (x = 0; x != nports; x++) {
|
||||
|
||||
child = usb2_bus_port_get_device(hub->bus,
|
||||
hub->hub->ports + x);
|
||||
|
||||
if (child == NULL)
|
||||
continue;
|
||||
|
||||
if (child->pwr_save.suspended)
|
||||
continue;
|
||||
|
||||
if (child == udev)
|
||||
continue;
|
||||
|
||||
/* another device on the HUB is not suspended */
|
||||
suspend_parent = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
suspend_parent = 0;
|
||||
}
|
||||
|
||||
sx_xlock(udev->default_sx + 1);
|
||||
/* notify all sub-devices about suspend */
|
||||
err = usb2_suspend_resume(udev, 1);
|
||||
sx_unlock(udev->default_sx + 1);
|
||||
|
||||
if (usb2_peer_can_wakeup(udev)) {
|
||||
/* allow device to do remote wakeup */
|
||||
err = usb2_req_set_device_feature(udev,
|
||||
&Giant, UF_DEVICE_REMOTE_WAKEUP);
|
||||
if (err) {
|
||||
DPRINTFN(0, "Setting device "
|
||||
"remote wakeup failed!\n");
|
||||
}
|
||||
}
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
/*
|
||||
* Set that this device is suspended. This variable must be set
|
||||
* before calling USB controller suspend callbacks.
|
||||
*/
|
||||
udev->pwr_save.suspended = 1;
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
if (udev->bus->methods->device_suspend != NULL) {
|
||||
|
||||
/* suspend device on the USB controller */
|
||||
(udev->bus->methods->device_suspend) (udev);
|
||||
|
||||
/* do DMA delay */
|
||||
temp = usb2_get_dma_delay(udev->bus);
|
||||
usb2_pause_mtx(&Giant, temp);
|
||||
|
||||
}
|
||||
/* suspend current port */
|
||||
err = usb2_req_set_port_feature(udev->parent_hub,
|
||||
&Giant, udev->port_no, UHF_PORT_SUSPEND);
|
||||
if (err) {
|
||||
DPRINTFN(0, "Suspending port failed\n");
|
||||
return;
|
||||
}
|
||||
if (suspend_parent) {
|
||||
udev = udev->parent_hub;
|
||||
goto repeat;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_set_power_mode
|
||||
*
|
||||
* This function will set the power mode, see USB_POWER_MODE_XXX for a
|
||||
* USB device.
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
usb2_set_power_mode(struct usb2_device *udev, uint8_t power_mode)
|
||||
{
|
||||
/* filter input argument */
|
||||
if (power_mode != USB_POWER_MODE_ON) {
|
||||
power_mode = USB_POWER_MODE_SAVE;
|
||||
}
|
||||
udev->power_mode = power_mode; /* update copy of power mode */
|
||||
|
||||
usb2_bus_power_update(udev->bus);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -74,5 +74,7 @@ struct usb2_device *usb2_bus_port_get_device(struct usb2_bus *bus,
|
||||
struct usb2_port *up);
|
||||
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);
|
||||
|
||||
#endif /* _USB2_HUB_H_ */
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <dev/usb2/include/usb2_mfunc.h>
|
||||
#include <dev/usb2/include/usb2_error.h>
|
||||
#include <dev/usb2/include/usb2_standard.h>
|
||||
#include <dev/usb2/include/usb2_devid.h>
|
||||
|
||||
#define USB_DEBUG_VAR usb2_debug
|
||||
|
||||
@ -577,163 +576,3 @@ done:
|
||||
free(sc, M_USB);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: The entries marked with XXX should be checked for the correct
|
||||
* speed indication to set the buffer sizes.
|
||||
*/
|
||||
static const struct usb2_device_id u3g_devs[] = {
|
||||
/* OEM: Option */
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G, U3GINFO(U3GSP_UMTS, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD, U3GINFO(U3GSP_UMTS, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GPLUS, U3GINFO(U3GSP_UMTS, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX36, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAXHSUPA, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G, U3GINFO(U3GSP_UMTS, U3GFL_NONE))},
|
||||
/* OEM: Qualcomm, Inc. */
|
||||
{USB_VPI(USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_STOR, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))},
|
||||
/* OEM: Huawei */
|
||||
{USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE, U3GINFO(U3GSP_HSDPA, U3GFL_HUAWEI_INIT))},
|
||||
{USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220, U3GINFO(U3GSP_HSPA, U3GFL_HUAWEI_INIT))},
|
||||
/* OEM: Novatel */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_CDMA_MODEM, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC950D, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U720, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740_2, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U870, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V620, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V640, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V720, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_X950D, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_XU870, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ZEROCD, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_DELL, USB_PRODUCT_DELL_U740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
/* OEM: Merlin */
|
||||
{USB_VPI(USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
/* OEM: Sierra Wireless: */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
/* Sierra TruInstaller device ID */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL, U3GINFO(U3GSP_UMTS, U3GFL_SIERRA_INIT))},
|
||||
};
|
||||
|
||||
static void
|
||||
u3g_sierra_init(struct usb2_device *udev)
|
||||
{
|
||||
struct usb2_device_request req;
|
||||
|
||||
DPRINTFN(0, "\n");
|
||||
|
||||
req.bmRequestType = UT_VENDOR;
|
||||
req.bRequest = UR_SET_INTERFACE;
|
||||
USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
|
||||
USETW(req.wIndex, UHF_PORT_CONNECTION);
|
||||
USETW(req.wLength, 0);
|
||||
|
||||
if (usb2_do_request_flags(udev, NULL, &req,
|
||||
NULL, 0, NULL, USB_MS_HZ)) {
|
||||
/* ignore any errors */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
u3g_huawei_init(struct usb2_device *udev)
|
||||
{
|
||||
struct usb2_device_request req;
|
||||
|
||||
DPRINTFN(0, "\n");
|
||||
|
||||
req.bmRequestType = UT_WRITE_DEVICE;
|
||||
req.bRequest = UR_SET_FEATURE;
|
||||
USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
|
||||
USETW(req.wIndex, UHF_PORT_SUSPEND);
|
||||
USETW(req.wLength, 0);
|
||||
|
||||
if (usb2_do_request_flags(udev, NULL, &req,
|
||||
NULL, 0, NULL, USB_MS_HZ)) {
|
||||
/* ignore any errors */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
usb2_lookup_huawei(struct usb2_attach_arg *uaa)
|
||||
{
|
||||
/* Calling the lookup function will also set the driver info! */
|
||||
return (usb2_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa));
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function handles 3G modem devices (E220, Mobile,
|
||||
* etc.) with auto-install flash disks for Windows/MacOSX on the first
|
||||
* interface. After some command or some delay they change appearance
|
||||
* to a modem.
|
||||
*/
|
||||
usb2_error_t
|
||||
usb2_test_huawei(struct usb2_device *udev, struct usb2_attach_arg *uaa)
|
||||
{
|
||||
struct usb2_interface *iface;
|
||||
struct usb2_interface_descriptor *id;
|
||||
uint32_t flags;
|
||||
|
||||
if (udev == NULL) {
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
iface = usb2_get_iface(udev, 0);
|
||||
if (iface == NULL) {
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
id = iface->idesc;
|
||||
if (id == NULL) {
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
if (id->bInterfaceClass != UICLASS_MASS) {
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
if (usb2_lookup_huawei(uaa)) {
|
||||
/* no device match */
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
flags = USB_GET_DRIVER_INFO(uaa);
|
||||
|
||||
if (flags & U3GFL_HUAWEI_INIT) {
|
||||
u3g_huawei_init(udev);
|
||||
} else if (flags & U3GFL_SCSI_EJECT) {
|
||||
return (usb2_test_autoinstall(udev, 0, 1));
|
||||
} else if (flags & U3GFL_SIERRA_INIT) {
|
||||
u3g_sierra_init(udev);
|
||||
} else {
|
||||
/* no quirks */
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
return (0); /* success */
|
||||
}
|
||||
|
@ -29,30 +29,5 @@
|
||||
|
||||
usb2_error_t usb2_test_autoinstall(struct usb2_device *udev,
|
||||
uint8_t iface_index, uint8_t do_eject);
|
||||
usb2_error_t usb2_test_huawei(struct usb2_device *udev,
|
||||
struct usb2_attach_arg *uaa);
|
||||
int usb2_lookup_huawei(struct usb2_attach_arg *uaa);
|
||||
|
||||
/* Huawei specific defines */
|
||||
|
||||
#define U3GINFO(flag,speed) ((flag)|((speed) * 256))
|
||||
#define U3G_GET_SPEED(uaa) (USB_GET_DRIVER_INFO(uaa) / 256)
|
||||
|
||||
#define U3GFL_NONE 0x00
|
||||
#define U3GFL_HUAWEI_INIT 0x01 /* Requires init command (Huawei
|
||||
* cards) */
|
||||
#define U3GFL_SCSI_EJECT 0x02 /* Requires SCSI eject command
|
||||
* (Novatel) */
|
||||
#define U3GFL_SIERRA_INIT 0x04 /* Requires init command (Sierra
|
||||
* cards) */
|
||||
|
||||
#define U3GSP_GPRS 0
|
||||
#define U3GSP_EDGE 1
|
||||
#define U3GSP_CDMA 2
|
||||
#define U3GSP_UMTS 3
|
||||
#define U3GSP_HSDPA 4
|
||||
#define U3GSP_HSUPA 5
|
||||
#define U3GSP_HSPA 6
|
||||
#define U3GSP_MAX 7
|
||||
|
||||
#endif /* _USB2_MSCTEST_H_ */
|
||||
|
@ -611,7 +611,8 @@ usb2_req_get_desc(struct usb2_device *udev, struct mtx *mtx, void *desc,
|
||||
}
|
||||
USETW(req.wLength, min_len);
|
||||
|
||||
err = usb2_do_request(udev, mtx, &req, desc);
|
||||
err = usb2_do_request_flags(udev, mtx, &req,
|
||||
desc, 0, NULL, 1000);
|
||||
|
||||
if (err) {
|
||||
if (!retries) {
|
||||
@ -1326,6 +1327,7 @@ usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx)
|
||||
struct usb2_device *parent_hub;
|
||||
usb2_error_t err;
|
||||
uint8_t old_addr;
|
||||
uint8_t do_retry = 1;
|
||||
|
||||
if (udev->flags.usb2_mode != USB_MODE_HOST) {
|
||||
return (USB_ERR_INVAL);
|
||||
@ -1335,6 +1337,7 @@ usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx)
|
||||
if (parent_hub == NULL) {
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
retry:
|
||||
err = usb2_req_reset_port(parent_hub, mtx, udev->port_no);
|
||||
if (err) {
|
||||
DPRINTFN(0, "addr=%d, port reset failed\n", old_addr);
|
||||
@ -1355,9 +1358,8 @@ usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx)
|
||||
err = usb2_req_set_address(udev, mtx, old_addr);
|
||||
if (err) {
|
||||
/* XXX ignore any errors! */
|
||||
DPRINTFN(0, "addr=%d, set address failed\n",
|
||||
DPRINTFN(0, "addr=%d, set address failed! (ignored)\n",
|
||||
old_addr);
|
||||
err = 0;
|
||||
}
|
||||
/* restore device address */
|
||||
udev->address = old_addr;
|
||||
@ -1381,7 +1383,57 @@ usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx)
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
if (err && do_retry) {
|
||||
/* give the USB firmware some time to load */
|
||||
usb2_pause_mtx(mtx, 500);
|
||||
/* no more retries after this retry */
|
||||
do_retry = 0;
|
||||
/* try again */
|
||||
goto retry;
|
||||
}
|
||||
/* restore address */
|
||||
udev->address = old_addr;
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_req_clear_device_feature
|
||||
*
|
||||
* Returns:
|
||||
* 0: Success
|
||||
* Else: Failure
|
||||
*------------------------------------------------------------------------*/
|
||||
usb2_error_t
|
||||
usb2_req_clear_device_feature(struct usb2_device *udev, struct mtx *mtx,
|
||||
uint16_t sel)
|
||||
{
|
||||
struct usb2_device_request req;
|
||||
|
||||
req.bmRequestType = UT_WRITE_DEVICE;
|
||||
req.bRequest = UR_CLEAR_FEATURE;
|
||||
USETW(req.wValue, sel);
|
||||
USETW(req.wIndex, 0);
|
||||
USETW(req.wLength, 0);
|
||||
return (usb2_do_request(udev, mtx, &req, 0));
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_req_set_device_feature
|
||||
*
|
||||
* Returns:
|
||||
* 0: Success
|
||||
* Else: Failure
|
||||
*------------------------------------------------------------------------*/
|
||||
usb2_error_t
|
||||
usb2_req_set_device_feature(struct usb2_device *udev, struct mtx *mtx,
|
||||
uint16_t sel)
|
||||
{
|
||||
struct usb2_device_request req;
|
||||
|
||||
req.bmRequestType = UT_WRITE_DEVICE;
|
||||
req.bRequest = UR_SET_FEATURE;
|
||||
USETW(req.wValue, sel);
|
||||
USETW(req.wIndex, 0);
|
||||
USETW(req.wLength, 0);
|
||||
return (usb2_do_request(udev, mtx, &req, 0));
|
||||
}
|
||||
|
@ -89,6 +89,8 @@ usb2_error_t usb2_req_set_report(struct usb2_device *udev, struct mtx *mtx,
|
||||
void *data, uint16_t len, uint8_t iface_index,
|
||||
uint8_t type, uint8_t id);
|
||||
usb2_error_t usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx);
|
||||
usb2_error_t usb2_req_clear_device_feature(struct usb2_device *udev, struct mtx *mtx, uint16_t sel);
|
||||
usb2_error_t usb2_req_set_device_feature(struct usb2_device *udev, struct mtx *mtx, uint16_t sel);
|
||||
|
||||
#define usb2_do_request(u,m,r,d) \
|
||||
usb2_do_request_flags(u,m,r,d,0,NULL,USB_DEFAULT_TIMEOUT)
|
||||
|
@ -120,7 +120,6 @@ static const struct usb2_config usb2_control_ep_cfg[USB_DEFAULT_XFER_MAX] = {
|
||||
/* function prototypes */
|
||||
|
||||
static void usb2_update_max_frame_size(struct usb2_xfer *);
|
||||
static uint32_t usb2_get_dma_delay(struct usb2_bus *);
|
||||
static void usb2_transfer_unsetup_sub(struct usb2_xfer_root *, uint8_t);
|
||||
static void usb2_control_transfer_init(struct usb2_xfer *);
|
||||
static uint8_t usb2_start_hardware_sub(struct usb2_xfer *);
|
||||
@ -161,7 +160,7 @@ usb2_update_max_frame_size(struct usb2_xfer *xfer)
|
||||
* 0: no DMA delay required
|
||||
* Else: milliseconds of DMA delay
|
||||
*------------------------------------------------------------------------*/
|
||||
static uint32_t
|
||||
uint32_t
|
||||
usb2_get_dma_delay(struct usb2_bus *bus)
|
||||
{
|
||||
uint32_t temp = 0;
|
||||
@ -1374,6 +1373,9 @@ usb2_start_hardware(struct usb2_xfer *xfer)
|
||||
/* set "transferring" flag */
|
||||
xfer->flags_int.transferring = 1;
|
||||
|
||||
/* increment power reference */
|
||||
usb2_transfer_power_ref(xfer, 1);
|
||||
|
||||
/*
|
||||
* Check if the transfer is waiting on a queue, most
|
||||
* frequently the "done_q":
|
||||
@ -1886,6 +1888,9 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
goto done;
|
||||
}
|
||||
/* decrement power reference */
|
||||
usb2_transfer_power_ref(xfer, -1);
|
||||
|
||||
xfer->flags_int.transferring = 0;
|
||||
|
||||
if (xfer->error) {
|
||||
|
@ -124,5 +124,7 @@ usb2_callback_t usb2_handle_request_callback;
|
||||
usb2_callback_t usb2_do_clear_stall_callback;
|
||||
void usb2_transfer_timeout_ms(struct usb2_xfer *xfer,
|
||||
void (*cb) (void *arg), uint32_t ms);
|
||||
uint32_t usb2_get_dma_delay(struct usb2_bus *bus);
|
||||
void usb2_transfer_power_ref(struct usb2_xfer *xfer, int val);
|
||||
|
||||
#endif /* _USB2_TRANSFER_H_ */
|
||||
|
@ -186,6 +186,7 @@ static void axe_cfg_cmd(struct axe_softc *, uint16_t, uint16_t, uint16_t,
|
||||
void *);
|
||||
static void axe_cfg_ax88178_init(struct axe_softc *);
|
||||
static void axe_cfg_ax88772_init(struct axe_softc *);
|
||||
static int axe_get_phyno(struct axe_softc *, int);
|
||||
|
||||
static const struct usb2_config axe_config[AXE_ENDPT_MAX] = {
|
||||
|
||||
@ -335,34 +336,26 @@ axe_cfg_miibus_readreg(device_t dev, int phy, int reg)
|
||||
do_unlock = 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* The chip tells us the MII address of any supported
|
||||
* PHYs attached to the chip, so only read from those.
|
||||
*/
|
||||
if (sc->sc_phyno != phy) {
|
||||
val = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((sc->sc_phyaddrs[0] != AXE_NOPHY) && (phy != sc->sc_phyaddrs[0])) {
|
||||
val = 0;
|
||||
goto done;
|
||||
}
|
||||
if ((sc->sc_phyaddrs[1] != AXE_NOPHY) && (phy != sc->sc_phyaddrs[1])) {
|
||||
val = 0;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
if ((sc->sc_phyaddrs[0] != 0xFF) && (sc->sc_phyaddrs[0] != phy)) {
|
||||
val = 0;
|
||||
goto done;
|
||||
}
|
||||
axe_cfg_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
|
||||
axe_cfg_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, &val);
|
||||
axe_cfg_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
|
||||
|
||||
val = le16toh(val);
|
||||
|
||||
if (val && (val != 0xffff)) {
|
||||
sc->sc_phyaddrs[0] = phy;
|
||||
if ((sc->sc_flags & AXE_FLAG_772) != 0 && reg == MII_BMSR) {
|
||||
/*
|
||||
* BMSR of AX88772 indicates that it supports extended
|
||||
* capability but the extended status register is
|
||||
* revered for embedded ethernet PHY. So clear the
|
||||
* extended capability bit of BMSR.
|
||||
*/
|
||||
val &= ~BMSR_EXTCAP;
|
||||
}
|
||||
|
||||
done:
|
||||
if (do_unlock) {
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
@ -386,10 +379,14 @@ axe_cfg_miibus_writereg(device_t dev, int phy, int reg, int val)
|
||||
do_unlock = 1;
|
||||
}
|
||||
|
||||
if (sc->sc_phyno != phy)
|
||||
goto done;
|
||||
|
||||
axe_cfg_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
|
||||
axe_cfg_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, &val);
|
||||
axe_cfg_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
|
||||
|
||||
done:
|
||||
if (do_unlock) {
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
}
|
||||
@ -401,6 +398,7 @@ axe_cfg_miibus_statchg(device_t dev)
|
||||
{
|
||||
struct axe_softc *sc = device_get_softc(dev);
|
||||
struct mii_data *mii = GET_MII(sc);
|
||||
struct ifnet *ifp;
|
||||
uint16_t val;
|
||||
uint8_t do_unlock;
|
||||
|
||||
@ -412,15 +410,40 @@ axe_cfg_miibus_statchg(device_t dev)
|
||||
do_unlock = 1;
|
||||
}
|
||||
|
||||
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
|
||||
val = AXE_MEDIA_FULL_DUPLEX;
|
||||
else
|
||||
val = 0;
|
||||
ifp = sc->sc_ifp;
|
||||
if (mii == NULL || ifp == NULL ||
|
||||
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
goto done;
|
||||
|
||||
if (sc->sc_flags & (AXE_FLAG_772 | AXE_FLAG_178)) {
|
||||
sc->sc_flags &= ~AXE_FLAG_LINK;
|
||||
if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
|
||||
(IFM_ACTIVE | IFM_AVALID)) {
|
||||
switch (IFM_SUBTYPE(mii->mii_media_active)) {
|
||||
case IFM_10_T:
|
||||
case IFM_100_TX:
|
||||
sc->sc_flags |= AXE_FLAG_LINK;
|
||||
break;
|
||||
case IFM_1000_T:
|
||||
if ((sc->sc_flags & AXE_FLAG_178) == 0)
|
||||
break;
|
||||
sc->sc_flags |= AXE_FLAG_LINK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
val |= (AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC);
|
||||
/* Lost link, do nothing. */
|
||||
if ((sc->sc_flags & AXE_FLAG_LINK) == 0)
|
||||
goto done;
|
||||
|
||||
val = 0;
|
||||
if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
|
||||
val |= AXE_MEDIA_FULL_DUPLEX;
|
||||
if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) {
|
||||
val |= AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC;
|
||||
if ((sc->sc_flags & AXE_FLAG_178) != 0)
|
||||
val |= AXE_178_MEDIA_ENCK;
|
||||
switch (IFM_SUBTYPE(mii->mii_media_active)) {
|
||||
case IFM_1000_T:
|
||||
val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK;
|
||||
@ -434,6 +457,7 @@ axe_cfg_miibus_statchg(device_t dev)
|
||||
}
|
||||
}
|
||||
axe_cfg_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL);
|
||||
done:
|
||||
if (do_unlock) {
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
}
|
||||
@ -467,7 +491,6 @@ axe_cfg_ifmedia_upd(struct axe_softc *sc,
|
||||
/* not ready */
|
||||
return;
|
||||
}
|
||||
sc->sc_flags |= AXE_FLAG_WAIT_LINK;
|
||||
|
||||
if (mii->mii_instance) {
|
||||
struct mii_softc *miisc;
|
||||
@ -550,6 +573,30 @@ axe_cfg_reset(struct axe_softc *sc)
|
||||
err = usb2_config_td_sleep(&sc->sc_config_td, hz / 100);
|
||||
}
|
||||
|
||||
static int
|
||||
axe_get_phyno(struct axe_softc *sc, int sel)
|
||||
{
|
||||
int phyno;
|
||||
|
||||
switch (AXE_PHY_TYPE(sc->sc_phyaddrs[sel])) {
|
||||
case PHY_TYPE_100_HOME:
|
||||
case PHY_TYPE_GIG:
|
||||
phyno = AXE_PHY_NO(sc->sc_phyaddrs[sel]);
|
||||
break;
|
||||
case PHY_TYPE_SPECIAL:
|
||||
/* FALLTHROUGH */
|
||||
case PHY_TYPE_RSVD:
|
||||
/* FALLTHROUGH */
|
||||
case PHY_TYPE_NON_SUP:
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
phyno = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return (phyno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe for a AX88172 chip.
|
||||
*/
|
||||
@ -617,8 +664,6 @@ axe_attach(device_t dev)
|
||||
}
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
|
||||
sc->sc_flags |= AXE_FLAG_WAIT_LINK;
|
||||
|
||||
/* start setup */
|
||||
|
||||
usb2_config_td_queue_command
|
||||
@ -687,6 +732,9 @@ axe_cfg_ax88178_init(struct axe_softc *sc)
|
||||
axe_cfg_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
|
||||
AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL);
|
||||
err = usb2_config_td_sleep(&sc->sc_config_td, hz / 4);
|
||||
/* Enable MII/GMII/RGMII interface to work with external PHY. */
|
||||
axe_cfg_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0, NULL);
|
||||
err = usb2_config_td_sleep(&sc->sc_config_td, hz / 4);
|
||||
|
||||
axe_cfg_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
|
||||
}
|
||||
@ -701,7 +749,7 @@ axe_cfg_ax88772_init(struct axe_softc *sc)
|
||||
axe_cfg_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL);
|
||||
err = usb2_config_td_sleep(&sc->sc_config_td, hz / 16);
|
||||
|
||||
if (sc->sc_phyaddrs[1] == AXE_INTPHY) {
|
||||
if (sc->sc_phyno == AXE_772_PHY_NO_EPHY) {
|
||||
/* ask for the embedded PHY */
|
||||
axe_cfg_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL);
|
||||
err = usb2_config_td_sleep(&sc->sc_config_td, hz / 64);
|
||||
@ -752,6 +800,19 @@ axe_cfg_first_time_setup(struct axe_softc *sc,
|
||||
* Load PHY indexes first. Needed by axe_xxx_init().
|
||||
*/
|
||||
axe_cfg_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, sc->sc_phyaddrs);
|
||||
#if 1
|
||||
device_printf(sc->sc_dev, "PHYADDR 0x%02x:0x%02x\n",
|
||||
sc->sc_phyaddrs[0], sc->sc_phyaddrs[1]);
|
||||
#endif
|
||||
sc->sc_phyno = axe_get_phyno(sc, AXE_PHY_SEL_PRI);
|
||||
if (sc->sc_phyno == -1)
|
||||
sc->sc_phyno = axe_get_phyno(sc, AXE_PHY_SEL_SEC);
|
||||
if (sc->sc_phyno == -1) {
|
||||
device_printf(sc->sc_dev,
|
||||
"no valid PHY address found, "
|
||||
"assuming PHY address 0\n");
|
||||
sc->sc_phyno = 0;
|
||||
}
|
||||
|
||||
if (sc->sc_flags & AXE_FLAG_178) {
|
||||
axe_cfg_ax88178_init(sc);
|
||||
@ -771,12 +832,6 @@ axe_cfg_first_time_setup(struct axe_softc *sc,
|
||||
*/
|
||||
axe_cfg_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->sc_ipgs);
|
||||
|
||||
/*
|
||||
* Work around broken adapters that appear to lie about
|
||||
* their PHY addresses.
|
||||
*/
|
||||
sc->sc_phyaddrs[0] = sc->sc_phyaddrs[1] = 0xFF;
|
||||
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
|
||||
ifp = if_alloc(IFT_ETHER);
|
||||
@ -1108,7 +1163,7 @@ axe_bulk_write_callback(struct usb2_xfer *xfer)
|
||||
usb2_transfer_start(sc->sc_xfer[2]);
|
||||
goto done;
|
||||
}
|
||||
if (sc->sc_flags & AXE_FLAG_WAIT_LINK) {
|
||||
if ((sc->sc_flags & AXE_FLAG_LINK) == 0) {
|
||||
/*
|
||||
* don't send anything if there is no link !
|
||||
*/
|
||||
@ -1204,19 +1259,17 @@ axe_cfg_tick(struct axe_softc *sc,
|
||||
return;
|
||||
}
|
||||
mii_tick(mii);
|
||||
|
||||
mii_pollstat(mii);
|
||||
|
||||
if ((sc->sc_flags & AXE_FLAG_WAIT_LINK) &&
|
||||
(mii->mii_media_status & IFM_ACTIVE) &&
|
||||
(IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)) {
|
||||
sc->sc_flags &= ~AXE_FLAG_WAIT_LINK;
|
||||
}
|
||||
sc->sc_media_active = mii->mii_media_active;
|
||||
sc->sc_media_status = mii->mii_media_status;
|
||||
|
||||
if ((sc->sc_flags & AXE_FLAG_LINK) == 0) {
|
||||
axe_cfg_miibus_statchg(sc->sc_dev);
|
||||
/* XXX */
|
||||
if ((sc->sc_flags & AXE_FLAG_LINK) == 0) {
|
||||
sc->sc_media_active = IFM_ETHER | IFM_NONE;
|
||||
sc->sc_media_status = IFM_AVALID;
|
||||
}
|
||||
}
|
||||
/* start stopped transfers, if any */
|
||||
|
||||
axe_start_transfers(sc);
|
||||
}
|
||||
|
||||
@ -1444,7 +1497,7 @@ axe_cfg_pre_stop(struct axe_softc *sc,
|
||||
sc->sc_flags &= ~(AXE_FLAG_HL_READY |
|
||||
AXE_FLAG_LL_READY);
|
||||
|
||||
sc->sc_flags |= AXE_FLAG_WAIT_LINK;
|
||||
sc->sc_flags &= ~AXE_FLAG_LINK;
|
||||
|
||||
/*
|
||||
* stop all the transfers, if not already stopped:
|
||||
|
@ -135,8 +135,23 @@
|
||||
#define AXE_178_RXCMD_MFB_8192 0x0200
|
||||
#define AXE_178_RXCMD_MFB_16384 0x0300
|
||||
|
||||
#define AXE_NOPHY 0xE0
|
||||
#define AXE_INTPHY 0x10
|
||||
#define AXE_PHY_SEL_PRI 1
|
||||
#define AXE_PHY_SEL_SEC 0
|
||||
#define AXE_PHY_TYPE_MASK 0xE0
|
||||
#define AXE_PHY_TYPE_SHIFT 5
|
||||
#define AXE_PHY_TYPE(x) \
|
||||
(((x) & AXE_PHY_TYPE_MASK) >> AXE_PHY_TYPE_SHIFT)
|
||||
|
||||
#define PHY_TYPE_100_HOME 0 /* 10/100 or 1M HOME PHY */
|
||||
#define PHY_TYPE_GIG 1 /* Gigabit PHY */
|
||||
#define PHY_TYPE_SPECIAL 4 /* Special case */
|
||||
#define PHY_TYPE_RSVD 5 /* Reserved */
|
||||
#define PHY_TYPE_NON_SUP 7 /* Non-supported PHY */
|
||||
|
||||
#define AXE_PHY_NO_MASK 0x1F
|
||||
#define AXE_PHY_NO(x) ((x) & AXE_PHY_NO_MASK)
|
||||
|
||||
#define AXE_772_PHY_NO_EPHY 0x10 /* Embedded 10/100 PHY of AX88772 */
|
||||
|
||||
#define AXE_BULK_BUF_SIZE 16384 /* bytes */
|
||||
|
||||
@ -170,12 +185,14 @@ struct axe_softc {
|
||||
device_t sc_miibus;
|
||||
device_t sc_dev;
|
||||
|
||||
int sc_phyno;
|
||||
|
||||
uint32_t sc_unit;
|
||||
uint32_t sc_media_active;
|
||||
uint32_t sc_media_status;
|
||||
|
||||
uint16_t sc_flags;
|
||||
#define AXE_FLAG_WAIT_LINK 0x0001
|
||||
#define AXE_FLAG_LINK 0x0001
|
||||
#define AXE_FLAG_INTR_STALL 0x0002
|
||||
#define AXE_FLAG_READ_STALL 0x0004
|
||||
#define AXE_FLAG_WRITE_STALL 0x0008
|
||||
|
@ -266,6 +266,7 @@ static const struct usb2_device_id uscanner_devs[] = {
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4100C, 0)},
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4200C, 0)},
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4300C, 0)},
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4470C, 0)},
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4670V, 0)},
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_S20, 0)},
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_5200C, 0)},
|
||||
|
@ -4,7 +4,7 @@
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
*
|
||||
* generated from:
|
||||
* FreeBSD: head/sys/dev/usb/usbdevs 185998 2008-12-12 18:34:27Z thompsa
|
||||
* FreeBSD: src/sys/dev/usb/usbdevs,v 1.390 2008/12/23 13:09:17 remko Exp
|
||||
*/
|
||||
/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
|
||||
|
||||
@ -533,6 +533,7 @@
|
||||
#define USB_VENDOR_FOSSIL 0x0e67 /* Fossil, Inc */
|
||||
#define USB_VENDOR_GMATE 0x0e7e /* G.Mate, Inc */
|
||||
#define USB_VENDOR_OTI 0x0ea0 /* Ours Technology */
|
||||
#define USB_VENDOR_YISO 0x0eab /* Yiso Wireless Co. */
|
||||
#define USB_VENDOR_PILOTECH 0x0eaf /* Pilotech */
|
||||
#define USB_VENDOR_NOVATECH 0x0eb0 /* NovaTech */
|
||||
#define USB_VENDOR_ITEGNO 0x0eba /* iTegno */
|
||||
@ -814,6 +815,7 @@
|
||||
/* Alcor Micro, Inc. products */
|
||||
#define USB_PRODUCT_ALCOR2_KBD_HUB 0x2802 /* Kbd Hub */
|
||||
|
||||
#define USB_PRODUCT_ALCOR_TRANSCEND 0x6387 /* Transcend JetFlash Drive */
|
||||
#define USB_PRODUCT_ALCOR_MA_KBD_HUB 0x9213 /* MacAlly Kbd Hub */
|
||||
#define USB_PRODUCT_ALCOR_AU9814 0x9215 /* AU9814 Hub */
|
||||
#define USB_PRODUCT_ALCOR_UMCR_9361 0x9361 /* USB Multimedia Card Reader */
|
||||
@ -1286,6 +1288,7 @@
|
||||
#define USB_PRODUCT_FTDI_EMCU2D 0xe88a /* Expert mouseCLOCK USB II */
|
||||
#define USB_PRODUCT_FTDI_PCMSFU 0xe88b /* Precision Clock MSF USB */
|
||||
#define USB_PRODUCT_FTDI_EMCU2H 0xe88c /* Expert mouseCLOCK USB II HBG */
|
||||
#define USB_PRODUCT_FTDI_MAXSTREAM 0xee18 /* Maxstream PKG-U */
|
||||
#define USB_PRODUCT_FTDI_USBSERIAL 0xfa00 /* Matrix Orbital USB Serial */
|
||||
#define USB_PRODUCT_FTDI_MX2_3 0xfa01 /* Matrix Orbital MX2 or MX3 */
|
||||
#define USB_PRODUCT_FTDI_MX4_5 0xfa02 /* Matrix Orbital MX4 or MX5 */
|
||||
@ -1423,6 +1426,7 @@
|
||||
#define USB_PRODUCT_HP_2200C 0x0605 /* ScanJet 2200C */
|
||||
#define USB_PRODUCT_HP_5300C 0x0701 /* Scanjet 5300C */
|
||||
#define USB_PRODUCT_HP_4400C 0x0705 /* Scanjet 4400C */
|
||||
#define USB_PRODUCT_HP_4470C 0x0805 /* Scanjet 4470C */
|
||||
#define USB_PRODUCT_HP_82x0C 0x0b01 /* Scanjet 82x0C */
|
||||
#define USB_PRODUCT_HP_2300D 0x0b17 /* Laserjet 2300d */
|
||||
#define USB_PRODUCT_HP_970CSE 0x1004 /* Deskjet 970Cse */
|
||||
@ -2008,6 +2012,7 @@
|
||||
#define USB_PRODUCT_QUALCOMM2_CDMA_MSM 0x3196 /* CDMA Technologies MSM modem */
|
||||
#define USB_PRODUCT_QUALCOMMINC_CDMA_MSM 0x0001 /* CDMA Technologies MSM modem */
|
||||
#define USB_PRODUCT_QUALCOMMINC_ZTE_STOR 0x2000 /* USB ZTE Storage */
|
||||
#define USB_PRODUCT_QUALCOMMINC_AC8700 0xfffe /* CDMA 1xEVDO USB modem */
|
||||
|
||||
/* Qtronix products */
|
||||
#define USB_PRODUCT_QTRONIX_980N 0x2011 /* Scorpion-980N keyboard */
|
||||
@ -2469,6 +2474,9 @@
|
||||
#define USB_PRODUCT_YANO_U640MO 0x0101 /* U640MO-03 */
|
||||
#define USB_PRODUCT_YANO_FW800HD 0x05fc /* METALWEAR-HDD */
|
||||
|
||||
/* Yiso Wireless Co. products */
|
||||
#define USB_PRODUCT_YISO_C893 0xc893 /* CDMA 2000 1xEVDO PC Card */
|
||||
|
||||
/* Z-Com products */
|
||||
#define USB_PRODUCT_ZCOM_M4Y750 0x0001 /* M4Y-750 */
|
||||
#define USB_PRODUCT_ZCOM_XI725 0x0002 /* XI-725/726 */
|
||||
|
@ -4,7 +4,7 @@
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
*
|
||||
* generated from:
|
||||
* FreeBSD: head/sys/dev/usb/usbdevs 185998 2008-12-12 18:34:27Z thompsa
|
||||
* FreeBSD: src/sys/dev/usb/usbdevs,v 1.390 2008/12/23 13:09:17 remko Exp
|
||||
*/
|
||||
/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
|
||||
|
||||
@ -622,6 +622,12 @@ const struct usb_knowndev usb_knowndevs[] = {
|
||||
"Alcor Micro",
|
||||
"Kbd Hub",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_TRANSCEND,
|
||||
0,
|
||||
"Alcor Micro",
|
||||
"Transcend JetFlash Drive",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_MA_KBD_HUB,
|
||||
0,
|
||||
@ -2494,6 +2500,12 @@ const struct usb_knowndev usb_knowndevs[] = {
|
||||
"Future Technology Devices",
|
||||
"Expert mouseCLOCK USB II HBG",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MAXSTREAM,
|
||||
0,
|
||||
"Future Technology Devices",
|
||||
"Maxstream PKG-U",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_FTDI, USB_PRODUCT_FTDI_USBSERIAL,
|
||||
0,
|
||||
@ -3040,6 +3052,12 @@ const struct usb_knowndev usb_knowndevs[] = {
|
||||
"Hewlett Packard",
|
||||
"Scanjet 4400C",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_HP, USB_PRODUCT_HP_4470C,
|
||||
0,
|
||||
"Hewlett Packard",
|
||||
"Scanjet 4470C",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_HP, USB_PRODUCT_HP_82x0C,
|
||||
0,
|
||||
@ -5470,6 +5488,12 @@ const struct usb_knowndev usb_knowndevs[] = {
|
||||
"Qualcomm, Incorporated",
|
||||
"USB ZTE Storage",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_AC8700,
|
||||
0,
|
||||
"Qualcomm, Incorporated",
|
||||
"CDMA 1xEVDO USB modem",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N,
|
||||
0,
|
||||
@ -7144,6 +7168,12 @@ const struct usb_knowndev usb_knowndevs[] = {
|
||||
"Yano",
|
||||
"METALWEAR-HDD",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_YISO, USB_PRODUCT_YISO_C893,
|
||||
0,
|
||||
"Yiso Wireless Co.",
|
||||
"CDMA 2000 1xEVDO PC Card",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_M4Y750,
|
||||
0,
|
||||
@ -10054,6 +10084,12 @@ const struct usb_knowndev usb_knowndevs[] = {
|
||||
"Ours Technology",
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
USB_VENDOR_YISO, 0,
|
||||
USB_KNOWNDEV_NOPROD,
|
||||
"Yiso Wireless Co.",
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
USB_VENDOR_PILOTECH, 0,
|
||||
USB_KNOWNDEV_NOPROD,
|
||||
|
@ -39,13 +39,6 @@
|
||||
#define USB_DEVICE_NAME "usb"
|
||||
#define USB_GENERIC_NAME "ugen"
|
||||
|
||||
/* definition of USB power mode */
|
||||
#define USB_POWER_MODE_OFF 0 /* turn off device */
|
||||
#define USB_POWER_MODE_ON 1 /* always on */
|
||||
#define USB_POWER_MODE_SAVE 2 /* automatic suspend and resume */
|
||||
#define USB_POWER_MODE_SUSPEND 3 /* force suspend */
|
||||
#define USB_POWER_MODE_RESUME 4 /* force resume */
|
||||
|
||||
struct usb2_read_dir {
|
||||
void *urd_data;
|
||||
uint32_t urd_startentry;
|
||||
|
@ -48,12 +48,20 @@
|
||||
#define USB_POWER_DOWN_TIME 200 /* ms */
|
||||
#define USB_PORT_POWER_DOWN_TIME 100 /* ms */
|
||||
|
||||
/* Definition of software USB power modes */
|
||||
#define USB_POWER_MODE_OFF 0 /* turn off device */
|
||||
#define USB_POWER_MODE_ON 1 /* always on */
|
||||
#define USB_POWER_MODE_SAVE 2 /* automatic suspend and resume */
|
||||
#define USB_POWER_MODE_SUSPEND 3 /* force suspend */
|
||||
#define USB_POWER_MODE_RESUME 4 /* force resume */
|
||||
|
||||
#if 0
|
||||
/* These are the values from the USB specification. */
|
||||
#define USB_PORT_RESET_DELAY 10 /* ms */
|
||||
#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */
|
||||
#define USB_PORT_RESET_RECOVERY 10 /* ms */
|
||||
#define USB_PORT_POWERUP_DELAY 100 /* ms */
|
||||
#define USB_PORT_RESUME_DELAY 20 /* ms */
|
||||
#define USB_SET_ADDRESS_SETTLE 2 /* ms */
|
||||
#define USB_RESUME_DELAY (20*5) /* ms */
|
||||
#define USB_RESUME_WAIT 10 /* ms */
|
||||
@ -65,6 +73,7 @@
|
||||
#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */
|
||||
#define USB_PORT_RESET_RECOVERY 250 /* ms */
|
||||
#define USB_PORT_POWERUP_DELAY 300 /* ms */
|
||||
#define USB_PORT_RESUME_DELAY (20*2) /* ms */
|
||||
#define USB_SET_ADDRESS_SETTLE 10 /* ms */
|
||||
#define USB_RESUME_DELAY (50*5) /* ms */
|
||||
#define USB_RESUME_WAIT 50 /* ms */
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <dev/usb2/include/usb2_standard.h>
|
||||
#include <dev/usb2/include/usb2_mfunc.h>
|
||||
#include <dev/usb2/include/usb2_error.h>
|
||||
#include <dev/usb2/include/usb2_cdc.h>
|
||||
#include <dev/usb2/include/usb2_defs.h>
|
||||
|
||||
#define USB_DEBUG_VAR u3g_debug
|
||||
|
||||
@ -50,6 +50,8 @@
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_msctest.h>
|
||||
#include <dev/usb2/core/usb2_dynamic.h>
|
||||
#include <dev/usb2/core/usb2_device.h>
|
||||
|
||||
#include <dev/usb2/serial/usb2_serial.h>
|
||||
|
||||
@ -66,6 +68,20 @@ SYSCTL_INT(_hw_usb2_u3g, OID_AUTO, debug, CTLFLAG_RW,
|
||||
#define U3G_CONFIG_INDEX 0
|
||||
#define U3G_BSIZE 2048
|
||||
|
||||
#define U3GSP_GPRS 0
|
||||
#define U3GSP_EDGE 1
|
||||
#define U3GSP_CDMA 2
|
||||
#define U3GSP_UMTS 3
|
||||
#define U3GSP_HSDPA 4
|
||||
#define U3GSP_HSUPA 5
|
||||
#define U3GSP_HSPA 6
|
||||
#define U3GSP_MAX 7
|
||||
|
||||
#define U3GFL_NONE 0x00 /* No flags */
|
||||
#define U3GFL_HUAWEI_INIT 0x01 /* Init command required */
|
||||
#define U3GFL_SCSI_EJECT 0x02 /* SCSI eject command required */
|
||||
#define U3GFL_SIERRA_INIT 0x04 /* Init command required */
|
||||
|
||||
struct u3g_speeds_s {
|
||||
uint32_t ispeed;
|
||||
uint32_t ospeed;
|
||||
@ -98,6 +114,8 @@ static void u3g_stop_read(struct usb2_com_softc *ucom);
|
||||
static void u3g_start_write(struct usb2_com_softc *ucom);
|
||||
static void u3g_stop_write(struct usb2_com_softc *ucom);
|
||||
|
||||
static int u3g_driver_loaded(struct module *mod, int what, void *arg);
|
||||
|
||||
static const struct usb2_config u3g_config[U3G_N_TRANSFER] = {
|
||||
|
||||
[0] = {
|
||||
@ -151,10 +169,195 @@ static driver_t u3g_driver = {
|
||||
.size = sizeof(struct u3g_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(u3g, ushub, u3g_driver, u3g_devclass, NULL, 0);
|
||||
DRIVER_MODULE(u3g, ushub, u3g_driver, u3g_devclass, u3g_driver_loaded, 0);
|
||||
MODULE_DEPEND(u3g, usb2_serial, 1, 1, 1);
|
||||
MODULE_DEPEND(u3g, usb2_core, 1, 1, 1);
|
||||
|
||||
/* Huawei specific defines */
|
||||
|
||||
#define U3GINFO(flag,speed) ((flag)|((speed) * 256))
|
||||
#define U3G_GET_SPEED(uaa) (USB_GET_DRIVER_INFO(uaa) / 256)
|
||||
|
||||
/*
|
||||
* NOTE: The entries marked with XXX should be checked for the correct
|
||||
* speed indication to set the buffer sizes.
|
||||
*/
|
||||
static const struct usb2_device_id u3g_devs[] = {
|
||||
/* OEM: Option */
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G, U3GINFO(U3GSP_UMTS, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD, U3GINFO(U3GSP_UMTS, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GPLUS, U3GINFO(U3GSP_UMTS, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX36, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAXHSUPA, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G, U3GINFO(U3GSP_UMTS, U3GFL_NONE))},
|
||||
/* OEM: Qualcomm, Inc. */
|
||||
{USB_VPI(USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_STOR, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))},
|
||||
/* OEM: Huawei */
|
||||
{USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE, U3GINFO(U3GSP_HSDPA, U3GFL_HUAWEI_INIT))},
|
||||
{USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220, U3GINFO(U3GSP_HSPA, U3GFL_HUAWEI_INIT))},
|
||||
/* OEM: Novatel */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_CDMA_MODEM, U3GINFO(U3GSP_CDMA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC950D, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U720, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740_2, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U870, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V620, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V640, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V720, U3GINFO(U3GSP_UMTS, U3GFL_SCSI_EJECT))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_X950D, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_XU870, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ZEROCD, U3GINFO(U3GSP_HSUPA, U3GFL_SCSI_EJECT))},
|
||||
{USB_VPI(USB_VENDOR_DELL, USB_PRODUCT_DELL_U740, U3GINFO(U3GSP_HSDPA, U3GFL_SCSI_EJECT))},
|
||||
/* OEM: Merlin */
|
||||
{USB_VPI(USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
/* OEM: Sierra Wireless: */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_HS2300, U3GINFO(U3GSP_HSDPA, U3GFL_NONE))},
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781, U3GINFO(U3GSP_UMTS, U3GFL_NONE))}, /* XXX */
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_HS2300, U3GINFO(U3GSP_HSPA, U3GFL_NONE))}, /* XXX */
|
||||
/* Sierra TruInstaller device ID */
|
||||
{USB_VPI(USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL, U3GINFO(U3GSP_UMTS, U3GFL_SIERRA_INIT))},
|
||||
};
|
||||
|
||||
static void
|
||||
u3g_sierra_init(struct usb2_device *udev)
|
||||
{
|
||||
struct usb2_device_request req;
|
||||
|
||||
DPRINTFN(0, "\n");
|
||||
|
||||
req.bmRequestType = UT_VENDOR;
|
||||
req.bRequest = UR_SET_INTERFACE;
|
||||
USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
|
||||
USETW(req.wIndex, UHF_PORT_CONNECTION);
|
||||
USETW(req.wLength, 0);
|
||||
|
||||
if (usb2_do_request_flags(udev, NULL, &req,
|
||||
NULL, 0, NULL, USB_MS_HZ)) {
|
||||
/* ignore any errors */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
u3g_huawei_init(struct usb2_device *udev)
|
||||
{
|
||||
struct usb2_device_request req;
|
||||
|
||||
DPRINTFN(0, "\n");
|
||||
|
||||
req.bmRequestType = UT_WRITE_DEVICE;
|
||||
req.bRequest = UR_SET_FEATURE;
|
||||
USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
|
||||
USETW(req.wIndex, UHF_PORT_SUSPEND);
|
||||
USETW(req.wLength, 0);
|
||||
|
||||
if (usb2_do_request_flags(udev, NULL, &req,
|
||||
NULL, 0, NULL, USB_MS_HZ)) {
|
||||
/* ignore any errors */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
u3g_lookup_huawei(struct usb2_attach_arg *uaa)
|
||||
{
|
||||
/* Calling the lookup function will also set the driver info! */
|
||||
return (usb2_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa));
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function handles 3G modem devices (E220, Mobile,
|
||||
* etc.) with auto-install flash disks for Windows/MacOSX on the first
|
||||
* interface. After some command or some delay they change appearance
|
||||
* to a modem.
|
||||
*/
|
||||
static usb2_error_t
|
||||
u3g_test_huawei_autoinst(struct usb2_device *udev,
|
||||
struct usb2_attach_arg *uaa)
|
||||
{
|
||||
struct usb2_interface *iface;
|
||||
struct usb2_interface_descriptor *id;
|
||||
uint32_t flags;
|
||||
|
||||
if (udev == NULL) {
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
iface = usb2_get_iface(udev, 0);
|
||||
if (iface == NULL) {
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
id = iface->idesc;
|
||||
if (id == NULL) {
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
if (id->bInterfaceClass != UICLASS_MASS) {
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
if (u3g_lookup_huawei(uaa)) {
|
||||
/* no device match */
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
flags = USB_GET_DRIVER_INFO(uaa);
|
||||
|
||||
if (flags & U3GFL_HUAWEI_INIT) {
|
||||
u3g_huawei_init(udev);
|
||||
} else if (flags & U3GFL_SCSI_EJECT) {
|
||||
return (usb2_test_autoinstall(udev, 0, 1));
|
||||
} else if (flags & U3GFL_SIERRA_INIT) {
|
||||
u3g_sierra_init(udev);
|
||||
} else {
|
||||
/* no quirks */
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
return (0); /* success */
|
||||
}
|
||||
|
||||
static int
|
||||
u3g_driver_loaded(struct module *mod, int what, void *arg)
|
||||
{
|
||||
switch (what) {
|
||||
case MOD_LOAD:
|
||||
/* register our autoinstall handler */
|
||||
usb2_test_huawei_autoinst_p = &u3g_test_huawei_autoinst;
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
usb2_test_huawei_unload(NULL);
|
||||
break;
|
||||
default:
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
u3g_probe(device_t self)
|
||||
{
|
||||
@ -169,7 +372,7 @@ u3g_probe(device_t self)
|
||||
if (uaa->info.bInterfaceClass != UICLASS_VENDOR) {
|
||||
return (ENXIO);
|
||||
}
|
||||
return (usb2_lookup_huawei(uaa));
|
||||
return (u3g_lookup_huawei(uaa));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -196,8 +196,6 @@ static const struct usb2_device_id uchcom_devs[] = {
|
||||
|
||||
/* protypes */
|
||||
|
||||
static int uchcom_ioctl(struct usb2_com_softc *, uint32_t, caddr_t, int,
|
||||
struct thread *);
|
||||
static int uchcom_pre_param(struct usb2_com_softc *, struct termios *);
|
||||
static void uchcom_cfg_get_status(struct usb2_com_softc *, uint8_t *,
|
||||
uint8_t *);
|
||||
@ -297,7 +295,6 @@ struct usb2_com_callback uchcom_callback = {
|
||||
.usb2_com_cfg_set_break = &uchcom_cfg_set_break,
|
||||
.usb2_com_cfg_param = &uchcom_cfg_param,
|
||||
.usb2_com_pre_param = &uchcom_pre_param,
|
||||
.usb2_com_ioctl = &uchcom_ioctl,
|
||||
.usb2_com_start_read = &uchcom_start_read,
|
||||
.usb2_com_stop_read = &uchcom_stop_read,
|
||||
.usb2_com_start_write = &uchcom_start_write,
|
||||
@ -738,13 +735,6 @@ uchcom_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr)
|
||||
*msr = sc->sc_msr;
|
||||
}
|
||||
|
||||
static int
|
||||
uchcom_ioctl(struct usb2_com_softc *ucom, uint32_t cmd, caddr_t data, int flag,
|
||||
struct thread *td)
|
||||
{
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
static void
|
||||
uchcom_cfg_set_dtr(struct usb2_com_softc *ucom, uint8_t onoff)
|
||||
{
|
||||
|
@ -249,6 +249,7 @@ static struct usb2_device_id uftdi_devs[] = {
|
||||
{USB_VPI(USB_VENDOR_FTDI, USB_PRODUCT_FTDI_EMCU2D, UFTDI_TYPE_8U232AM)},
|
||||
{USB_VPI(USB_VENDOR_FTDI, USB_PRODUCT_FTDI_PCMSFU, UFTDI_TYPE_8U232AM)},
|
||||
{USB_VPI(USB_VENDOR_FTDI, USB_PRODUCT_FTDI_EMCU2H, UFTDI_TYPE_8U232AM)},
|
||||
{USB_VPI(USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MAXSTREAM, UFTDI_TYPE_8U232AM)},
|
||||
{USB_VPI(USB_VENDOR_SIIG2, USB_PRODUCT_SIIG2_US2308, UFTDI_TYPE_8U232AM)},
|
||||
{USB_VPI(USB_VENDOR_INTREPIDCS, USB_PRODUCT_INTREPIDCS_VALUECAN, UFTDI_TYPE_8U232AM)},
|
||||
{USB_VPI(USB_VENDOR_INTREPIDCS, USB_PRODUCT_INTREPIDCS_NEOVI, UFTDI_TYPE_8U232AM)},
|
||||
@ -470,6 +471,7 @@ uftdi_read_callback(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct uftdi_softc *sc = xfer->priv_sc;
|
||||
uint8_t buf[2];
|
||||
uint8_t ftdi_msr;
|
||||
uint8_t msr;
|
||||
uint8_t lsr;
|
||||
|
||||
@ -481,9 +483,19 @@ uftdi_read_callback(struct usb2_xfer *xfer)
|
||||
}
|
||||
usb2_copy_out(xfer->frbuffers, 0, buf, 2);
|
||||
|
||||
msr = FTDI_GET_MSR(buf);
|
||||
ftdi_msr = FTDI_GET_MSR(buf);
|
||||
lsr = FTDI_GET_LSR(buf);
|
||||
|
||||
msr = 0;
|
||||
if (ftdi_msr & FTDI_SIO_CTS_MASK)
|
||||
msr |= SER_CTS;
|
||||
if (ftdi_msr & FTDI_SIO_DSR_MASK)
|
||||
msr |= SER_DSR;
|
||||
if (ftdi_msr & FTDI_SIO_RI_MASK)
|
||||
msr |= SER_RI;
|
||||
if (ftdi_msr & FTDI_SIO_RLSD_MASK)
|
||||
msr |= SER_DCD;
|
||||
|
||||
if ((sc->sc_msr != msr) ||
|
||||
((sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK))) {
|
||||
DPRINTF("status change msr=0x%02x (0x%02x) "
|
||||
|
@ -171,8 +171,6 @@ static void uplcom_start_write(struct usb2_com_softc *);
|
||||
static void uplcom_stop_write(struct usb2_com_softc *);
|
||||
static void uplcom_cfg_get_status(struct usb2_com_softc *, uint8_t *,
|
||||
uint8_t *);
|
||||
static int uplcom_ioctl(struct usb2_com_softc *, uint32_t, caddr_t, int,
|
||||
struct thread *);
|
||||
static void uplcom_cfg_do_request(struct uplcom_softc *,
|
||||
struct usb2_device_request *, void *);
|
||||
|
||||
@ -260,7 +258,6 @@ struct usb2_com_callback uplcom_callback = {
|
||||
.usb2_com_cfg_set_break = &uplcom_cfg_set_break,
|
||||
.usb2_com_cfg_param = &uplcom_cfg_param,
|
||||
.usb2_com_pre_param = &uplcom_pre_param,
|
||||
.usb2_com_ioctl = &uplcom_ioctl,
|
||||
.usb2_com_start_read = &uplcom_start_read,
|
||||
.usb2_com_stop_read = &uplcom_stop_read,
|
||||
.usb2_com_start_write = &uplcom_start_write,
|
||||
@ -768,13 +765,6 @@ uplcom_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr)
|
||||
*msr = sc->sc_msr;
|
||||
}
|
||||
|
||||
static int
|
||||
uplcom_ioctl(struct usb2_com_softc *ucom, uint32_t cmd, caddr_t data, int flag,
|
||||
struct thread *td)
|
||||
{
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
static void
|
||||
uplcom_intr_callback(struct usb2_xfer *xfer)
|
||||
{
|
||||
|
@ -172,8 +172,6 @@ static void uvscom_start_write(struct usb2_com_softc *);
|
||||
static void uvscom_stop_write(struct usb2_com_softc *);
|
||||
static void uvscom_cfg_get_status(struct usb2_com_softc *, uint8_t *,
|
||||
uint8_t *);
|
||||
static int uvscom_ioctl(struct usb2_com_softc *, uint32_t, caddr_t, int,
|
||||
struct thread *);
|
||||
static void uvscom_cfg_write(struct uvscom_softc *, uint8_t, uint16_t);
|
||||
static uint16_t uvscom_cfg_read_status(struct uvscom_softc *);
|
||||
|
||||
@ -247,7 +245,6 @@ static const struct usb2_com_callback uvscom_callback = {
|
||||
.usb2_com_cfg_close = &uvscom_cfg_close,
|
||||
.usb2_com_pre_open = &uvscom_pre_open,
|
||||
.usb2_com_pre_param = &uvscom_pre_param,
|
||||
.usb2_com_ioctl = &uvscom_ioctl,
|
||||
.usb2_com_start_read = &uvscom_start_read,
|
||||
.usb2_com_stop_read = &uvscom_stop_read,
|
||||
.usb2_com_start_write = &uvscom_start_write,
|
||||
@ -753,13 +750,6 @@ uvscom_cfg_get_status(struct usb2_com_softc *ucom, uint8_t *lsr, uint8_t *msr)
|
||||
*msr = sc->sc_msr;
|
||||
}
|
||||
|
||||
static int
|
||||
uvscom_ioctl(struct usb2_com_softc *ucom, uint32_t cmd, caddr_t data, int fflag,
|
||||
struct thread *td)
|
||||
{
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
static void
|
||||
uvscom_cfg_write(struct uvscom_softc *sc, uint8_t index, uint16_t value)
|
||||
{
|
||||
|
@ -80,22 +80,27 @@
|
||||
#include <dev/sound/chip.h>
|
||||
#include "feeder_if.h"
|
||||
|
||||
static int uaudio_default_rate = 96000;
|
||||
static int uaudio_default_bits = 32;
|
||||
static int uaudio_default_channels = 2;
|
||||
|
||||
#if USB_DEBUG
|
||||
static int uaudio_debug = 0;
|
||||
|
||||
SYSCTL_NODE(_hw_usb2, OID_AUTO, uaudio, CTLFLAG_RW, 0, "USB uaudio");
|
||||
SYSCTL_INT(_hw_usb2_uaudio, OID_AUTO, debug, CTLFLAG_RW,
|
||||
&uaudio_debug, 0, "uaudio debug level");
|
||||
SYSCTL_INT(_hw_usb2_uaudio, OID_AUTO, default_rate, CTLFLAG_RW,
|
||||
&uaudio_default_rate, 0, "uaudio default sample rate");
|
||||
SYSCTL_INT(_hw_usb2_uaudio, OID_AUTO, default_bits, CTLFLAG_RW,
|
||||
&uaudio_default_bits, 0, "uaudio default sample bits");
|
||||
SYSCTL_INT(_hw_usb2_uaudio, OID_AUTO, default_channels, CTLFLAG_RW,
|
||||
&uaudio_default_channels, 0, "uaudio default sample channels");
|
||||
#endif
|
||||
|
||||
static uint32_t uaudio_default_rate = 96000;
|
||||
static uint8_t uaudio_default_bits = 32;
|
||||
static uint8_t uaudio_default_channels = 2;
|
||||
|
||||
#define UAUDIO_MINFRAMES 16 /* must be factor of 8 due HS-USB */
|
||||
#define UAUDIO_NCHANBUFS 2 /* number of outstanding request */
|
||||
#define UAUDIO_NFRAMES 25 /* ms of sound in each request */
|
||||
#define UAUDIO_RECURSE_LIMIT 24 /* rounds */
|
||||
#define UAUDIO_DEFAULT_BUFSZ ((2 * 96000 * 4 * 2) / (1000 / UAUDIO_NCHANBUFS)) /* bytes */
|
||||
|
||||
#define MAKE_WORD(h,l) (((h) << 8) | (l))
|
||||
#define BIT_TEST(bm,bno) (((bm)[(bno) / 8] >> (7 - ((bno) % 8))) & 1)
|
||||
@ -154,6 +159,7 @@ struct uaudio_chan {
|
||||
uint8_t *cur; /* current position in upper layer
|
||||
* buffer */
|
||||
|
||||
uint32_t intr_size; /* in bytes */
|
||||
uint32_t block_size;
|
||||
uint32_t sample_rate;
|
||||
uint32_t format;
|
||||
@ -389,13 +395,13 @@ static const char *uaudio_mixer_get_terminal_name(uint16_t);
|
||||
#endif
|
||||
|
||||
static const struct usb2_config
|
||||
uaudio_cfg_record_full_speed[UAUDIO_NCHANBUFS] = {
|
||||
uaudio_cfg_record[UAUDIO_NCHANBUFS] = {
|
||||
[0] = {
|
||||
.type = UE_ISOCHRONOUS,
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_IN,
|
||||
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
|
||||
.mh.frames = UAUDIO_NFRAMES,
|
||||
.mh.frames = UAUDIO_MINFRAMES,
|
||||
.mh.flags = {.short_xfer_ok = 1,},
|
||||
.mh.callback = &uaudio_chan_record_callback,
|
||||
},
|
||||
@ -405,43 +411,20 @@ static const struct usb2_config
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_IN,
|
||||
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
|
||||
.mh.frames = UAUDIO_NFRAMES,
|
||||
.mh.frames = UAUDIO_MINFRAMES,
|
||||
.mh.flags = {.short_xfer_ok = 1,},
|
||||
.mh.callback = &uaudio_chan_record_callback,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb2_config
|
||||
uaudio_cfg_record_high_speed[UAUDIO_NCHANBUFS] = {
|
||||
[0] = {
|
||||
.type = UE_ISOCHRONOUS,
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_IN,
|
||||
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
|
||||
.mh.frames = (UAUDIO_NFRAMES * 8),
|
||||
.mh.flags = {.short_xfer_ok = 1,},
|
||||
.mh.callback = &uaudio_chan_record_callback,
|
||||
},
|
||||
|
||||
[1] = {
|
||||
.type = UE_ISOCHRONOUS,
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_IN,
|
||||
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
|
||||
.mh.frames = (UAUDIO_NFRAMES * 8),
|
||||
.mh.flags = {.short_xfer_ok = 1,},
|
||||
.mh.callback = &uaudio_chan_record_callback,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb2_config
|
||||
uaudio_cfg_play_full_speed[UAUDIO_NCHANBUFS] = {
|
||||
uaudio_cfg_play[UAUDIO_NCHANBUFS] = {
|
||||
[0] = {
|
||||
.type = UE_ISOCHRONOUS,
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_OUT,
|
||||
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
|
||||
.mh.frames = UAUDIO_NFRAMES,
|
||||
.mh.frames = UAUDIO_MINFRAMES,
|
||||
.mh.flags = {.short_xfer_ok = 1,},
|
||||
.mh.callback = &uaudio_chan_play_callback,
|
||||
},
|
||||
@ -451,30 +434,7 @@ static const struct usb2_config
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_OUT,
|
||||
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
|
||||
.mh.frames = UAUDIO_NFRAMES,
|
||||
.mh.flags = {.short_xfer_ok = 1,},
|
||||
.mh.callback = &uaudio_chan_play_callback,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb2_config
|
||||
uaudio_cfg_play_high_speed[UAUDIO_NCHANBUFS] = {
|
||||
[0] = {
|
||||
.type = UE_ISOCHRONOUS,
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_OUT,
|
||||
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
|
||||
.mh.frames = (UAUDIO_NFRAMES * 8),
|
||||
.mh.flags = {.short_xfer_ok = 1,},
|
||||
.mh.callback = &uaudio_chan_play_callback,
|
||||
},
|
||||
|
||||
[1] = {
|
||||
.type = UE_ISOCHRONOUS,
|
||||
.endpoint = UE_ADDR_ANY,
|
||||
.direction = UE_DIR_OUT,
|
||||
.mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
|
||||
.mh.frames = (UAUDIO_NFRAMES * 8),
|
||||
.mh.frames = UAUDIO_MINFRAMES,
|
||||
.mh.flags = {.short_xfer_ok = 1,},
|
||||
.mh.callback = &uaudio_chan_play_callback,
|
||||
},
|
||||
@ -706,10 +666,6 @@ uaudio_attach_sub(device_t dev, kobj_class_t mixer_class, kobj_class_t chan_clas
|
||||
struct uaudio_softc *sc = device_get_softc(device_get_parent(dev));
|
||||
char status[SND_STATUSLEN];
|
||||
|
||||
if (bootverbose) {
|
||||
device_printf(dev, "using a default buffer "
|
||||
"size of %u bytes\n", UAUDIO_DEFAULT_BUFSZ);
|
||||
}
|
||||
uaudio_mixer_init(sc);
|
||||
|
||||
if (sc->sc_uq_audio_swap_lr) {
|
||||
@ -1066,19 +1022,20 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb2_device *udev,
|
||||
chan->iface_index = curidx;
|
||||
chan->iface_alt_index = alt_index;
|
||||
|
||||
chan->usb2_cfg =
|
||||
(ep_dir == UE_DIR_IN) ?
|
||||
((fps == 1000) ?
|
||||
uaudio_cfg_record_full_speed :
|
||||
uaudio_cfg_record_high_speed) :
|
||||
((fps == 1000) ?
|
||||
uaudio_cfg_play_full_speed :
|
||||
uaudio_cfg_play_high_speed);
|
||||
|
||||
if (ep_dir == UE_DIR_IN)
|
||||
chan->usb2_cfg =
|
||||
uaudio_cfg_record;
|
||||
else
|
||||
chan->usb2_cfg =
|
||||
uaudio_cfg_play;
|
||||
|
||||
sample_size = ((chan->p_asf1d->bNrChannels *
|
||||
chan->p_asf1d->bBitResolution) / 8);
|
||||
|
||||
/*
|
||||
* NOTE: "chan->bytes_per_frame"
|
||||
* should not be zero!
|
||||
*/
|
||||
chan->bytes_per_frame = ((rate / fps) * sample_size);
|
||||
|
||||
if (sc->sc_sndstat_valid) {
|
||||
@ -1103,15 +1060,26 @@ uaudio_chan_fill_info(struct uaudio_softc *sc, struct usb2_device *udev)
|
||||
{
|
||||
uint32_t rate = uaudio_default_rate;
|
||||
uint32_t z;
|
||||
uint16_t fps = (usb2_get_speed(udev) == USB_SPEED_HIGH) ? 8000 : 1000;
|
||||
uint16_t fps = usb2_get_isoc_fps(udev);
|
||||
uint8_t bits = uaudio_default_bits;
|
||||
uint8_t y;
|
||||
uint8_t channels = uaudio_default_channels;
|
||||
uint8_t x;
|
||||
|
||||
bits -= (bits % 8);
|
||||
if ((bits == 0) || (bits > 32)) {
|
||||
/* set a valid value */
|
||||
bits = 32;
|
||||
}
|
||||
rate -= (rate % fps);
|
||||
|
||||
if ((rate == 0) || (rate > 192000)) {
|
||||
/* set a valid value */
|
||||
rate = 192000 - (192000 % fps);
|
||||
}
|
||||
if ((channels == 0) || (channels > 2)) {
|
||||
/* set a valid value */
|
||||
channels = 2;
|
||||
}
|
||||
if (sbuf_new(&sc->sc_sndstat, NULL, 4096, SBUF_AUTOEXTEND)) {
|
||||
sc->sc_sndstat_valid = 1;
|
||||
}
|
||||
@ -1141,21 +1109,23 @@ uaudio_chan_play_callback(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct uaudio_chan *ch = xfer->priv_sc;
|
||||
uint32_t *p_len = xfer->frlengths;
|
||||
uint32_t total = (sndbuf_getblkcnt(ch->pcm_buf) *
|
||||
sndbuf_getblksz(ch->pcm_buf)) / 2;
|
||||
uint32_t total;
|
||||
uint32_t blockcount;
|
||||
uint32_t n;
|
||||
uint32_t offset;
|
||||
|
||||
/* allow dynamic sizing of play buffer */
|
||||
total = ch->intr_size;
|
||||
|
||||
/* allow dynamic sizing of play buffer */
|
||||
blockcount = total / ch->bytes_per_frame;
|
||||
|
||||
/* align to 8 units */
|
||||
blockcount &= ~7;
|
||||
/* align units */
|
||||
blockcount -= (blockcount % UAUDIO_MINFRAMES);
|
||||
|
||||
/* range check - min */
|
||||
if (blockcount == 0) {
|
||||
blockcount = 8;
|
||||
blockcount = UAUDIO_MINFRAMES;
|
||||
}
|
||||
/* range check - max */
|
||||
if (blockcount > xfer->max_frame_count) {
|
||||
@ -1230,21 +1200,23 @@ uaudio_chan_record_callback(struct usb2_xfer *xfer)
|
||||
uint32_t *p_len = xfer->frlengths;
|
||||
uint32_t n;
|
||||
uint32_t m;
|
||||
uint32_t total = (sndbuf_getblkcnt(ch->pcm_buf) *
|
||||
sndbuf_getblksz(ch->pcm_buf)) / 2;
|
||||
uint32_t total;
|
||||
uint32_t blockcount;
|
||||
uint32_t offset0;
|
||||
uint32_t offset1;
|
||||
|
||||
/* allow dynamic sizing of play buffer */
|
||||
total = ch->intr_size;
|
||||
|
||||
/* allow dynamic sizing of play buffer */
|
||||
blockcount = total / ch->bytes_per_frame;
|
||||
|
||||
/* align to 8 units */
|
||||
blockcount &= ~7;
|
||||
/* align units */
|
||||
blockcount -= (blockcount % UAUDIO_MINFRAMES);
|
||||
|
||||
/* range check - min */
|
||||
if (blockcount == 0) {
|
||||
blockcount = 8;
|
||||
blockcount = UAUDIO_MINFRAMES;
|
||||
}
|
||||
/* range check - max */
|
||||
if (blockcount > xfer->max_frame_count) {
|
||||
@ -1326,21 +1298,30 @@ uaudio_chan_init(struct uaudio_softc *sc, struct snd_dbuf *b,
|
||||
{
|
||||
struct uaudio_chan *ch = ((dir == PCMDIR_PLAY) ?
|
||||
&sc->sc_play_chan : &sc->sc_rec_chan);
|
||||
uint32_t buf_size;
|
||||
uint8_t endpoint;
|
||||
uint8_t iface_index;
|
||||
uint8_t alt_index;
|
||||
usb2_error_t err;
|
||||
|
||||
ch->buf = malloc(UAUDIO_DEFAULT_BUFSZ, M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
/* compute required buffer size */
|
||||
buf_size = (ch->bytes_per_frame * UAUDIO_MINFRAMES);
|
||||
|
||||
/* setup interrupt interval */
|
||||
ch->intr_size = buf_size;
|
||||
|
||||
/* double buffering */
|
||||
buf_size *= 2;
|
||||
|
||||
ch->buf = malloc(buf_size, M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
if (ch->buf == NULL) {
|
||||
goto error;
|
||||
}
|
||||
if (sndbuf_setup(b, ch->buf, UAUDIO_DEFAULT_BUFSZ) != 0) {
|
||||
if (sndbuf_setup(b, ch->buf, buf_size) != 0) {
|
||||
goto error;
|
||||
}
|
||||
ch->start = ch->buf;
|
||||
ch->end = ch->buf + UAUDIO_DEFAULT_BUFSZ;
|
||||
ch->end = ch->buf + buf_size;
|
||||
ch->cur = ch->buf;
|
||||
ch->pcm_ch = c;
|
||||
ch->pcm_mtx = c->lock;
|
||||
@ -1437,16 +1418,14 @@ int
|
||||
uaudio_chan_set_param_fragments(struct uaudio_chan *ch, uint32_t blocksize,
|
||||
uint32_t blockcount)
|
||||
{
|
||||
uint32_t max = sndbuf_getmaxsize(ch->pcm_buf);
|
||||
|
||||
RANGE(blocksize, 128, max / 2);
|
||||
|
||||
blockcount = max / blocksize;
|
||||
RANGE(blockcount, 2, 512);
|
||||
/* we only support one size */
|
||||
blocksize = ch->intr_size;
|
||||
blockcount = 2;
|
||||
|
||||
if ((sndbuf_getblksz(ch->pcm_buf) != blocksize) ||
|
||||
(sndbuf_getblkcnt(ch->pcm_buf) != blockcount)) {
|
||||
|
||||
DPRINTFN(1, "resizing to %u x "
|
||||
"%u bytes\n", blockcount, blocksize);
|
||||
if (sndbuf_resize(ch->pcm_buf, blockcount, blocksize)) {
|
||||
DPRINTFN(0, "failed to resize sound buffer, count=%u, "
|
||||
"size=%u\n", blockcount, blocksize);
|
||||
@ -2672,7 +2651,10 @@ uaudio_mixer_fill_info(struct uaudio_softc *sc, struct usb2_device *udev,
|
||||
DPRINTF("invalid Audio Control header\n");
|
||||
goto done;
|
||||
}
|
||||
wTotalLen = UGETW(cd->wTotalLength);
|
||||
/* "wTotalLen" is allowed to be corrupt */
|
||||
wTotalLen = UGETW(acdp->wTotalLength) - acdp->bLength;
|
||||
|
||||
/* get USB audio revision */
|
||||
sc->sc_audio_rev = UGETW(acdp->bcdADC);
|
||||
|
||||
DPRINTFN(3, "found AC header, vers=%03x, len=%d\n",
|
||||
|
@ -400,6 +400,10 @@ static const struct umass_devdescr umass_devdescr[] = {
|
||||
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
|
||||
NO_GETMAXLUN
|
||||
},
|
||||
{USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_TRANSCEND, RID_WILDCARD,
|
||||
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
|
||||
NO_GETMAXLUN
|
||||
},
|
||||
{USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO230, RID_WILDCARD,
|
||||
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
|
||||
NO_INQUIRY
|
||||
@ -636,10 +640,10 @@ static const struct umass_devdescr umass_devdescr[] = {
|
||||
UMASS_PROTO_SCSI,
|
||||
NO_GETMAXLUN
|
||||
},
|
||||
{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_SDS_HOTFIND_D, RID_WILDCARD,
|
||||
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
|
||||
NO_GETMAXLUN | NO_SYNCHRONIZE_CACHE
|
||||
},
|
||||
{USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_SDS_HOTFIND_D, RID_WILDCARD,
|
||||
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
|
||||
NO_GETMAXLUN | NO_SYNCHRONIZE_CACHE
|
||||
},
|
||||
{USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFMS_RW, RID_WILDCARD,
|
||||
UMASS_PROTO_SCSI,
|
||||
NO_QUIRKS
|
||||
|
@ -1301,6 +1301,7 @@ ustorage_fs_mode_select(struct ustorage_fs_softc *sc)
|
||||
static uint8_t
|
||||
ustorage_fs_synchronize_cache(struct ustorage_fs_softc *sc)
|
||||
{
|
||||
#if 0
|
||||
struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
|
||||
uint8_t rc;
|
||||
|
||||
@ -1311,6 +1312,7 @@ ustorage_fs_synchronize_cache(struct ustorage_fs_softc *sc)
|
||||
if (rc) {
|
||||
currlun->sense_data = SS_WRITE_ERROR;
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,6 @@ static const struct usb2_device_id ural_devs[] = {
|
||||
{USB_VPI(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570, 0)},
|
||||
{USB_VPI(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_2, 0)},
|
||||
{USB_VPI(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_3, 0)},
|
||||
{USB_VPI(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573, 0)},
|
||||
{USB_VPI(USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_WL54G, 0)},
|
||||
{USB_VPI(USB_VENDOR_SMC, USB_PRODUCT_SMC_2862WG, 0)},
|
||||
{USB_VPI(USB_VENDOR_SPHAIRON, USB_PRODUCT_SPHAIRON_UB801R, 0)},
|
||||
@ -787,8 +786,9 @@ ural_cfg_first_time_setup(struct ural_softc *sc,
|
||||
/* retrieve MAC address and various other things from EEPROM */
|
||||
ural_cfg_read_eeprom(sc);
|
||||
|
||||
printf("%s: MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
|
||||
sc->sc_name, sc->sc_asic_rev, ural_get_rf(sc->sc_rf_rev));
|
||||
printf("%s: MAC/BBP RT2570 (rev 0x%02x), RF %s (0x%02x)\n",
|
||||
sc->sc_name, sc->sc_asic_rev, ural_get_rf(sc->sc_rf_rev),
|
||||
sc->sc_rf_rev);
|
||||
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
|
||||
@ -958,8 +958,11 @@ ural_config_copy(struct ural_softc *sc,
|
||||
static const char *
|
||||
ural_get_rf(int rev)
|
||||
{
|
||||
; /* style fix */
|
||||
|
||||
switch (rev) {
|
||||
case RAL_RF_2522:return "RT2522";
|
||||
case RAL_RF_2522:
|
||||
return "RT2522";
|
||||
case RAL_RF_2523:
|
||||
return "RT2523";
|
||||
case RAL_RF_2524:
|
||||
|
@ -155,6 +155,7 @@ static int zyd_newstate_cb(struct ieee80211vap *,
|
||||
static void zyd_cfg_amrr_start(struct zyd_softc *);
|
||||
static void zyd_update_mcast_cb(struct ifnet *);
|
||||
static void zyd_update_promisc_cb(struct ifnet *);
|
||||
static void zyd_cfg_get_macaddr(struct zyd_softc *sc);
|
||||
|
||||
static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY;
|
||||
static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB;
|
||||
@ -758,6 +759,17 @@ zyd_cfg_rfwrite(struct zyd_softc *sc, uint32_t value)
|
||||
zyd_cfg_cmd(sc, ZYD_CMD_RFCFG, &req, 4 + (2 * rf->width), NULL, 0, 0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* zyd_cfg_rfwrite_cr
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
zyd_cfg_rfwrite_cr(struct zyd_softc *sc, uint32_t val)
|
||||
{
|
||||
zyd_cfg_write16(sc, ZYD_CR244, (val >> 16) & 0xff);
|
||||
zyd_cfg_write16(sc, ZYD_CR243, (val >> 8) & 0xff);
|
||||
zyd_cfg_write16(sc, ZYD_CR242, (val >> 0) & 0xff);
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_bulk_read_clear_stall_callback(struct usb2_xfer *xfer)
|
||||
{
|
||||
@ -1148,10 +1160,24 @@ zyd_cfg_unlock_phy(struct zyd_softc *sc)
|
||||
static void
|
||||
zyd_cfg_set_beacon_interval(struct zyd_softc *sc, uint32_t bintval)
|
||||
{
|
||||
/* XXX this is probably broken.. */
|
||||
zyd_cfg_write32(sc, ZYD_CR_ATIM_WND_PERIOD, bintval - 2);
|
||||
zyd_cfg_write32(sc, ZYD_CR_PRE_TBTT, bintval - 1);
|
||||
zyd_cfg_write32(sc, ZYD_CR_BCN_INTERVAL, bintval);
|
||||
uint32_t val;
|
||||
|
||||
zyd_cfg_read32(sc, ZYD_CR_ATIM_WND_PERIOD, &val);
|
||||
sc->sc_atim_wnd = val;
|
||||
zyd_cfg_read32(sc, ZYD_CR_PRE_TBTT, &val);
|
||||
sc->sc_pre_tbtt = val;
|
||||
sc->sc_bcn_int = bintval;
|
||||
|
||||
if (sc->sc_bcn_int <= 5)
|
||||
sc->sc_bcn_int = 5;
|
||||
if (sc->sc_pre_tbtt < 4 || sc->sc_pre_tbtt >= sc->sc_bcn_int)
|
||||
sc->sc_pre_tbtt = sc->sc_bcn_int - 1;
|
||||
if (sc->sc_atim_wnd >= sc->sc_pre_tbtt)
|
||||
sc->sc_atim_wnd = sc->sc_pre_tbtt - 1;
|
||||
|
||||
zyd_cfg_write32(sc, ZYD_CR_ATIM_WND_PERIOD, sc->sc_atim_wnd);
|
||||
zyd_cfg_write32(sc, ZYD_CR_PRE_TBTT, sc->sc_pre_tbtt);
|
||||
zyd_cfg_write32(sc, ZYD_CR_BCN_INTERVAL, sc->sc_bcn_int);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1163,7 +1189,7 @@ zyd_rf_name(uint8_t type)
|
||||
static const char *const zyd_rfs[] = {
|
||||
"unknown", "unknown", "UW2451", "UCHIP", "AL2230",
|
||||
"AL7230B", "THETA", "AL2210", "MAXIM_NEW", "GCT",
|
||||
"PV2000", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2",
|
||||
"AL2230S", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2",
|
||||
"PHILIPS"
|
||||
};
|
||||
|
||||
@ -1235,36 +1261,106 @@ static void
|
||||
zyd_cfg_rf_al2230_init(struct zyd_softc *sc, struct zyd_rf *rf)
|
||||
{
|
||||
static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY;
|
||||
static const uint32_t rfini[] = ZYD_AL2230_RF;
|
||||
static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT;
|
||||
static const struct zyd_phy_pair phypll[] = {
|
||||
{ZYD_CR251, 0x2f}, {ZYD_CR251, 0x3f},
|
||||
{ZYD_CR138, 0x28}, {ZYD_CR203, 0x06}
|
||||
};
|
||||
static const uint32_t rfini1[] = ZYD_AL2230_RF_PART1;
|
||||
static const uint32_t rfini2[] = ZYD_AL2230_RF_PART2;
|
||||
static const uint32_t rfini3[] = ZYD_AL2230_RF_PART3;
|
||||
uint32_t i;
|
||||
|
||||
/* init RF-dependent PHY registers */
|
||||
for (i = 0; i != INDEXES(phyini); i++) {
|
||||
for (i = 0; i != INDEXES(phyini); i++)
|
||||
zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val);
|
||||
}
|
||||
|
||||
/* init AL2230 radio */
|
||||
for (i = 0; i != INDEXES(rfini); i++) {
|
||||
zyd_cfg_rfwrite(sc, rfini[i]);
|
||||
if ((sc->sc_rf_rev == ZYD_RF_AL2230S) || (sc->sc_al2230s != 0)) {
|
||||
for (i = 0; i != INDEXES(phy2230s); i++)
|
||||
zyd_cfg_write16(sc, phy2230s[i].reg, phy2230s[i].val);
|
||||
}
|
||||
/* init AL2230 radio */
|
||||
for (i = 0; i != INDEXES(rfini1); i++)
|
||||
zyd_cfg_rfwrite(sc, rfini1[i]);
|
||||
|
||||
if ((sc->sc_rf_rev == ZYD_RF_AL2230S) || (sc->sc_al2230s != 0))
|
||||
zyd_cfg_rfwrite(sc, 0x000824);
|
||||
else
|
||||
zyd_cfg_rfwrite(sc, 0x0005a4);
|
||||
|
||||
for (i = 0; i != INDEXES(rfini2); i++)
|
||||
zyd_cfg_rfwrite(sc, rfini2[i]);
|
||||
|
||||
for (i = 0; i != INDEXES(phypll); i++)
|
||||
zyd_cfg_write16(sc, phypll[i].reg, phypll[i].val);
|
||||
|
||||
for (i = 0; i != INDEXES(rfini3); i++)
|
||||
zyd_cfg_rfwrite(sc, rfini3[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_cfg_rf_al2230_fini(struct zyd_softc *sc, struct zyd_rf *rf)
|
||||
{
|
||||
static const struct zyd_phy_pair phy[] = ZYD_AL2230_PHY_FINI_PART1;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i != INDEXES(phy); i++)
|
||||
zyd_cfg_write16(sc, phy[i].reg, phy[i].val);
|
||||
|
||||
if (sc->sc_newphy != 0)
|
||||
zyd_cfg_write16(sc, ZYD_CR9, 0xe1);
|
||||
zyd_cfg_write16(sc, ZYD_CR203, 0x6);
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_cfg_rf_al2230_init_b(struct zyd_softc *sc, struct zyd_rf *rf)
|
||||
{
|
||||
static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY_B;
|
||||
static const uint32_t rfini[] = ZYD_AL2230_RF_B;
|
||||
static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1;
|
||||
static const struct zyd_phy_pair phy2[] = ZYD_AL2230_PHY_PART2;
|
||||
static const struct zyd_phy_pair phy3[] = ZYD_AL2230_PHY_PART3;
|
||||
static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT;
|
||||
static const uint32_t rfini_part1[] = ZYD_AL2230_RF_B_PART1;
|
||||
static const uint32_t rfini_part2[] = ZYD_AL2230_RF_B_PART2;
|
||||
static const uint32_t rfini_part3[] = ZYD_AL2230_RF_B_PART3;
|
||||
static const uint32_t zyd_al2230_chtable[][3] = ZYD_AL2230_CHANTABLE;
|
||||
uint32_t i;
|
||||
|
||||
/* init RF-dependent PHY registers */
|
||||
for (i = 0; i != INDEXES(phyini); i++) {
|
||||
zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val);
|
||||
}
|
||||
for (i = 0; i != INDEXES(phy1); i++)
|
||||
zyd_cfg_write16(sc, phy1[i].reg, phy1[i].val);
|
||||
|
||||
/* init AL2230 radio */
|
||||
for (i = 0; i != INDEXES(rfini); i++) {
|
||||
zyd_cfg_rfwrite(sc, rfini[i]);
|
||||
}
|
||||
/* init RF-dependent PHY registers */
|
||||
for (i = 0; i != INDEXES(phyini); i++)
|
||||
zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val);
|
||||
|
||||
if ((sc->sc_rf_rev == ZYD_RF_AL2230S) || (sc->sc_al2230s != 0))
|
||||
for (i = 0; i != INDEXES(phy2230s); i++)
|
||||
zyd_cfg_write16(sc, phy2230s[i].reg, phy2230s[i].val);
|
||||
|
||||
for (i = 0; i != 3; i++)
|
||||
zyd_cfg_rfwrite_cr(sc, zyd_al2230_chtable[0][i]);
|
||||
|
||||
for (i = 0; i != INDEXES(rfini_part1); i++)
|
||||
zyd_cfg_rfwrite_cr(sc, rfini_part1[i]);
|
||||
|
||||
if ((sc->sc_rf_rev == ZYD_RF_AL2230S) || (sc->sc_al2230s != 0))
|
||||
zyd_cfg_rfwrite(sc, 0x241000);
|
||||
else
|
||||
zyd_cfg_rfwrite(sc, 0x25a000);
|
||||
|
||||
for (i = 0; i != INDEXES(rfini_part2); i++)
|
||||
zyd_cfg_rfwrite_cr(sc, rfini_part2[i]);
|
||||
|
||||
for (i = 0; i != INDEXES(phy2); i++)
|
||||
zyd_cfg_write16(sc, phy2[i].reg, phy2[i].val);
|
||||
|
||||
for (i = 0; i != INDEXES(rfini_part3); i++)
|
||||
zyd_cfg_rfwrite_cr(sc, rfini_part3[i]);
|
||||
|
||||
for (i = 0; i < INDEXES(phy3); i++)
|
||||
zyd_cfg_write16(sc, phy3[i].reg, phy3[i].val);
|
||||
|
||||
zyd_cfg_rf_al2230_fini(sc, rf);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1274,16 +1370,60 @@ static void
|
||||
zyd_cfg_rf_al2230_set_channel(struct zyd_softc *sc, struct zyd_rf *rf,
|
||||
uint8_t channel)
|
||||
{
|
||||
static const struct zyd_phy_pair phy1[] = {
|
||||
{ZYD_CR138, 0x28}, {ZYD_CR203, 0x06},
|
||||
};
|
||||
static const struct {
|
||||
uint32_t r1, r2, r3;
|
||||
} rfprog[] = ZYD_AL2230_CHANTABLE;
|
||||
uint32_t i;
|
||||
|
||||
zyd_cfg_rfwrite(sc, rfprog[channel - 1].r1);
|
||||
zyd_cfg_rfwrite(sc, rfprog[channel - 1].r2);
|
||||
zyd_cfg_rfwrite(sc, rfprog[channel - 1].r3);
|
||||
|
||||
zyd_cfg_write16(sc, ZYD_CR138, 0x28);
|
||||
zyd_cfg_write16(sc, ZYD_CR203, 0x06);
|
||||
for (i = 0; i != INDEXES(phy1); i++)
|
||||
zyd_cfg_write16(sc, phy1[i].reg, phy1[i].val);
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_cfg_rf_al2230_set_channel_b(struct zyd_softc *sc,
|
||||
struct zyd_rf *rf, uint8_t chan)
|
||||
{
|
||||
static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1;
|
||||
static const struct {
|
||||
uint32_t r1, r2, r3;
|
||||
} rfprog[] = ZYD_AL2230_CHANTABLE_B;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i != INDEXES(phy1); i++)
|
||||
zyd_cfg_write16(sc, phy1[i].reg, phy1[i].val);
|
||||
|
||||
zyd_cfg_rfwrite_cr(sc, rfprog[chan - 1].r1);
|
||||
zyd_cfg_rfwrite_cr(sc, rfprog[chan - 1].r2);
|
||||
zyd_cfg_rfwrite_cr(sc, rfprog[chan - 1].r3);
|
||||
|
||||
zyd_cfg_rf_al2230_fini(sc, rf);
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_PHY_BANDEDGE6 \
|
||||
{ \
|
||||
{ ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, \
|
||||
{ ZYD_CR47, 0x1e } \
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_cfg_rf_al2230_bandedge6(struct zyd_softc *sc,
|
||||
struct zyd_rf *rf, uint8_t chan)
|
||||
{
|
||||
struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6;
|
||||
uint32_t i;
|
||||
|
||||
if ((chan == 1) || (chan == 11))
|
||||
r[0].val = 0x12;
|
||||
|
||||
for (i = 0; i < INDEXES(r); i++)
|
||||
zyd_cfg_write16(sc, r[i].reg, r[i].val);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1413,7 +1553,6 @@ zyd_cfg_rf_al2210_set_channel(struct zyd_softc *sc, struct zyd_rf *rf,
|
||||
zyd_cfg_write32(sc, ZYD_CR_RADIO_PD, tmp & ~1);
|
||||
zyd_cfg_write32(sc, ZYD_CR_RADIO_PD, tmp | 1);
|
||||
zyd_cfg_write32(sc, ZYD_CR_RFCFG, 0x05);
|
||||
|
||||
zyd_cfg_write32(sc, ZYD_CR_RFCFG, 0x00);
|
||||
zyd_cfg_write16(sc, ZYD_CR47, 0x1e);
|
||||
|
||||
@ -1617,12 +1756,16 @@ zyd_cfg_rf_init_hw(struct zyd_softc *sc, struct zyd_rf *rf)
|
||||
rf->width = 24; /* 24-bit RF values */
|
||||
break;
|
||||
case ZYD_RF_AL2230:
|
||||
if (sc->sc_mac_rev == ZYD_ZD1211B)
|
||||
case ZYD_RF_AL2230S:
|
||||
if (sc->sc_mac_rev == ZYD_ZD1211B) {
|
||||
rf->cfg_init_hw = zyd_cfg_rf_al2230_init_b;
|
||||
else
|
||||
rf->cfg_set_channel = zyd_cfg_rf_al2230_set_channel_b;
|
||||
} else {
|
||||
rf->cfg_init_hw = zyd_cfg_rf_al2230_init;
|
||||
rf->cfg_set_channel = zyd_cfg_rf_al2230_set_channel;
|
||||
}
|
||||
rf->cfg_switch_radio = zyd_cfg_rf_al2230_switch_radio;
|
||||
rf->cfg_set_channel = zyd_cfg_rf_al2230_set_channel;
|
||||
rf->cfg_bandedge6 = zyd_cfg_rf_al2230_bandedge6;
|
||||
rf->width = 24; /* 24-bit RF values */
|
||||
break;
|
||||
case ZYD_RF_AL7230B:
|
||||
@ -1689,6 +1832,9 @@ zyd_cfg_hw_init(struct zyd_softc *sc)
|
||||
zyd_cfg_write32(sc, ZYD_CR_GPI_EN, 0);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_CONT_WIN_LIMIT, 0x7f043f);
|
||||
|
||||
/* set mandatory rates - XXX assumes 802.11b/g */
|
||||
zyd_cfg_write32(sc, ZYD_MAC_MAN_RATE, 0x150f);
|
||||
|
||||
/* disable interrupts */
|
||||
zyd_cfg_write32(sc, ZYD_CR_INTERRUPT, 0);
|
||||
|
||||
@ -1698,7 +1844,7 @@ zyd_cfg_hw_init(struct zyd_softc *sc)
|
||||
for (; phyp->reg != 0; phyp++) {
|
||||
zyd_cfg_write16(sc, phyp->reg, phyp->val);
|
||||
}
|
||||
if (sc->sc_fix_cr157) {
|
||||
if ((sc->sc_mac_rev == ZYD_ZD1211) && sc->sc_fix_cr157) {
|
||||
zyd_cfg_read32(sc, ZYD_EEPROM_PHY_REG, &tmp);
|
||||
zyd_cfg_write32(sc, ZYD_CR157, tmp >> 8);
|
||||
}
|
||||
@ -1707,20 +1853,6 @@ zyd_cfg_hw_init(struct zyd_softc *sc)
|
||||
/* HMAC init */
|
||||
zyd_cfg_write32(sc, ZYD_MAC_ACK_EXT, 0x00000020);
|
||||
zyd_cfg_write32(sc, ZYD_CR_ADDA_MBIAS_WT, 0x30000808);
|
||||
|
||||
if (sc->sc_mac_rev == ZYD_ZD1211) {
|
||||
zyd_cfg_write32(sc, ZYD_MAC_RETRY, 0x00000002);
|
||||
} else {
|
||||
zyd_cfg_write32(sc, ZYD_MACB_MAX_RETRY, 0x02020202);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_AIFS_CTL1, 0x00280028);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_AIFS_CTL2, 0x008C003C);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXOP, 0x01800824);
|
||||
}
|
||||
|
||||
zyd_cfg_write32(sc, ZYD_MAC_SNIFFER, 0x00000000);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_RXFILTER, 0x00000000);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_GHTBL, 0x00000000);
|
||||
@ -1732,12 +1864,28 @@ zyd_cfg_hw_init(struct zyd_softc *sc)
|
||||
zyd_cfg_write32(sc, ZYD_MAC_ACK_EXT, 0x00000080);
|
||||
zyd_cfg_write32(sc, ZYD_CR_ADDA_PWR_DWN, 0x00000000);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_SIFS_ACK_TIME, 0x00000100);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0547c032);
|
||||
zyd_cfg_write32(sc, ZYD_CR_RX_PE_DELAY, 0x00000070);
|
||||
zyd_cfg_write32(sc, ZYD_CR_PS_CTRL, 0x10000000);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_RTSCTSRATE, 0x02030203);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_AFTER_PNP, 1);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_BACKOFF_PROTECT, 0x00000114);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0a47c032);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_CAM_MODE, 0x3);
|
||||
|
||||
if (sc->sc_mac_rev == ZYD_ZD1211) {
|
||||
zyd_cfg_write32(sc, ZYD_MAC_RETRY, 0x00000002);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640);
|
||||
} else {
|
||||
zyd_cfg_write32(sc, ZYD_MACB_MAX_RETRY, 0x02020202);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_AIFS_CTL1, 0x00280028);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_AIFS_CTL2, 0x008C003C);
|
||||
zyd_cfg_write32(sc, ZYD_MACB_TXOP, 0x01800824);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0eff);
|
||||
}
|
||||
|
||||
/* init beacon interval to 100ms */
|
||||
zyd_cfg_set_beacon_interval(sc, 100);
|
||||
@ -1756,20 +1904,19 @@ zyd_cfg_read_eeprom(struct zyd_softc *sc)
|
||||
uint16_t val;
|
||||
|
||||
/* read MAC address */
|
||||
zyd_cfg_read32(sc, ZYD_EEPROM_MAC_ADDR_P1, &tmp);
|
||||
sc->sc_myaddr[0] = tmp & 0xff;
|
||||
sc->sc_myaddr[1] = tmp >> 8;
|
||||
sc->sc_myaddr[2] = tmp >> 16;
|
||||
sc->sc_myaddr[3] = tmp >> 24;
|
||||
zyd_cfg_read32(sc, ZYD_EEPROM_MAC_ADDR_P2, &tmp);
|
||||
sc->sc_myaddr[4] = tmp & 0xff;
|
||||
sc->sc_myaddr[5] = tmp >> 8;
|
||||
zyd_cfg_get_macaddr(sc);
|
||||
|
||||
/* read product data */
|
||||
zyd_cfg_read32(sc, ZYD_EEPROM_POD, &tmp);
|
||||
sc->sc_rf_rev = tmp & 0x0f;
|
||||
sc->sc_fix_cr47 = (tmp >> 8) & 0x01;
|
||||
sc->sc_ledtype = (tmp >> 4) & 0x01;
|
||||
sc->sc_cckgain = (tmp >> 8) & 0x01;
|
||||
sc->sc_fix_cr157 = (tmp >> 13) & 0x01;
|
||||
sc->sc_pa_rev = (tmp >> 16) & 0x0f;
|
||||
sc->sc_al2230s = (tmp >> 7) & 0x01;
|
||||
sc->sc_bandedge6 = (tmp >> 21) & 0x01;
|
||||
sc->sc_newphy = (tmp >> 31) & 0x01;
|
||||
sc->sc_txled = ((tmp & (1 << 24)) && (tmp & (1 << 29))) ? 0 : 1;
|
||||
|
||||
/* read regulatory domain (currently unused) */
|
||||
zyd_cfg_read32(sc, ZYD_EEPROM_SUBID, &tmp);
|
||||
@ -1800,6 +1947,21 @@ zyd_cfg_read_eeprom(struct zyd_softc *sc)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_cfg_get_macaddr(struct zyd_softc *sc)
|
||||
{
|
||||
struct usb2_device_request req;
|
||||
|
||||
req.bmRequestType = UT_READ_VENDOR_DEVICE;
|
||||
req.bRequest = ZYD_READFWDATAREQ;
|
||||
USETW(req.wValue, ZYD_EEPROM_MAC_ADDR_P1);
|
||||
USETW(req.wIndex, 0);
|
||||
USETW(req.wLength, IEEE80211_ADDR_LEN);
|
||||
|
||||
zyd_cfg_usbrequest(sc, &req, sc->sc_myaddr);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_cfg_set_mac_addr(struct zyd_softc *sc, const uint8_t *addr)
|
||||
{
|
||||
@ -2270,17 +2432,18 @@ zyd_cfg_set_chan(struct zyd_softc *sc,
|
||||
zyd_cfg_write16(sc, ZYD_CR67, sc->sc_ofdm36_cal[chan - 1]);
|
||||
zyd_cfg_write16(sc, ZYD_CR66, sc->sc_ofdm48_cal[chan - 1]);
|
||||
zyd_cfg_write16(sc, ZYD_CR65, sc->sc_ofdm54_cal[chan - 1]);
|
||||
|
||||
zyd_cfg_write16(sc, ZYD_CR68, sc->sc_pwr_cal[chan - 1]);
|
||||
|
||||
zyd_cfg_write16(sc, ZYD_CR69, 0x28);
|
||||
zyd_cfg_write16(sc, ZYD_CR69, 0x2a);
|
||||
}
|
||||
if (sc->sc_fix_cr47) {
|
||||
if (sc->sc_cckgain) {
|
||||
/* set CCK baseband gain from EEPROM */
|
||||
zyd_cfg_read32(sc, ZYD_EEPROM_PHY_REG, &tmp);
|
||||
zyd_cfg_write16(sc, ZYD_CR47, tmp & 0xff);
|
||||
}
|
||||
if (sc->sc_bandedge6 && (sc->sc_rf.cfg_bandedge6 != NULL)) {
|
||||
(sc->sc_rf.cfg_bandedge6) (sc, &sc->sc_rf, chan);
|
||||
}
|
||||
zyd_cfg_write32(sc, ZYD_CR_CONFIG_PHILIPS, 0);
|
||||
|
||||
zyd_cfg_unlock_phy(sc);
|
||||
@ -2349,7 +2512,7 @@ zyd_cfg_init(struct zyd_softc *sc,
|
||||
else if (cc->ic_curmode == IEEE80211_MODE_11A)
|
||||
zyd_cfg_write32(sc, ZYD_MAC_BAS_RATE, 0x1500);
|
||||
else /* assumes 802.11b/g */
|
||||
zyd_cfg_write32(sc, ZYD_MAC_BAS_RATE, 0x000f);
|
||||
zyd_cfg_write32(sc, ZYD_MAC_BAS_RATE, 0xff0f);
|
||||
|
||||
/* set mandatory rates */
|
||||
if (cc->ic_curmode == IEEE80211_MODE_11B)
|
||||
|
@ -101,6 +101,7 @@
|
||||
#define ZYD_MAC_CONT_WIN_LIMIT 0x96f0 /* Contention window limit */
|
||||
#define ZYD_MAC_TX_PKT 0x96f4 /* Tx total packet count read */
|
||||
#define ZYD_MAC_DL_CTRL 0x96f8 /* Download control */
|
||||
#define ZYD_MAC_CAM_MODE 0x9700 /* CAM: Continuous Access Mode */
|
||||
#define ZYD_MACB_TXPWR_CTL1 0x9b00
|
||||
#define ZYD_MACB_TXPWR_CTL2 0x9b04
|
||||
#define ZYD_MACB_TXPWR_CTL3 0x9b08
|
||||
@ -127,8 +128,8 @@
|
||||
#define ZYD_EEPROM_PWR_CAL 0xf81f /* Calibration */
|
||||
#define ZYD_EEPROM_PWR_INT 0xf827 /* Calibration */
|
||||
#define ZYD_EEPROM_ALLOWEDCHAN 0xf82f /* Allowed CH mask, 1 bit each */
|
||||
#define ZYD_EEPROM_PHY_REG 0xf831 /* PHY registers */
|
||||
#define ZYD_EEPROM_DEVICE_VER 0xf837 /* Device version */
|
||||
#define ZYD_EEPROM_PHY_REG 0xf83c /* PHY registers */
|
||||
#define ZYD_EEPROM_36M_CAL 0xf83f /* Calibration */
|
||||
#define ZYD_EEPROM_11A_INT 0xf847 /* Interpolation */
|
||||
#define ZYD_EEPROM_48M_CAL 0xf84f /* Calibration */
|
||||
@ -161,7 +162,7 @@
|
||||
#define ZYD_RF_AL2210 0x7
|
||||
#define ZYD_RF_MAXIM_NEW 0x8
|
||||
#define ZYD_RF_GCT 0x9
|
||||
#define ZYD_RF_PV2000 0xa /* not supported yet */
|
||||
#define ZYD_RF_AL2230S 0xa
|
||||
#define ZYD_RF_RALINK 0xb /* not supported yet */
|
||||
#define ZYD_RF_INTERSIL 0xc /* not supported yet */
|
||||
#define ZYD_RF_RFMD 0xd
|
||||
@ -437,7 +438,7 @@
|
||||
{ ZYD_CR37, 0x00 }, { ZYD_CR38, 0x38 }, { ZYD_CR39, 0x0c }, \
|
||||
{ ZYD_CR40, 0x84 }, { ZYD_CR41, 0x2a }, { ZYD_CR42, 0x80 }, \
|
||||
{ ZYD_CR43, 0x10 }, { ZYD_CR44, 0x12 }, { ZYD_CR46, 0xff }, \
|
||||
{ ZYD_CR47, 0x08 }, { ZYD_CR48, 0x26 }, { ZYD_CR49, 0x5b }, \
|
||||
{ ZYD_CR47, 0x1e }, { ZYD_CR48, 0x26 }, { ZYD_CR49, 0x5b }, \
|
||||
{ ZYD_CR64, 0xd0 }, { ZYD_CR65, 0x04 }, { ZYD_CR66, 0x58 }, \
|
||||
{ ZYD_CR67, 0xc9 }, { ZYD_CR68, 0x88 }, { ZYD_CR69, 0x41 }, \
|
||||
{ ZYD_CR70, 0x23 }, { ZYD_CR71, 0x10 }, { ZYD_CR72, 0xff }, \
|
||||
@ -459,7 +460,7 @@
|
||||
{ ZYD_CR5, 0x00 }, { ZYD_CR6, 0x00 }, { ZYD_CR7, 0x00 }, \
|
||||
{ ZYD_CR8, 0x00 }, { ZYD_CR9, 0x20 }, { ZYD_CR12, 0xf0 }, \
|
||||
{ ZYD_CR20, 0x0e }, { ZYD_CR21, 0x0e }, { ZYD_CR27, 0x10 }, \
|
||||
{ ZYD_CR44, 0x33 }, { ZYD_CR47, 0x30 }, { ZYD_CR83, 0x24 }, \
|
||||
{ ZYD_CR44, 0x33 }, { ZYD_CR47, 0x1E }, { ZYD_CR83, 0x24 }, \
|
||||
{ ZYD_CR84, 0x04 }, { ZYD_CR85, 0x00 }, { ZYD_CR86, 0x0C }, \
|
||||
{ ZYD_CR87, 0x12 }, { ZYD_CR88, 0x0C }, { ZYD_CR89, 0x00 }, \
|
||||
{ ZYD_CR90, 0x10 }, { ZYD_CR91, 0x08 }, { ZYD_CR93, 0x00 }, \
|
||||
@ -470,19 +471,18 @@
|
||||
{ ZYD_CR111, 0x27 }, { ZYD_CR112, 0x27 }, { ZYD_CR113, 0x27 }, \
|
||||
{ ZYD_CR114, 0x27 }, { ZYD_CR115, 0x26 }, { ZYD_CR116, 0x24 }, \
|
||||
{ ZYD_CR117, 0xfc }, { ZYD_CR118, 0xfa }, { ZYD_CR120, 0x4f }, \
|
||||
{ ZYD_CR123, 0x27 }, { ZYD_CR125, 0xaa }, { ZYD_CR127, 0x03 }, \
|
||||
{ ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, \
|
||||
{ ZYD_CR131, 0x0C }, { ZYD_CR136, 0xdf }, { ZYD_CR137, 0x40 }, \
|
||||
{ ZYD_CR138, 0xa0 }, { ZYD_CR139, 0xb0 }, { ZYD_CR140, 0x99 }, \
|
||||
{ ZYD_CR141, 0x82 }, { ZYD_CR142, 0x54 }, { ZYD_CR143, 0x1c }, \
|
||||
{ ZYD_CR144, 0x6c }, { ZYD_CR147, 0x07 }, { ZYD_CR148, 0x4c }, \
|
||||
{ ZYD_CR149, 0x50 }, { ZYD_CR150, 0x0e }, { ZYD_CR151, 0x18 }, \
|
||||
{ ZYD_CR160, 0xfe }, { ZYD_CR161, 0xee }, { ZYD_CR162, 0xaa }, \
|
||||
{ ZYD_CR163, 0xfa }, { ZYD_CR164, 0xfa }, { ZYD_CR165, 0xea }, \
|
||||
{ ZYD_CR166, 0xbe }, { ZYD_CR167, 0xbe }, { ZYD_CR168, 0x6a }, \
|
||||
{ ZYD_CR169, 0xba }, { ZYD_CR170, 0xba }, { ZYD_CR171, 0xba }, \
|
||||
{ ZYD_CR204, 0x7d }, { ZYD_CR203, 0x30 }, \
|
||||
{ 0, 0 } \
|
||||
{ ZYD_CR125, 0xaa }, { ZYD_CR127, 0x03 }, { ZYD_CR128, 0x14 }, \
|
||||
{ ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, { ZYD_CR131, 0x0C }, \
|
||||
{ ZYD_CR136, 0xdf }, { ZYD_CR137, 0x40 }, { ZYD_CR138, 0xa0 }, \
|
||||
{ ZYD_CR139, 0xb0 }, { ZYD_CR140, 0x99 }, { ZYD_CR141, 0x82 }, \
|
||||
{ ZYD_CR142, 0x54 }, { ZYD_CR143, 0x1c }, { ZYD_CR144, 0x6c }, \
|
||||
{ ZYD_CR147, 0x07 }, { ZYD_CR148, 0x4c }, { ZYD_CR149, 0x50 }, \
|
||||
{ ZYD_CR150, 0x0e }, { ZYD_CR151, 0x18 }, { ZYD_CR160, 0xfe }, \
|
||||
{ ZYD_CR161, 0xee }, { ZYD_CR162, 0xaa }, { ZYD_CR163, 0xfa }, \
|
||||
{ ZYD_CR164, 0xfa }, { ZYD_CR165, 0xea }, { ZYD_CR166, 0xbe }, \
|
||||
{ ZYD_CR167, 0xbe }, { ZYD_CR168, 0x6a }, { ZYD_CR169, 0xba }, \
|
||||
{ ZYD_CR170, 0xba }, { ZYD_CR171, 0xba }, { ZYD_CR204, 0x7d }, \
|
||||
{ ZYD_CR203, 0x30 }, { 0, 0} \
|
||||
}
|
||||
|
||||
#define ZYD_DEF_PHYB \
|
||||
@ -590,8 +590,6 @@
|
||||
{ 0x181a60, 0x1c0000 } \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ZYD_AL2230_PHY \
|
||||
{ \
|
||||
{ ZYD_CR15, 0x20 }, { ZYD_CR23, 0x40 }, { ZYD_CR24, 0x20 }, \
|
||||
@ -617,34 +615,73 @@
|
||||
|
||||
#define ZYD_AL2230_PHY_B \
|
||||
{ \
|
||||
{ ZYD_CR10, 0x89 }, { ZYD_CR15, 0x20 }, { ZYD_CR17, 0x2b }, \
|
||||
{ ZYD_CR10, 0x89 }, { ZYD_CR15, 0x20 }, { ZYD_CR17, 0x2B }, \
|
||||
{ ZYD_CR23, 0x40 }, { ZYD_CR24, 0x20 }, { ZYD_CR26, 0x93 }, \
|
||||
{ ZYD_CR28, 0x3e }, { ZYD_CR29, 0x00 }, { ZYD_CR33, 0x28 }, \
|
||||
{ ZYD_CR34, 0x30 }, { ZYD_CR35, 0x3e }, { ZYD_CR41, 0x24 }, \
|
||||
{ ZYD_CR44, 0x32 }, { ZYD_CR46, 0x99 }, { ZYD_CR47, 0x1e }, \
|
||||
{ ZYD_CR48, 0x00 }, { ZYD_CR49, 0x00 }, { ZYD_CR51, 0x01 }, \
|
||||
{ ZYD_CR48, 0x06 }, { ZYD_CR49, 0xf9 }, { ZYD_CR51, 0x01 }, \
|
||||
{ ZYD_CR52, 0x80 }, { ZYD_CR53, 0x7e }, { ZYD_CR65, 0x00 }, \
|
||||
{ ZYD_CR66, 0x00 }, { ZYD_CR67, 0x00 }, { ZYD_CR68, 0x00 }, \
|
||||
{ ZYD_CR69, 0x28 }, { ZYD_CR79, 0x58 }, { ZYD_CR80, 0x30 }, \
|
||||
{ ZYD_CR81, 0x30 }, { ZYD_CR87, 0x0a }, { ZYD_CR89, 0x04 }, \
|
||||
{ ZYD_CR91, 0x00 }, { ZYD_CR92, 0x0a }, { ZYD_CR98, 0x8d }, \
|
||||
{ ZYD_CR99, 0x00 }, { ZYD_CR101, 0x13 }, { ZYD_CR106, 0x24 }, \
|
||||
{ ZYD_CR107, 0x2a }, { ZYD_CR109, 0x13 }, { ZYD_CR110, 0x1f }, \
|
||||
{ ZYD_CR111, 0x1f }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x26 }, \
|
||||
{ ZYD_CR99, 0x00 }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \
|
||||
{ ZYD_CR106, 0x24 }, { ZYD_CR107, 0x2a }, { ZYD_CR109, 0x13 }, \
|
||||
{ ZYD_CR110, 0x1f }, { ZYD_CR111, 0x1f }, { ZYD_CR112, 0x1f }, \
|
||||
{ ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x26 }, \
|
||||
{ ZYD_CR116, 0x24 }, { ZYD_CR117, 0xfa }, { ZYD_CR118, 0xfa }, \
|
||||
{ ZYD_CR119, 0x10 }, { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x6c }, \
|
||||
{ ZYD_CR122, 0xfc }, { ZYD_CR123, 0x57 }, { ZYD_CR125, 0xad }, \
|
||||
{ ZYD_CR126, 0x6c }, { ZYD_CR127, 0x03 }, { ZYD_CR137, 0x50 }, \
|
||||
{ ZYD_CR138, 0xa8 }, { ZYD_CR144, 0xac }, { ZYD_CR150, 0x0d }, \
|
||||
{ ZYD_CR252, 0x00 }, { ZYD_CR253, 0x00 } \
|
||||
{ ZYD_CR252, 0x34 }, { ZYD_CR253, 0x34 } \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_RF \
|
||||
#define ZYD_AL2230_PHY_PART1 \
|
||||
{ \
|
||||
{ ZYD_CR240, 0x57 }, { ZYD_CR9, 0xe0 } \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_PHY_PART2 \
|
||||
{ \
|
||||
{ ZYD_CR251, 0x2f }, { ZYD_CR251, 0x7f }, \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_PHY_PART3 \
|
||||
{ \
|
||||
{ ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230S_PHY_INIT \
|
||||
{ \
|
||||
{ ZYD_CR47, 0x1e }, { ZYD_CR106, 0x22 }, { ZYD_CR107, 0x2a }, \
|
||||
{ ZYD_CR109, 0x13 }, { ZYD_CR118, 0xf8 }, { ZYD_CR119, 0x12 }, \
|
||||
{ ZYD_CR122, 0xe0 }, { ZYD_CR128, 0x10 }, { ZYD_CR129, 0x0e }, \
|
||||
{ ZYD_CR130, 0x10 } \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_PHY_FINI_PART1 \
|
||||
{ \
|
||||
{ ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR79, 0x58 }, \
|
||||
{ ZYD_CR12, 0xf0 }, { ZYD_CR77, 0x1b }, { ZYD_CR78, 0x58 }, \
|
||||
{ ZYD_CR203, 0x06 }, { ZYD_CR240, 0x80 }, \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_RF_PART1 \
|
||||
{ \
|
||||
0x03f790, 0x033331, 0x00000d, 0x0b3331, 0x03b812, 0x00fff3 \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_RF_PART2 \
|
||||
{ \
|
||||
0x03f790, 0x033331, 0x00000d, 0x0b3331, 0x03b812, 0x00fff3, \
|
||||
0x000da4, 0x0f4dc5, 0x0805b6, 0x011687, 0x000688, 0x0403b9, \
|
||||
0x00dbba, 0x00099b, 0x0bdffc, 0x00000d, 0x00500f, 0x00d00f, \
|
||||
0x004c0f, 0x00540f, 0x00700f, 0x00500f \
|
||||
0x00dbba, 0x00099b, 0x0bdffc, 0x00000d, 0x00500f \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_RF_PART3 \
|
||||
{ \
|
||||
0x00d00f, 0x004c0f, 0x00540f, 0x00700f, 0x00500f \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_RF_B \
|
||||
@ -654,6 +691,22 @@
|
||||
0x00dbba, 0x00099b, 0x0bdffc, 0x00000d, 0x00580f \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_RF_B_PART1 \
|
||||
{ \
|
||||
0x8cccd0, 0x481dc0, 0xcfff00, 0x25a000 \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_RF_B_PART2 \
|
||||
{ \
|
||||
0x25a000, 0xa3b2f0, 0x6da010, 0xe36280, 0x116000, 0x9dc020, \
|
||||
0x5ddb00, 0xd99000, 0x3ffbd0, 0xb00000, 0xf01a00 \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_RF_B_PART3 \
|
||||
{ \
|
||||
0xf01b00, 0xf01e00, 0xf01a00 \
|
||||
}
|
||||
|
||||
#define ZYD_AL2230_CHANTABLE \
|
||||
{ \
|
||||
{ 0x03f790, 0x033331, 0x00000d }, \
|
||||
@ -672,7 +725,23 @@
|
||||
{ 0x03e7c0, 0x066661, 0x00000d } \
|
||||
}
|
||||
|
||||
|
||||
#define ZYD_AL2230_CHANTABLE_B \
|
||||
{ \
|
||||
{ 0x09efc0, 0x8cccc0, 0xb00000 }, \
|
||||
{ 0x09efc0, 0x8cccd0, 0xb00000 }, \
|
||||
{ 0x09e7c0, 0x8cccc0, 0xb00000 }, \
|
||||
{ 0x09e7c0, 0x8cccd0, 0xb00000 }, \
|
||||
{ 0x05efc0, 0x8cccc0, 0xb00000 }, \
|
||||
{ 0x05efc0, 0x8cccd0, 0xb00000 }, \
|
||||
{ 0x05e7c0, 0x8cccc0, 0xb00000 }, \
|
||||
{ 0x05e7c0, 0x8cccd0, 0xb00000 }, \
|
||||
{ 0x0defc0, 0x8cccc0, 0xb00000 }, \
|
||||
{ 0x0defc0, 0x8cccd0, 0xb00000 }, \
|
||||
{ 0x0de7c0, 0x8cccc0, 0xb00000 }, \
|
||||
{ 0x0de7c0, 0x8cccd0, 0xb00000 }, \
|
||||
{ 0x03efc0, 0x8cccc0, 0xb00000 }, \
|
||||
{ 0x03e7c0, 0x866660, 0xb00000 } \
|
||||
}
|
||||
|
||||
#define ZYD_AL7230B_PHY_1 \
|
||||
{ \
|
||||
@ -744,8 +813,6 @@
|
||||
{ 0x03ec00, 0x866660 } \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ZYD_AL2210_PHY \
|
||||
{ \
|
||||
{ ZYD_CR9, 0xe0 }, { ZYD_CR10, 0x91 }, { ZYD_CR12, 0x90 }, \
|
||||
@ -771,8 +838,6 @@
|
||||
0x019a80, 0x019b40 \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ZYD_GCT_PHY \
|
||||
{ \
|
||||
{ ZYD_CR47, 0x1e }, { ZYD_CR15, 0xdc }, { ZYD_CR113, 0xc0 }, \
|
||||
@ -801,8 +866,6 @@
|
||||
0x1a3000, 0x1ab000 \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ZYD_MAXIM_PHY \
|
||||
{ \
|
||||
{ ZYD_CR23, 0x40 }, { ZYD_CR15, 0x20 }, { ZYD_CR28, 0x3e }, \
|
||||
@ -855,8 +918,6 @@
|
||||
{ 0x199a4, 0x20a53 } \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ZYD_MAXIM2_PHY \
|
||||
{ \
|
||||
{ ZYD_CR23, 0x40 }, { ZYD_CR15, 0x20 }, { ZYD_CR28, 0x3e }, \
|
||||
@ -919,6 +980,7 @@
|
||||
*/
|
||||
#define ZYD_DOWNLOADREQ 0x30
|
||||
#define ZYD_DOWNLOADSTS 0x31
|
||||
#define ZYD_READFWDATAREQ 0x32
|
||||
|
||||
/* possible values for register ZYD_CR_INTERRUPT */
|
||||
#define ZYD_HWINT_MASK 0x004f0000
|
||||
@ -950,10 +1012,15 @@
|
||||
|
||||
/* helpers for register ZYD_MAC_RXFILTER */
|
||||
#define ZYD_FILTER_MONITOR 0xffffffff
|
||||
#define ZYD_FILTER_BSS \
|
||||
(ZYD_FILTER_ASS_RSP | ZYD_FILTER_REASS_RSP | \
|
||||
ZYD_FILTER_PRB_RSP | ZYD_FILTER_BCN | ZYD_FILTER_DEASS | \
|
||||
ZYD_FILTER_AUTH | ZYD_FILTER_DEAUTH)
|
||||
#define ZYD_FILTER_BSS \
|
||||
(ZYD_FILTER_ASS_REQ | ZYD_FILTER_ASS_RSP | \
|
||||
ZYD_FILTER_REASS_REQ | ZYD_FILTER_REASS_RSP | \
|
||||
ZYD_FILTER_PRB_REQ | ZYD_FILTER_PRB_RSP | \
|
||||
(0x3 << 6) | \
|
||||
ZYD_FILTER_BCN | ZYD_FILTER_ATIM | ZYD_FILTER_DEASS | \
|
||||
ZYD_FILTER_AUTH | ZYD_FILTER_DEAUTH | \
|
||||
(0x7 << 13) | \
|
||||
ZYD_FILTER_PS_POLL | ZYD_FILTER_ACK)
|
||||
#define ZYD_FILTER_HOSTAP \
|
||||
(ZYD_FILTER_ASS_REQ | ZYD_FILTER_REASS_REQ | \
|
||||
ZYD_FILTER_PRB_REQ | ZYD_FILTER_DEASS | ZYD_FILTER_AUTH | \
|
||||
@ -1138,6 +1205,8 @@ struct zyd_rf {
|
||||
void (*cfg_init_hw) (struct zyd_softc *, struct zyd_rf *);
|
||||
void (*cfg_switch_radio) (struct zyd_softc *, uint8_t on);
|
||||
void (*cfg_set_channel) (struct zyd_softc *, struct zyd_rf *, uint8_t);
|
||||
void (*cfg_bandedge6) (struct zyd_softc *, struct zyd_rf *, uint8_t);
|
||||
|
||||
uint8_t width;
|
||||
};
|
||||
|
||||
@ -1239,6 +1308,10 @@ struct zyd_softc {
|
||||
uint32_t sc_rxtap_len;
|
||||
uint32_t sc_txtap_len;
|
||||
uint32_t sc_unit;
|
||||
uint32_t sc_atim_wnd;
|
||||
uint32_t sc_pre_tbtt;
|
||||
uint32_t sc_bcn_int;
|
||||
|
||||
int sc_ns_arg;
|
||||
|
||||
uint16_t sc_firmware_base;
|
||||
@ -1254,7 +1327,12 @@ struct zyd_softc {
|
||||
uint8_t sc_mac_rev;
|
||||
uint8_t sc_rf_rev;
|
||||
uint8_t sc_pa_rev;
|
||||
uint8_t sc_fix_cr47;
|
||||
uint8_t sc_al2230s;
|
||||
uint8_t sc_cckgain;
|
||||
uint8_t sc_bandedge6;
|
||||
uint8_t sc_newphy;
|
||||
uint8_t sc_ledtype;
|
||||
uint8_t sc_txled;
|
||||
uint8_t sc_fix_cr157;
|
||||
uint8_t sc_pwr_cal[14];
|
||||
uint8_t sc_pwr_int[14];
|
||||
|
@ -57,7 +57,7 @@ SUBDIR += misc_fm
|
||||
SUBDIR += quirk
|
||||
SUBDIR += scanner
|
||||
SUBDIR += serial
|
||||
#SUBDIR += serial_3g
|
||||
SUBDIR += serial_3g
|
||||
SUBDIR += serial_ark
|
||||
SUBDIR += serial_bsa
|
||||
SUBDIR += serial_bser
|
||||
|
38
sys/modules/usb2/serial_3g/Makefile
Normal file
38
sys/modules/usb2/serial_3g/Makefile
Normal file
@ -0,0 +1,38 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
S=${.CURDIR}/../../..
|
||||
|
||||
.PATH: $S/dev/usb2/serial
|
||||
|
||||
KMOD=usb2_serial_3g
|
||||
SRCS=
|
||||
SRCS+= bus_if.h usb2_if.h device_if.h vnode_if.h
|
||||
SRCS+= opt_usb.h opt_bus.h opt_compat.h
|
||||
SRCS+= u3g2.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
Loading…
x
Reference in New Issue
Block a user