summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2019-09-24 11:05:03 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2019-11-13 10:47:04 +0100
commita5ddb0ea69f21c16b7697a935d7a0c16bb3cffcf (patch)
treedb091fb0f7d091804482156c9f3f55879ac93d5b /freebsd/sys/dev
parenttest/syscalls01: Fix sporadic test failures (diff)
downloadrtems-libbsd-a5ddb0ea69f21c16b7697a935d7a0c16bb3cffcf.tar.bz2
Update to FreeBSD head 2019-09-24
Git mirror commit 6b0307a0a5184339393f555d5d424190d8a8277a.
Diffstat (limited to 'freebsd/sys/dev')
-rw-r--r--freebsd/sys/dev/bge/if_bge.c41
-rw-r--r--freebsd/sys/dev/bge/if_bgereg.h6
-rw-r--r--freebsd/sys/dev/cadence/if_cgem.c10
-rw-r--r--freebsd/sys/dev/e1000/em_txrx.c9
-rw-r--r--freebsd/sys/dev/e1000/if_em.c347
-rw-r--r--freebsd/sys/dev/e1000/if_em.h9
-rw-r--r--freebsd/sys/dev/e1000/igb_txrx.c9
-rw-r--r--freebsd/sys/dev/evdev/evdev.c93
-rw-r--r--freebsd/sys/dev/evdev/evdev_private.h6
-rw-r--r--freebsd/sys/dev/extres/clk/clk.h1
-rw-r--r--freebsd/sys/dev/fb/fbd.c1
-rw-r--r--freebsd/sys/dev/fdt/fdt_common.c3
-rw-r--r--freebsd/sys/dev/gpio/gpiobus.c185
-rw-r--r--freebsd/sys/dev/gpio/gpiobusvar.h14
-rw-r--r--freebsd/sys/dev/gpio/ofw_gpiobus.c4
-rw-r--r--freebsd/sys/dev/iicbus/iicbus.c6
-rw-r--r--freebsd/sys/dev/iicbus/iicbus.h12
-rw-r--r--freebsd/sys/dev/iicbus/iiconf.c55
-rw-r--r--freebsd/sys/dev/iicbus/iiconf.h2
-rw-r--r--freebsd/sys/dev/led/led.c15
-rw-r--r--freebsd/sys/dev/mii/micphy.c12
-rw-r--r--freebsd/sys/dev/mmc/bridge.h2
-rw-r--r--freebsd/sys/dev/mmc/mmc.c2
-rw-r--r--freebsd/sys/dev/mmc/mmc_private.h2
-rw-r--r--freebsd/sys/dev/mmc/mmc_subr.c2
-rw-r--r--freebsd/sys/dev/mmc/mmc_subr.h2
-rw-r--r--freebsd/sys/dev/mmc/mmcbrvar.h2
-rw-r--r--freebsd/sys/dev/mmc/mmcreg.h46
-rw-r--r--freebsd/sys/dev/mmc/mmcsd.c8
-rw-r--r--freebsd/sys/dev/mmc/mmcvar.h2
-rw-r--r--freebsd/sys/dev/nvme/nvme.h524
-rw-r--r--freebsd/sys/dev/ofw/ofw_bus_subr.h8
-rw-r--r--freebsd/sys/dev/ofw/ofw_subr.c3
-rw-r--r--freebsd/sys/dev/pci/pci.c177
-rw-r--r--freebsd/sys/dev/pci/pci_pci.c45
-rw-r--r--freebsd/sys/dev/pci/pci_user.c8
-rw-r--r--freebsd/sys/dev/pci/pcivar.h19
-rw-r--r--freebsd/sys/dev/rtwn/if_rtwn.c12
-rw-r--r--freebsd/sys/dev/rtwn/if_rtwnvar.h3
-rw-r--r--freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.h7
-rw-r--r--freebsd/sys/dev/rtwn/pci/rtwn_pci_reg.c2
-rw-r--r--freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c123
-rw-r--r--freebsd/sys/dev/rtwn/pci/rtwn_pci_tx.c4
-rw-r--r--freebsd/sys/dev/rtwn/pci/rtwn_pci_var.h12
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e.h6
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c331
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c6
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c77
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h34
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h54
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c3
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h23
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c19
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h12
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c37
-rw-r--r--freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c81
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce.h2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c7
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c55
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c4
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c.h1
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_calib.c352
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c1
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h22
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c7
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c8
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h6
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu.h1
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c8
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c7
-rw-r--r--freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c2
-rw-r--r--freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c2
-rw-r--r--freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h6
-rw-r--r--freebsd/sys/dev/rtwn/usb/rtwn_usb_reg.c6
-rw-r--r--freebsd/sys/dev/sdhci/fsl_sdhci.c2
-rw-r--r--freebsd/sys/dev/sdhci/sdhci.c410
-rw-r--r--freebsd/sys/dev/sdhci/sdhci.h29
-rw-r--r--freebsd/sys/dev/usb/net/if_aue.c6
-rw-r--r--freebsd/sys/dev/usb/net/if_axe.c4
-rw-r--r--freebsd/sys/dev/usb/net/if_axge.c8
-rw-r--r--freebsd/sys/dev/usb/net/if_cdce.c5
-rw-r--r--freebsd/sys/dev/usb/net/if_mos.c6
-rw-r--r--freebsd/sys/dev/usb/net/if_rue.c6
-rw-r--r--freebsd/sys/dev/usb/net/if_smsc.c150
-rw-r--r--freebsd/sys/dev/usb/net/if_udav.c6
-rw-r--r--freebsd/sys/dev/usb/net/if_ure.c22
-rw-r--r--freebsd/sys/dev/usb/net/if_urereg.h2
-rw-r--r--freebsd/sys/dev/usb/net/usb_ethernet.c15
-rw-r--r--freebsd/sys/dev/usb/net/usb_ethernet.h8
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.c44
-rw-r--r--freebsd/sys/dev/usb/serial/u3g.c4
-rw-r--r--freebsd/sys/dev/usb/serial/ugensa.c109
-rw-r--r--freebsd/sys/dev/usb/serial/umcs.c4
-rw-r--r--freebsd/sys/dev/usb/serial/usb_serial.c3
-rw-r--r--freebsd/sys/dev/usb/usb.h1
-rw-r--r--freebsd/sys/dev/usb/usb_bus.h1
-rw-r--r--freebsd/sys/dev/usb/usb_device.c2
-rw-r--r--freebsd/sys/dev/usb/usb_fdt_support.h48
-rw-r--r--freebsd/sys/dev/usb/usb_generic.c58
-rw-r--r--freebsd/sys/dev/usb/usb_hid.c2
-rw-r--r--freebsd/sys/dev/usb/usb_hub.c76
-rw-r--r--freebsd/sys/dev/usb/usb_hub_private.h86
-rw-r--r--freebsd/sys/dev/usb/usb_ioctl.h3
-rw-r--r--freebsd/sys/dev/usb/usb_request.c5
-rw-r--r--freebsd/sys/dev/usb/usb_transfer.c33
-rw-r--r--freebsd/sys/dev/usb/usbdi.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_rsu.c56
-rw-r--r--freebsd/sys/dev/usb/wlan/if_rsureg.h13
-rw-r--r--freebsd/sys/dev/usb/wlan/if_rum.c10
-rw-r--r--freebsd/sys/dev/usb/wlan/if_rumvar.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_run.c145
-rw-r--r--freebsd/sys/dev/usb/wlan/if_runreg.h3
-rw-r--r--freebsd/sys/dev/usb/wlan/if_runvar.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_uath.c6
-rw-r--r--freebsd/sys/dev/usb/wlan/if_uathvar.h3
-rw-r--r--freebsd/sys/dev/usb/wlan/if_upgt.c5
-rw-r--r--freebsd/sys/dev/usb/wlan/if_upgtvar.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_ural.c10
-rw-r--r--freebsd/sys/dev/usb/wlan/if_uralvar.h2
-rw-r--r--freebsd/sys/dev/usb/wlan/if_urtw.c142
-rw-r--r--freebsd/sys/dev/usb/wlan/if_urtwvar.h12
-rw-r--r--freebsd/sys/dev/usb/wlan/if_zyd.c7
-rw-r--r--freebsd/sys/dev/usb/wlan/if_zydreg.h6
125 files changed, 3415 insertions, 1210 deletions
diff --git a/freebsd/sys/dev/bge/if_bge.c b/freebsd/sys/dev/bge/if_bge.c
index a4a937b2..79e930ca 100644
--- a/freebsd/sys/dev/bge/if_bge.c
+++ b/freebsd/sys/dev/bge/if_bge.c
@@ -2929,10 +2929,14 @@ bge_dma_ring_alloc(struct bge_softc *sc, bus_size_t alignment,
bus_addr_t *paddr, const char *msg)
{
struct bge_dmamap_arg ctx;
+ bus_addr_t lowaddr;
+ bus_size_t ring_end;
int error;
+ lowaddr = BUS_SPACE_MAXADDR;
+again:
error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag,
- alignment, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL,
+ alignment, 0, lowaddr, BUS_SPACE_MAXADDR, NULL,
NULL, maxsize, 1, maxsize, 0, NULL, NULL, tag);
if (error != 0) {
device_printf(sc->bge_dev,
@@ -2957,6 +2961,25 @@ bge_dma_ring_alloc(struct bge_softc *sc, bus_size_t alignment,
return (ENOMEM);
}
*paddr = ctx.bge_busaddr;
+ ring_end = *paddr + maxsize;
+ if ((sc->bge_flags & BGE_FLAG_4G_BNDRY_BUG) != 0 &&
+ BGE_ADDR_HI(*paddr) != BGE_ADDR_HI(ring_end)) {
+ /*
+ * 4GB boundary crossed. Limit maximum allowable DMA
+ * address space to 32bit and try again.
+ */
+ bus_dmamap_unload(*tag, *map);
+ bus_dmamem_free(*tag, *ring, *map);
+ bus_dma_tag_destroy(*tag);
+ if (bootverbose)
+ device_printf(sc->bge_dev, "4GB boundary crossed, "
+ "limit DMA address space to 32bit for %s\n", msg);
+ *ring = NULL;
+ *tag = NULL;
+ *map = NULL;
+ lowaddr = BUS_SPACE_MAXADDR_32BIT;
+ goto again;
+ }
return (0);
}
@@ -2964,7 +2987,7 @@ static int
bge_dma_alloc(struct bge_softc *sc)
{
bus_addr_t lowaddr;
- bus_size_t rxmaxsegsz, sbsz, txsegsz, txmaxsegsz;
+ bus_size_t boundary, sbsz, rxmaxsegsz, txsegsz, txmaxsegsz;
int i, error;
lowaddr = BUS_SPACE_MAXADDR;
@@ -3051,7 +3074,9 @@ bge_dma_alloc(struct bge_softc *sc)
}
/* Create parent tag for buffers. */
+ boundary = 0;
if ((sc->bge_flags & BGE_FLAG_4G_BNDRY_BUG) != 0) {
+ boundary = BGE_DMA_BNDRY;
/*
* XXX
* watchdog timeout issue was observed on BCM5704 which
@@ -3062,10 +3087,10 @@ bge_dma_alloc(struct bge_softc *sc)
if (sc->bge_pcixcap != 0)
lowaddr = BUS_SPACE_MAXADDR_32BIT;
}
- error = bus_dma_tag_create(bus_get_dma_tag(sc->bge_dev), 1, 0, lowaddr,
- BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, 0,
- BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL,
- &sc->bge_cdata.bge_buffer_tag);
+ error = bus_dma_tag_create(bus_get_dma_tag(sc->bge_dev),
+ 1, boundary, lowaddr, BUS_SPACE_MAXADDR, NULL,
+ NULL, BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT,
+ 0, NULL, NULL, &sc->bge_cdata.bge_buffer_tag);
if (error != 0) {
device_printf(sc->bge_dev,
"could not allocate buffer dma tag\n");
@@ -3253,6 +3278,8 @@ bge_mbox_reorder(struct bge_softc *sc)
bus = device_get_parent(dev);
if (device_get_devclass(dev) != pcib)
break;
+ if (device_get_devclass(bus) != pci)
+ break;
for (i = 0; i < nitems(mbox_reorder_lists); i++) {
if (pci_get_vendor(dev) ==
mbox_reorder_lists[i].vendor &&
@@ -3264,8 +3291,6 @@ bge_mbox_reorder(struct bge_softc *sc)
return (1);
}
}
- if (device_get_devclass(bus) != pci)
- break;
}
return (0);
}
diff --git a/freebsd/sys/dev/bge/if_bgereg.h b/freebsd/sys/dev/bge/if_bgereg.h
index eb7686e7..58fe8040 100644
--- a/freebsd/sys/dev/bge/if_bgereg.h
+++ b/freebsd/sys/dev/bge/if_bgereg.h
@@ -2866,6 +2866,12 @@ struct bge_gib {
#define BGE_DMA_MAXADDR 0xFFFFFFFFFF
#endif
+#if (BUS_SPACE_MAXSIZE > 0xFFFFFFFF)
+#define BGE_DMA_BNDRY 0x100000000
+#else
+#define BGE_DMA_BNDRY 0
+#endif
+
/*
* Ring structures. Most of these reside in host memory and we tell
* the NIC where they are via the ring control blocks. The exceptions
diff --git a/freebsd/sys/dev/cadence/if_cgem.c b/freebsd/sys/dev/cadence/if_cgem.c
index 191362c4..34340f22 100644
--- a/freebsd/sys/dev/cadence/if_cgem.c
+++ b/freebsd/sys/dev/cadence/if_cgem.c
@@ -107,6 +107,14 @@ __FBSDID("$FreeBSD$");
#define CGEM_CKSUM_ASSIST (CSUM_IP | CSUM_TCP | CSUM_UDP | \
CSUM_TCP_IPV6 | CSUM_UDP_IPV6)
+#ifndef __rtems__
+static struct ofw_compat_data compat_data[] = {
+ { "cadence,gem", 1 },
+ { "cdns,macb", 1 },
+ { NULL, 0 },
+};
+#endif /* __rtems__ */
+
struct cgem_softc {
if_t ifp;
struct mtx sc_mtx;
@@ -1724,7 +1732,7 @@ cgem_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_is_compatible(dev, "cadence,gem"))
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
#endif /* __rtems__ */
diff --git a/freebsd/sys/dev/e1000/em_txrx.c b/freebsd/sys/dev/e1000/em_txrx.c
index c2b60743..4faf806e 100644
--- a/freebsd/sys/dev/e1000/em_txrx.c
+++ b/freebsd/sys/dev/e1000/em_txrx.c
@@ -459,16 +459,11 @@ em_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
prev = txr->tx_cidx_processed;
ntxd = scctx->isc_ntxd[0];
do {
+ MPASS(prev != cur);
delta = (int32_t)cur - (int32_t)prev;
- /*
- * XXX This appears to be a hack for first-packet.
- * A correct fix would prevent prev == cur in the first place.
- */
- MPASS(prev == 0 || delta != 0);
- if (prev == 0 && cur == 0)
- delta += 1;
if (delta < 0)
delta += ntxd;
+ MPASS(delta > 0);
DPRINTF(iflib_get_dev(adapter->ctx),
"%s: cidx_processed=%u cur=%u clear=%d delta=%d\n",
__FUNCTION__, prev, cur, clear, delta);
diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c
index 803b68ec..32eb4afe 100644
--- a/freebsd/sys/dev/e1000/if_em.c
+++ b/freebsd/sys/dev/e1000/if_em.c
@@ -251,6 +251,7 @@ static int em_if_mtu_set(if_ctx_t ctx, uint32_t mtu);
static void em_if_timer(if_ctx_t ctx, uint16_t qid);
static void em_if_vlan_register(if_ctx_t ctx, u16 vtag);
static void em_if_vlan_unregister(if_ctx_t ctx, u16 vtag);
+static void em_if_watchdog_reset(if_ctx_t ctx);
static void em_identify_hardware(if_ctx_t ctx);
static int em_allocate_pci_resources(if_ctx_t ctx);
@@ -262,10 +263,14 @@ static int em_setup_msix(if_ctx_t ctx);
static void em_initialize_transmit_unit(if_ctx_t ctx);
static void em_initialize_receive_unit(if_ctx_t ctx);
-static void em_if_enable_intr(if_ctx_t ctx);
-static void em_if_disable_intr(if_ctx_t ctx);
+static void em_if_intr_enable(if_ctx_t ctx);
+static void em_if_intr_disable(if_ctx_t ctx);
+static void igb_if_intr_enable(if_ctx_t ctx);
+static void igb_if_intr_disable(if_ctx_t ctx);
static int em_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid);
static int em_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid);
+static int igb_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid);
+static int igb_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid);
static void em_if_multi_set(if_ctx_t ctx);
static void em_if_update_admin_status(if_ctx_t ctx);
static void em_if_debug(if_ctx_t ctx);
@@ -295,7 +300,7 @@ static void em_disable_aspm(struct adapter *);
int em_intr(void *arg);
static void em_disable_promisc(if_ctx_t ctx);
-/* MSIX handlers */
+/* MSI-X handlers */
static int em_if_msix_intr_assign(if_ctx_t, int);
static int em_msix_link(void *);
static void em_handle_link(void *context);
@@ -376,8 +381,8 @@ static device_method_t em_if_methods[] = {
DEVMETHOD(ifdi_init, em_if_init),
DEVMETHOD(ifdi_stop, em_if_stop),
DEVMETHOD(ifdi_msix_intr_assign, em_if_msix_intr_assign),
- DEVMETHOD(ifdi_intr_enable, em_if_enable_intr),
- DEVMETHOD(ifdi_intr_disable, em_if_disable_intr),
+ DEVMETHOD(ifdi_intr_enable, em_if_intr_enable),
+ DEVMETHOD(ifdi_intr_disable, em_if_intr_disable),
DEVMETHOD(ifdi_tx_queues_alloc, em_if_tx_queues_alloc),
DEVMETHOD(ifdi_rx_queues_alloc, em_if_rx_queues_alloc),
DEVMETHOD(ifdi_queues_free, em_if_queues_free),
@@ -388,6 +393,7 @@ static device_method_t em_if_methods[] = {
DEVMETHOD(ifdi_mtu_set, em_if_mtu_set),
DEVMETHOD(ifdi_promisc_set, em_if_set_promisc),
DEVMETHOD(ifdi_timer, em_if_timer),
+ DEVMETHOD(ifdi_watchdog_reset, em_if_watchdog_reset),
DEVMETHOD(ifdi_vlan_register, em_if_vlan_register),
DEVMETHOD(ifdi_vlan_unregister, em_if_vlan_unregister),
DEVMETHOD(ifdi_get_counter, em_if_get_counter),
@@ -398,14 +404,47 @@ static device_method_t em_if_methods[] = {
DEVMETHOD_END
};
-/*
- * note that if (adapter->msix_mem) is replaced by:
- * if (adapter->intr_type == IFLIB_INTR_MSIX)
- */
static driver_t em_if_driver = {
"em_if", em_if_methods, sizeof(struct adapter)
};
+static device_method_t igb_if_methods[] = {
+ DEVMETHOD(ifdi_attach_pre, em_if_attach_pre),
+ DEVMETHOD(ifdi_attach_post, em_if_attach_post),
+ DEVMETHOD(ifdi_detach, em_if_detach),
+ DEVMETHOD(ifdi_shutdown, em_if_shutdown),
+ DEVMETHOD(ifdi_suspend, em_if_suspend),
+ DEVMETHOD(ifdi_resume, em_if_resume),
+ DEVMETHOD(ifdi_init, em_if_init),
+ DEVMETHOD(ifdi_stop, em_if_stop),
+ DEVMETHOD(ifdi_msix_intr_assign, em_if_msix_intr_assign),
+ DEVMETHOD(ifdi_intr_enable, igb_if_intr_enable),
+ DEVMETHOD(ifdi_intr_disable, igb_if_intr_disable),
+ DEVMETHOD(ifdi_tx_queues_alloc, em_if_tx_queues_alloc),
+ DEVMETHOD(ifdi_rx_queues_alloc, em_if_rx_queues_alloc),
+ DEVMETHOD(ifdi_queues_free, em_if_queues_free),
+ DEVMETHOD(ifdi_update_admin_status, em_if_update_admin_status),
+ DEVMETHOD(ifdi_multi_set, em_if_multi_set),
+ DEVMETHOD(ifdi_media_status, em_if_media_status),
+ DEVMETHOD(ifdi_media_change, em_if_media_change),
+ DEVMETHOD(ifdi_mtu_set, em_if_mtu_set),
+ DEVMETHOD(ifdi_promisc_set, em_if_set_promisc),
+ DEVMETHOD(ifdi_timer, em_if_timer),
+ DEVMETHOD(ifdi_watchdog_reset, em_if_watchdog_reset),
+ DEVMETHOD(ifdi_vlan_register, em_if_vlan_register),
+ DEVMETHOD(ifdi_vlan_unregister, em_if_vlan_unregister),
+ DEVMETHOD(ifdi_get_counter, em_if_get_counter),
+ DEVMETHOD(ifdi_led_func, em_if_led_func),
+ DEVMETHOD(ifdi_rx_queue_intr_enable, igb_if_rx_queue_intr_enable),
+ DEVMETHOD(ifdi_tx_queue_intr_enable, igb_if_tx_queue_intr_enable),
+ DEVMETHOD(ifdi_debug, em_if_debug),
+ DEVMETHOD_END
+};
+
+static driver_t igb_if_driver = {
+ "igb_if", igb_if_methods, sizeof(struct adapter)
+};
+
/*********************************************************************
* Tunable default values.
*********************************************************************/
@@ -525,7 +564,7 @@ static struct if_shared_ctx igb_sctx_init = {
.isc_admin_intrcnt = 1,
.isc_vendor_info = igb_vendor_info_array,
.isc_driver_version = em_driver_version,
- .isc_driver = &em_if_driver,
+ .isc_driver = &igb_if_driver,
.isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | IFLIB_NEED_ZERO_CSUM,
.isc_nrxd_min = {EM_MIN_RXD},
@@ -723,7 +762,6 @@ em_set_num_queues(if_ctx_t ctx)
*
* return 0 on success, positive on failure
*********************************************************************/
-
static int
em_if_attach_pre(if_ctx_t ctx)
{
@@ -733,15 +771,10 @@ em_if_attach_pre(if_ctx_t ctx)
struct e1000_hw *hw;
int error = 0;
- INIT_DEBUGOUT("em_if_attach_pre begin");
+ INIT_DEBUGOUT("em_if_attach_pre: begin");
dev = iflib_get_dev(ctx);
adapter = iflib_get_softc(ctx);
- if (resource_disabled("em", device_get_unit(dev))) {
- device_printf(dev, "Disabled by device hint\n");
- return (ENXIO);
- }
-
adapter->ctx = adapter->osdep.ctx = ctx;
adapter->dev = adapter->osdep.dev = dev;
scctx = adapter->shared = iflib_get_softc_ctx(ctx);
@@ -779,14 +812,13 @@ em_if_attach_pre(if_ctx_t ctx)
/* Determine hardware and mac info */
em_identify_hardware(ctx);
- scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR);
scctx->isc_tx_nsegments = EM_MAX_SCATTER;
scctx->isc_nrxqsets_max = scctx->isc_ntxqsets_max = em_set_num_queues(ctx);
- device_printf(dev, "attach_pre capping queues at %d\n", scctx->isc_ntxqsets_max);
+ if (bootverbose)
+ device_printf(dev, "attach_pre capping queues at %d\n",
+ scctx->isc_ntxqsets_max);
if (adapter->hw.mac.type >= igb_mac_min) {
- int try_second_bar;
-
scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] * sizeof(union e1000_adv_tx_desc), EM_DBA_ALIGN);
scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union e1000_adv_rx_desc), EM_DBA_ALIGN);
scctx->isc_txd_size[0] = sizeof(union e1000_adv_tx_desc);
@@ -800,14 +832,13 @@ em_if_attach_pre(if_ctx_t ctx)
CSUM_IP6_TCP | CSUM_IP6_UDP;
if (adapter->hw.mac.type != e1000_82575)
scctx->isc_tx_csum_flags |= CSUM_SCTP | CSUM_IP6_SCTP;
-
/*
** Some new devices, as with ixgbe, now may
** use a different BAR, so we need to keep
** track of which is used.
*/
- try_second_bar = pci_read_config(dev, scctx->isc_msix_bar, 4);
- if (try_second_bar == 0)
+ scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR);
+ if (pci_read_config(dev, scctx->isc_msix_bar, 4) == 0)
scctx->isc_msix_bar += 4;
} else if (adapter->hw.mac.type >= em_mac_min) {
scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]* sizeof(struct e1000_tx_desc), EM_DBA_ALIGN);
@@ -837,6 +868,16 @@ em_if_attach_pre(if_ctx_t ctx)
*/
scctx->isc_capenable &= ~(IFCAP_TSO4 | IFCAP_VLAN_HWTSO);
scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_IP_TSO;
+ /*
+ * We support MSI-X with 82574 only, but indicate to iflib(4)
+ * that it shall give MSI at least a try with other devices.
+ */
+ if (adapter->hw.mac.type == e1000_82574) {
+ scctx->isc_msix_bar = PCIR_BAR(EM_MSIX_BAR);
+ } else {
+ scctx->isc_msix_bar = -1;
+ scctx->isc_disable_msix = 1;
+ }
} else {
scctx->isc_txqsizes[0] = roundup2((scctx->isc_ntxd[0] + 1) * sizeof(struct e1000_tx_desc), EM_DBA_ALIGN);
scctx->isc_rxqsizes[0] = roundup2((scctx->isc_nrxd[0] + 1) * sizeof(struct e1000_rx_desc), EM_DBA_ALIGN);
@@ -847,6 +888,7 @@ em_if_attach_pre(if_ctx_t ctx)
scctx->isc_capabilities = scctx->isc_capenable = LEM_CAPS;
if (adapter->hw.mac.type < e1000_82543)
scctx->isc_capenable &= ~(IFCAP_HWCSUM|IFCAP_VLAN_HWCSUM);
+ /* INTx only */
scctx->isc_msix_bar = 0;
}
@@ -1092,13 +1134,12 @@ err_late:
*
* return 0 on success, positive on failure
*********************************************************************/
-
static int
em_if_detach(if_ctx_t ctx)
{
struct adapter *adapter = iflib_get_softc(ctx);
- INIT_DEBUGOUT("em_detach: begin");
+ INIT_DEBUGOUT("em_if_detach: begin");
e1000_phy_hw_reset(&adapter->hw);
@@ -1203,16 +1244,16 @@ em_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
* by the driver as a hw/sw initialization routine to get to a
* consistent state.
*
- * return 0 on success, positive on failure
**********************************************************************/
-
static void
em_if_init(if_ctx_t ctx)
{
struct adapter *adapter = iflib_get_softc(ctx);
+ if_softc_ctx_t scctx = adapter->shared;
struct ifnet *ifp = iflib_get_ifp(ctx);
struct em_tx_queue *tx_que;
int i;
+
INIT_DEBUGOUT("em_if_init: begin");
/* Get the latest mac address, User can use a LAA */
@@ -1242,7 +1283,14 @@ em_if_init(if_ctx_t ctx)
for (i = 0, tx_que = adapter->tx_queues; i < adapter->tx_num_queues; i++, tx_que++) {
struct tx_ring *txr = &tx_que->txr;
- txr->tx_rs_cidx = txr->tx_rs_pidx = txr->tx_cidx_processed = 0;
+ txr->tx_rs_cidx = txr->tx_rs_pidx;
+
+ /* Initialize the last processed descriptor to be the end of
+ * the ring, rather than the start, so that we avoid an
+ * off-by-one error when calculating how many descriptors are
+ * done in the credits_update function.
+ */
+ txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1;
}
/* Setup VLAN support, basic and offload if available */
@@ -1261,21 +1309,7 @@ em_if_init(if_ctx_t ctx)
/* Setup Multicast table */
em_if_multi_set(ctx);
- /*
- * Figure out the desired mbuf
- * pool for doing jumbos
- */
- if (adapter->hw.mac.max_frame_size <= 2048)
- adapter->rx_mbuf_sz = MCLBYTES;
-#ifndef CONTIGMALLOC_WORKS
- else
- adapter->rx_mbuf_sz = MJUMPAGESIZE;
-#else
- else if (adapter->hw.mac.max_frame_size <= 4096)
- adapter->rx_mbuf_sz = MJUMPAGESIZE;
- else
- adapter->rx_mbuf_sz = MJUM9BYTES;
-#endif
+ adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx);
em_initialize_receive_unit(ctx);
/* Use real VLAN Filter support? */
@@ -1295,7 +1329,7 @@ em_if_init(if_ctx_t ctx)
em_if_set_promisc(ctx, IFF_PROMISC);
e1000_clear_hw_cntrs_base_generic(&adapter->hw);
- /* MSI/X configuration for 82574 */
+ /* MSI-X configuration for 82574 */
if (adapter->hw.mac.type == e1000_82574) {
int tmp = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
@@ -1338,8 +1372,6 @@ em_intr(void *arg)
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
- if (adapter->intr_type != IFLIB_INTR_LEGACY)
- goto skip_stray;
/* Hot eject? */
if (reg_icr == 0xffffffff)
return FILTER_STRAY;
@@ -1356,7 +1388,14 @@ em_intr(void *arg)
(reg_icr & E1000_ICR_INT_ASSERTED) == 0)
return FILTER_STRAY;
-skip_stray:
+ /*
+ * Only MSI-X interrupts have one-shot behavior by taking advantage
+ * of the EIAC register. Thus, explicitly disable interrupts. This
+ * also works around the MSI message reordering errata on certain
+ * systems.
+ */
+ IFDI_INTR_DISABLE(ctx);
+
/* Link status change */
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
adapter->hw.mac.get_link_status = 1;
@@ -1369,59 +1408,49 @@ skip_stray:
return (FILTER_SCHEDULE_THREAD);
}
-static void
-igb_rx_enable_queue(struct adapter *adapter, struct em_rx_queue *rxq)
+static int
+em_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid)
{
- E1000_WRITE_REG(&adapter->hw, E1000_EIMS, rxq->eims);
-}
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct em_rx_queue *rxq = &adapter->rx_queues[rxqid];
-static void
-em_rx_enable_queue(struct adapter *adapter, struct em_rx_queue *rxq)
-{
E1000_WRITE_REG(&adapter->hw, E1000_IMS, rxq->eims);
+ return (0);
}
-static void
-igb_tx_enable_queue(struct adapter *adapter, struct em_tx_queue *txq)
+static int
+em_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid)
{
- E1000_WRITE_REG(&adapter->hw, E1000_EIMS, txq->eims);
-}
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct em_tx_queue *txq = &adapter->tx_queues[txqid];
-static void
-em_tx_enable_queue(struct adapter *adapter, struct em_tx_queue *txq)
-{
E1000_WRITE_REG(&adapter->hw, E1000_IMS, txq->eims);
+ return (0);
}
static int
-em_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid)
+igb_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid)
{
struct adapter *adapter = iflib_get_softc(ctx);
struct em_rx_queue *rxq = &adapter->rx_queues[rxqid];
- if (adapter->hw.mac.type >= igb_mac_min)
- igb_rx_enable_queue(adapter, rxq);
- else
- em_rx_enable_queue(adapter, rxq);
+ E1000_WRITE_REG(&adapter->hw, E1000_EIMS, rxq->eims);
return (0);
}
static int
-em_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid)
+igb_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid)
{
struct adapter *adapter = iflib_get_softc(ctx);
struct em_tx_queue *txq = &adapter->tx_queues[txqid];
- if (adapter->hw.mac.type >= igb_mac_min)
- igb_tx_enable_queue(adapter, txq);
- else
- em_tx_enable_queue(adapter, txq);
+ E1000_WRITE_REG(&adapter->hw, E1000_EIMS, txq->eims);
return (0);
}
/*********************************************************************
*
- * MSIX RX Interrupt Service routine
+ * MSI-X RX Interrupt Service routine
*
**********************************************************************/
static int
@@ -1436,7 +1465,7 @@ em_msix_que(void *arg)
/*********************************************************************
*
- * MSIX Link Fast Interrupt Service routine
+ * MSI-X Link Fast Interrupt Service routine
*
**********************************************************************/
static int
@@ -1689,37 +1718,24 @@ em_if_multi_set(if_ctx_t ctx)
}
}
-
/*********************************************************************
* Timer routine
*
- * This routine checks for link status and updates statistics.
+ * This routine schedules em_if_update_admin_status() to check for
+ * link status and to gather statistics as well as to perform some
+ * controller-specific hardware patting.
*
**********************************************************************/
-
static void
em_if_timer(if_ctx_t ctx, uint16_t qid)
{
- struct adapter *adapter = iflib_get_softc(ctx);
- struct em_rx_queue *que;
- int i;
- int trigger = 0;
if (qid != 0)
return;
iflib_admin_intr_deferred(ctx);
-
- /* Mask to use in the irq trigger */
- if (adapter->intr_type == IFLIB_INTR_MSIX) {
- for (i = 0, que = adapter->rx_queues; i < adapter->rx_num_queues; i++, que++)
- trigger |= que->eims;
- } else {
- trigger = E1000_ICS_RXDMT0;
- }
}
-
static void
em_if_update_admin_status(if_ctx_t ctx)
{
@@ -1825,21 +1841,30 @@ em_if_update_admin_status(if_ctx_t ctx)
E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_LINK | E1000_IMS_LSC);
}
+static void
+em_if_watchdog_reset(if_ctx_t ctx)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+
+ /*
+ * Just count the event; iflib(4) will already trigger a
+ * sufficient reset of the controller.
+ */
+ adapter->watchdog_events++;
+}
+
/*********************************************************************
*
* This routine disables all traffic on the adapter by issuing a
- * global reset on the MAC and deallocates TX/RX buffers.
+ * global reset on the MAC.
*
- * This routine should always be called with BOTH the CORE
- * and TX locks.
**********************************************************************/
-
static void
em_if_stop(if_ctx_t ctx)
{
struct adapter *adapter = iflib_get_softc(ctx);
- INIT_DEBUGOUT("em_stop: begin");
+ INIT_DEBUGOUT("em_if_stop: begin");
e1000_reset_hw(&adapter->hw);
if (adapter->hw.mac.type >= e1000_82544)
@@ -1849,7 +1874,6 @@ em_if_stop(if_ctx_t ctx)
e1000_cleanup_led(&adapter->hw);
}
-
/*********************************************************************
*
* Determine hardware revision.
@@ -1906,7 +1930,6 @@ em_allocate_pci_resources(if_ctx_t ctx)
for (rid = PCIR_BAR(0); rid < PCIR_CIS;) {
val = pci_read_config(dev, rid, 4);
if (EM_BAR_TYPE(val) == EM_BAR_TYPE_IO) {
- adapter->io_rid = rid;
break;
}
rid += 4;
@@ -1918,8 +1941,8 @@ em_allocate_pci_resources(if_ctx_t ctx)
device_printf(dev, "Unable to locate IO BAR\n");
return (ENXIO);
}
- adapter->ioport = bus_alloc_resource_any(dev,
- SYS_RES_IOPORT, &adapter->io_rid, RF_ACTIVE);
+ adapter->ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+ &rid, RF_ACTIVE);
if (adapter->ioport == NULL) {
device_printf(dev, "Unable to allocate bus resource: "
"ioport\n");
@@ -1939,7 +1962,7 @@ em_allocate_pci_resources(if_ctx_t ctx)
/*********************************************************************
*
- * Setup the MSIX Interrupt handlers
+ * Set up the MSI-X Interrupt handlers
*
**********************************************************************/
static int
@@ -1968,7 +1991,7 @@ em_if_msix_intr_assign(if_ctx_t ctx, int msix)
* Set the bit to enable interrupt
* in E1000_IMS -- bits 20 and 21
* are for RX0 and RX1, note this has
- * NOTHING to do with the MSIX vector
+ * NOTHING to do with the MSI-X vector
*/
if (adapter->hw.mac.type == e1000_82574) {
rx_que->eims = 1 << (20 + i);
@@ -1989,22 +2012,22 @@ em_if_msix_intr_assign(if_ctx_t ctx, int msix)
&adapter->rx_queues[i % adapter->rx_num_queues].que_irq,
IFLIB_INTR_TX, tx_que, tx_que->me, buf);
- tx_que->msix = (vector % adapter->tx_num_queues);
+ tx_que->msix = (vector % adapter->rx_num_queues);
/*
* Set the bit to enable interrupt
* in E1000_IMS -- bits 22 and 23
* are for TX0 and TX1, note this has
- * NOTHING to do with the MSIX vector
+ * NOTHING to do with the MSI-X vector
*/
if (adapter->hw.mac.type == e1000_82574) {
tx_que->eims = 1 << (22 + i);
adapter->ims |= tx_que->eims;
adapter->ivars |= (8 | tx_que->msix) << (8 + (i * 4));
} else if (adapter->hw.mac.type == e1000_82575) {
- tx_que->eims = E1000_EICR_TX_QUEUE0 << (i % adapter->tx_num_queues);
+ tx_que->eims = E1000_EICR_TX_QUEUE0 << i;
} else {
- tx_que->eims = 1 << (i % adapter->tx_num_queues);
+ tx_que->eims = 1 << i;
}
}
@@ -2044,7 +2067,7 @@ igb_configure_queues(struct adapter *adapter)
E1000_GPIE_MSIX_MODE | E1000_GPIE_EIAME |
E1000_GPIE_PBA | E1000_GPIE_NSICR);
- /* Turn on MSIX */
+ /* Turn on MSI-X */
switch (adapter->hw.mac.type) {
case e1000_82580:
case e1000_i350:
@@ -2178,7 +2201,7 @@ em_free_pci_resources(if_ctx_t ctx)
struct em_rx_queue *que = adapter->rx_queues;
device_t dev = iflib_get_dev(ctx);
- /* Release all msix queue resources */
+ /* Release all MSI-X queue resources */
if (adapter->intr_type == IFLIB_INTR_MSIX)
iflib_irq_free(ctx, &adapter->irq);
@@ -2186,24 +2209,26 @@ em_free_pci_resources(if_ctx_t ctx)
iflib_irq_free(ctx, &que->que_irq);
}
- /* First release all the interrupt resources */
if (adapter->memory != NULL) {
bus_release_resource(dev, SYS_RES_MEMORY,
- PCIR_BAR(0), adapter->memory);
+ rman_get_rid(adapter->memory), adapter->memory);
adapter->memory = NULL;
}
if (adapter->flash != NULL) {
bus_release_resource(dev, SYS_RES_MEMORY,
- EM_FLASH, adapter->flash);
+ rman_get_rid(adapter->flash), adapter->flash);
adapter->flash = NULL;
}
- if (adapter->ioport != NULL)
+
+ if (adapter->ioport != NULL) {
bus_release_resource(dev, SYS_RES_IOPORT,
- adapter->io_rid, adapter->ioport);
+ rman_get_rid(adapter->ioport), adapter->ioport);
+ adapter->ioport = NULL;
+ }
}
-/* Setup MSI or MSI/X */
+/* Set up MSI or MSI-X */
static int
em_setup_msix(if_ctx_t ctx)
{
@@ -2217,11 +2242,9 @@ em_setup_msix(if_ctx_t ctx)
/*********************************************************************
*
- * Initialize the hardware to a configuration
- * as specified by the adapter structure.
+ * Workaround for SmartSpeed on 82541 and 82547 controllers
*
**********************************************************************/
-
static void
lem_smartspeed(struct adapter *adapter)
{
@@ -2386,6 +2409,12 @@ igb_init_dmac(struct adapter *adapter, u32 pba)
}
}
+/*********************************************************************
+ *
+ * Initialize the hardware to a configuration as specified by the
+ * adapter structure.
+ *
+ **********************************************************************/
static void
em_reset(if_ctx_t ctx)
{
@@ -2620,6 +2649,11 @@ em_reset(if_ctx_t ctx)
e1000_check_for_link(hw);
}
+/*
+ * Initialise the RSS mapping for NICs that support multiple transmit/
+ * receive rings.
+ */
+
#define RSSKEYLEN 10
static void
em_initialize_rss_mapping(struct adapter *adapter)
@@ -2660,7 +2694,6 @@ em_initialize_rss_mapping(struct adapter *adapter)
E1000_MRQC_RSS_FIELD_IPV6_TCP_EX |
E1000_MRQC_RSS_FIELD_IPV6_EX |
E1000_MRQC_RSS_FIELD_IPV6);
-
}
static void
@@ -2760,7 +2793,7 @@ igb_initialize_rss_mapping(struct adapter *adapter)
/*********************************************************************
*
- * Setup networking device structure and register an interface.
+ * Setup networking device structure and register interface media.
*
**********************************************************************/
static int
@@ -2845,7 +2878,9 @@ em_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs
txr->tx_paddr = paddrs[i*ntxqs];
}
- device_printf(iflib_get_dev(ctx), "allocated for %d tx_queues\n", adapter->tx_num_queues);
+ if (bootverbose)
+ device_printf(iflib_get_dev(ctx),
+ "allocated for %d tx_queues\n", adapter->tx_num_queues);
return (0);
fail:
em_if_queues_free(ctx);
@@ -2883,8 +2918,10 @@ em_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs
rxr->rx_base = (union e1000_rx_desc_extended *)vaddrs[i*nrxqs];
rxr->rx_paddr = paddrs[i*nrxqs];
}
-
- device_printf(iflib_get_dev(ctx), "allocated for %d rx_queues\n", adapter->rx_num_queues);
+
+ if (bootverbose)
+ device_printf(iflib_get_dev(ctx),
+ "allocated for %d rx_queues\n", adapter->rx_num_queues);
return (0);
fail:
@@ -3127,7 +3164,7 @@ em_initialize_receive_unit(if_ctx_t ctx)
rfctl = E1000_READ_REG(hw, E1000_RFCTL);
rfctl |= E1000_RFCTL_EXTEN;
/*
- * When using MSIX interrupts we need to throttle
+ * When using MSI-X interrupts we need to throttle
* using the EITR register (82574 only)
*/
if (hw->mac.type == e1000_82574) {
@@ -3371,7 +3408,7 @@ em_setup_vlan_hw_support(struct adapter *adapter)
}
static void
-em_if_enable_intr(if_ctx_t ctx)
+em_if_intr_enable(if_ctx_t ctx)
{
struct adapter *adapter = iflib_get_softc(ctx);
struct e1000_hw *hw = &adapter->hw;
@@ -3380,30 +3417,51 @@ em_if_enable_intr(if_ctx_t ctx)
if (hw->mac.type == e1000_82574) {
E1000_WRITE_REG(hw, EM_EIAC, EM_MSIX_MASK);
ims_mask |= adapter->ims;
- } else if (adapter->intr_type == IFLIB_INTR_MSIX && hw->mac.type >= igb_mac_min) {
- u32 mask = (adapter->que_mask | adapter->link_mask);
-
- E1000_WRITE_REG(&adapter->hw, E1000_EIAC, mask);
- E1000_WRITE_REG(&adapter->hw, E1000_EIAM, mask);
- E1000_WRITE_REG(&adapter->hw, E1000_EIMS, mask);
- ims_mask = E1000_IMS_LSC;
}
-
E1000_WRITE_REG(hw, E1000_IMS, ims_mask);
}
static void
-em_if_disable_intr(if_ctx_t ctx)
+em_if_intr_disable(if_ctx_t ctx)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct e1000_hw *hw = &adapter->hw;
+
+ if (hw->mac.type == e1000_82574)
+ E1000_WRITE_REG(hw, EM_EIAC, 0);
+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+}
+
+static void
+igb_if_intr_enable(if_ctx_t ctx)
+{
+ struct adapter *adapter = iflib_get_softc(ctx);
+ struct e1000_hw *hw = &adapter->hw;
+ u32 mask;
+
+ if (__predict_true(adapter->intr_type == IFLIB_INTR_MSIX)) {
+ mask = (adapter->que_mask | adapter->link_mask);
+ E1000_WRITE_REG(hw, E1000_EIAC, mask);
+ E1000_WRITE_REG(hw, E1000_EIAM, mask);
+ E1000_WRITE_REG(hw, E1000_EIMS, mask);
+ E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_LSC);
+ } else
+ E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK);
+ E1000_WRITE_FLUSH(hw);
+}
+
+static void
+igb_if_intr_disable(if_ctx_t ctx)
{
struct adapter *adapter = iflib_get_softc(ctx);
struct e1000_hw *hw = &adapter->hw;
- if (adapter->intr_type == IFLIB_INTR_MSIX) {
- if (hw->mac.type >= igb_mac_min)
- E1000_WRITE_REG(&adapter->hw, E1000_EIMC, ~0);
- E1000_WRITE_REG(&adapter->hw, E1000_EIAC, 0);
+ if (__predict_true(adapter->intr_type == IFLIB_INTR_MSIX)) {
+ E1000_WRITE_REG(hw, E1000_EIMC, 0xffffffff);
+ E1000_WRITE_REG(hw, E1000_EIAC, 0);
}
- E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff);
+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+ E1000_WRITE_FLUSH(hw);
}
/*
@@ -4001,13 +4059,7 @@ em_add_hw_stats(struct adapter *adapter)
"Driver dropped packets");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
CTLFLAG_RD, &adapter->link_irq,
- "Link MSIX IRQ Handled");
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail",
- CTLFLAG_RD, &adapter->mbuf_defrag_failed,
- "Defragmenting mbuf chain failed");
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",
- CTLFLAG_RD, &adapter->no_tx_dma_setup,
- "Driver tx dma failure in xmit");
+ "Link MSI-X IRQ Handled");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "rx_overruns",
CTLFLAG_RD, &adapter->rx_overruns,
"RX overruns");
@@ -4518,7 +4570,7 @@ em_print_debug_info(struct adapter *adapter)
/*
* 82574 only:
- * Write a new value to the EEPROM increasing the number of MSIX
+ * Write a new value to the EEPROM increasing the number of MSI-X
* vectors from 3 to 5, for proper multiqueue support.
*/
static void
@@ -4530,10 +4582,11 @@ em_enable_vectors_82574(if_ctx_t ctx)
u16 edata;
e1000_read_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata);
- printf("Current cap: %#06x\n", edata);
+ if (bootverbose)
+ device_printf(dev, "EM_NVM_PCIE_CTRL = %#06x\n", edata);
if (((edata & EM_NVM_MSIX_N_MASK) >> EM_NVM_MSIX_N_SHIFT) != 4) {
device_printf(dev, "Writing to eeprom: increasing "
- "reported MSIX vectors from 3 to 5...\n");
+ "reported MSI-X vectors from 3 to 5...\n");
edata &= ~(EM_NVM_MSIX_N_MASK);
edata |= 4 << EM_NVM_MSIX_N_SHIFT;
e1000_write_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata);
diff --git a/freebsd/sys/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h
index d573107b..392f6b3a 100644
--- a/freebsd/sys/dev/e1000/if_em.h
+++ b/freebsd/sys/dev/e1000/if_em.h
@@ -352,8 +352,8 @@
/*
* 82574 has a nonstandard address for EIAC
- * and since its only used in MSIX, and in
- * the em driver only 82574 uses MSIX we can
+ * and since its only used in MSI-X, and in
+ * the em driver only 82574 uses MSI-X we can
* solve it just using this define.
*/
#define EM_EIAC 0x000DC
@@ -468,7 +468,6 @@ struct adapter {
struct resource *memory;
struct resource *flash;
struct resource *ioport;
- int io_rid;
struct resource *res;
void *tag;
@@ -520,7 +519,6 @@ struct adapter {
u64 que_mask;
-
struct em_int_delay_info tx_int_delay;
struct em_int_delay_info tx_abs_int_delay;
struct em_int_delay_info rx_int_delay;
@@ -530,9 +528,6 @@ struct adapter {
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
unsigned long link_irq;
- unsigned long mbuf_defrag_failed;
- unsigned long no_tx_dma_setup;
- unsigned long no_tx_map_avail;
unsigned long rx_overruns;
unsigned long watchdog_events;
diff --git a/freebsd/sys/dev/e1000/igb_txrx.c b/freebsd/sys/dev/e1000/igb_txrx.c
index c54315f0..6da52b7e 100644
--- a/freebsd/sys/dev/e1000/igb_txrx.c
+++ b/freebsd/sys/dev/e1000/igb_txrx.c
@@ -334,16 +334,11 @@ igb_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
prev = txr->tx_cidx_processed;
ntxd = scctx->isc_ntxd[0];
do {
+ MPASS(prev != cur);
delta = (int32_t)cur - (int32_t)prev;
- /*
- * XXX This appears to be a hack for first-packet.
- * A correct fix would prevent prev == cur in the first place.
- */
- MPASS(prev == 0 || delta != 0);
- if (prev == 0 && cur == 0)
- delta += 1;
if (delta < 0)
delta += ntxd;
+ MPASS(delta > 0);
processed += delta;
prev = cur;
diff --git a/freebsd/sys/dev/evdev/evdev.c b/freebsd/sys/dev/evdev/evdev.c
index 63e651a2..90d6423d 100644
--- a/freebsd/sys/dev/evdev/evdev.c
+++ b/freebsd/sys/dev/evdev/evdev.c
@@ -75,14 +75,16 @@ int evdev_rcpt_mask = EVDEV_RCPT_HW_MOUSE | EVDEV_RCPT_HW_KBD;
#endif /* __rtems__ */
int evdev_sysmouse_t_axis = 0;
-#ifdef EVDEV_SUPPORT
SYSCTL_NODE(_kern, OID_AUTO, evdev, CTLFLAG_RW, 0, "Evdev args");
+#ifdef EVDEV_SUPPORT
SYSCTL_INT(_kern_evdev, OID_AUTO, rcpt_mask, CTLFLAG_RW, &evdev_rcpt_mask, 0,
"Who is receiving events: bit0 - sysmouse, bit1 - kbdmux, "
"bit2 - mouse hardware, bit3 - keyboard hardware");
SYSCTL_INT(_kern_evdev, OID_AUTO, sysmouse_t_axis, CTLFLAG_RW,
&evdev_sysmouse_t_axis, 0, "Extract T-axis from 0-none, 1-ums, 2-psm");
#endif
+SYSCTL_NODE(_kern_evdev, OID_AUTO, input, CTLFLAG_RD, 0,
+ "Evdev input devices");
static void evdev_start_repeat(struct evdev_dev *, uint16_t);
static void evdev_stop_repeat(struct evdev_dev *);
@@ -202,6 +204,87 @@ evdev_estimate_report_size(struct evdev_dev *evdev)
return (size);
}
+static void
+evdev_sysctl_create(struct evdev_dev *evdev)
+{
+ struct sysctl_oid *ev_sysctl_tree;
+ char ev_unit_str[8];
+
+ snprintf(ev_unit_str, sizeof(ev_unit_str), "%d", evdev->ev_unit);
+ sysctl_ctx_init(&evdev->ev_sysctl_ctx);
+
+ ev_sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&evdev->ev_sysctl_ctx,
+ SYSCTL_STATIC_CHILDREN(_kern_evdev_input), OID_AUTO,
+ ev_unit_str, CTLFLAG_RD, NULL, "", "device index");
+
+ SYSCTL_ADD_STRING(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "name", CTLFLAG_RD,
+ evdev->ev_name, 0,
+ "Input device name");
+
+ SYSCTL_ADD_STRUCT(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "id", CTLFLAG_RD,
+ &evdev->ev_id, input_id,
+ "Input device identification");
+
+ /* ioctl returns ENOENT if phys is not set. sysctl returns "" here */
+ SYSCTL_ADD_STRING(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "phys", CTLFLAG_RD,
+ evdev->ev_shortname, 0,
+ "Input device short name");
+
+ /* ioctl returns ENOENT if uniq is not set. sysctl returns "" here */
+ SYSCTL_ADD_STRING(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "uniq", CTLFLAG_RD,
+ evdev->ev_serial, 0,
+ "Input device unique number");
+
+ SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "props", CTLFLAG_RD,
+ evdev->ev_prop_flags, sizeof(evdev->ev_prop_flags), "",
+ "Input device properties");
+
+ SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "type_bits", CTLFLAG_RD,
+ evdev->ev_type_flags, sizeof(evdev->ev_type_flags), "",
+ "Input device supported events types");
+
+ SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "key_bits", CTLFLAG_RD,
+ evdev->ev_key_flags, sizeof(evdev->ev_key_flags),
+ "", "Input device supported keys");
+
+ SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "rel_bits", CTLFLAG_RD,
+ evdev->ev_rel_flags, sizeof(evdev->ev_rel_flags), "",
+ "Input device supported relative events");
+
+ SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "abs_bits", CTLFLAG_RD,
+ evdev->ev_abs_flags, sizeof(evdev->ev_abs_flags), "",
+ "Input device supported absolute events");
+
+ SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "msc_bits", CTLFLAG_RD,
+ evdev->ev_msc_flags, sizeof(evdev->ev_msc_flags), "",
+ "Input device supported miscellaneous events");
+
+ SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "led_bits", CTLFLAG_RD,
+ evdev->ev_led_flags, sizeof(evdev->ev_led_flags), "",
+ "Input device supported LED events");
+
+ SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "snd_bits", CTLFLAG_RD,
+ evdev->ev_snd_flags, sizeof(evdev->ev_snd_flags), "",
+ "Input device supported sound events");
+
+ SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
+ SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "sw_bits", CTLFLAG_RD,
+ evdev->ev_sw_flags, sizeof(evdev->ev_sw_flags), "",
+ "Input device supported switch events");
+}
+
static int
evdev_register_common(struct evdev_dev *evdev)
{
@@ -241,6 +324,12 @@ evdev_register_common(struct evdev_dev *evdev)
/* Create char device node */
ret = evdev_cdev_create(evdev);
+ if (ret != 0)
+ goto bail_out;
+
+ /* Create sysctls (for device enumeration without /dev/input access rights) */
+ evdev_sysctl_create(evdev);
+
bail_out:
return (ret);
}
@@ -278,6 +367,8 @@ evdev_unregister(struct evdev_dev *evdev)
debugf(evdev, "%s: unregistered evdev provider: %s\n",
evdev->ev_shortname, evdev->ev_name);
+ sysctl_ctx_free(&evdev->ev_sysctl_ctx);
+
EVDEV_LOCK(evdev);
evdev->ev_cdev->si_drv1 = NULL;
/* Wake up sleepers */
diff --git a/freebsd/sys/dev/evdev/evdev_private.h b/freebsd/sys/dev/evdev/evdev_private.h
index 71bdecaa..d7f0b4ea 100644
--- a/freebsd/sys/dev/evdev/evdev_private.h
+++ b/freebsd/sys/dev/evdev/evdev_private.h
@@ -32,9 +32,12 @@
#include <sys/bitstring.h>
#include <sys/kbio.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/mutex.h>
#include <sys/queue.h>
#include <sys/selinfo.h>
+#include <sys/sysctl.h>
#include <dev/evdev/evdev.h>
#include <dev/evdev/input.h>
@@ -132,6 +135,9 @@ struct evdev_dev
const struct evdev_methods * ev_methods;
void * ev_softc;
+ /* Sysctl: */
+ struct sysctl_ctx_list ev_sysctl_ctx;
+
LIST_ENTRY(evdev_dev) ev_link;
LIST_HEAD(, evdev_client) ev_clients;
};
diff --git a/freebsd/sys/dev/extres/clk/clk.h b/freebsd/sys/dev/extres/clk/clk.h
index 617cd5e7..7e9fe4eb 100644
--- a/freebsd/sys/dev/extres/clk/clk.h
+++ b/freebsd/sys/dev/extres/clk/clk.h
@@ -48,6 +48,7 @@
#define CLK_SET_ROUND_EXACT 0
#define CLK_SET_ROUND_UP 0x00000001
#define CLK_SET_ROUND_DOWN 0x00000002
+#define CLK_SET_ROUND_MULTIPLE 0x00000004
#define CLK_SET_ROUND_ANY (CLK_SET_ROUND_UP | CLK_SET_ROUND_DOWN)
#define CLK_SET_USER_MASK 0x0000FFFF
diff --git a/freebsd/sys/dev/fb/fbd.c b/freebsd/sys/dev/fb/fbd.c
index 871e193c..56f3605d 100644
--- a/freebsd/sys/dev/fb/fbd.c
+++ b/freebsd/sys/dev/fb/fbd.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
+#include <sys/eventhandler.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
diff --git a/freebsd/sys/dev/fdt/fdt_common.c b/freebsd/sys/dev/fdt/fdt_common.c
index ff32dc0a..12979fda 100644
--- a/freebsd/sys/dev/fdt/fdt_common.c
+++ b/freebsd/sys/dev/fdt/fdt_common.c
@@ -401,6 +401,9 @@ fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc)
*phy_addr = phy_reg;
+ if (phy_sc == NULL)
+ return (0);
+
/*
* Search for softc used to communicate with phy.
*/
diff --git a/freebsd/sys/dev/gpio/gpiobus.c b/freebsd/sys/dev/gpio/gpiobus.c
index 2b1899e6..d256ee4a 100644
--- a/freebsd/sys/dev/gpio/gpiobus.c
+++ b/freebsd/sys/dev/gpio/gpiobus.c
@@ -257,13 +257,6 @@ gpiobus_alloc_ivars(struct gpiobus_ivar *devi)
M_NOWAIT | M_ZERO);
if (devi->pins == NULL)
return (ENOMEM);
- devi->flags = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (devi->flags == NULL) {
- free(devi->pins, M_DEVBUF);
- return (ENOMEM);
- }
-
return (0);
}
@@ -271,14 +264,11 @@ void
gpiobus_free_ivars(struct gpiobus_ivar *devi)
{
- if (devi->flags) {
- free(devi->flags, M_DEVBUF);
- devi->flags = NULL;
- }
if (devi->pins) {
free(devi->pins, M_DEVBUF);
devi->pins = NULL;
}
+ devi->npins = 0;
}
int
@@ -328,6 +318,34 @@ gpiobus_release_pin(device_t bus, uint32_t pin)
}
static int
+gpiobus_acquire_child_pins(device_t dev, device_t child)
+{
+ struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
+ int i;
+
+ for (i = 0; i < devi->npins; i++) {
+ /* Reserve the GPIO pin. */
+ if (gpiobus_acquire_pin(dev, devi->pins[i]) != 0) {
+ device_printf(child, "cannot acquire pin %d\n",
+ devi->pins[i]);
+ while (--i >= 0) {
+ (void)gpiobus_release_pin(dev,
+ devi->pins[i]);
+ }
+ gpiobus_free_ivars(devi);
+ return (EBUSY);
+ }
+ }
+ for (i = 0; i < devi->npins; i++) {
+ /* Use the child name as pin name. */
+ GPIOBUS_PIN_SETNAME(dev, devi->pins[i],
+ device_get_nameunit(child));
+
+ }
+ return (0);
+}
+
+static int
gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
{
struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
@@ -351,17 +369,66 @@ gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
for (i = 0; i < 32; i++) {
if ((mask & (1 << i)) == 0)
continue;
- /* Reserve the GPIO pin. */
- if (gpiobus_acquire_pin(sc->sc_busdev, i) != 0) {
- gpiobus_free_ivars(devi);
- return (EINVAL);
- }
devi->pins[npins++] = i;
- /* Use the child name as pin name. */
- GPIOBUS_PIN_SETNAME(sc->sc_busdev, i,
- device_get_nameunit(child));
}
+ if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0)
+ return (EINVAL);
+ return (0);
+}
+
+static int
+gpiobus_parse_pin_list(struct gpiobus_softc *sc, device_t child,
+ const char *pins)
+{
+ struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
+ const char *p;
+ char *endp;
+ unsigned long pin;
+ int i, npins;
+
+ npins = 0;
+ p = pins;
+ for (;;) {
+ pin = strtoul(p, &endp, 0);
+ if (endp == p)
+ break;
+ npins++;
+ if (*endp == '\0')
+ break;
+ p = endp + 1;
+ }
+
+ if (*endp != '\0') {
+ device_printf(child, "garbage in the pin list: %s\n", endp);
+ return (EINVAL);
+ }
+ if (npins == 0) {
+ device_printf(child, "empty pin list\n");
+ return (EINVAL);
+ }
+
+ devi->npins = npins;
+ if (gpiobus_alloc_ivars(devi) != 0) {
+ device_printf(child, "cannot allocate device ivars\n");
+ return (EINVAL);
+ }
+
+ i = 0;
+ p = pins;
+ for (;;) {
+ pin = strtoul(p, &endp, 0);
+
+ devi->pins[i] = pin;
+
+ if (*endp == '\0')
+ break;
+ i++;
+ p = endp + 1;
+ }
+
+ if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0)
+ return (EINVAL);
return (0);
}
@@ -541,15 +608,26 @@ gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
struct gpiobus_ivar *devi;
device_t child;
- int irq, pins;
+ const char *pins;
+ int irq, pinmask;
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
devi = GPIOBUS_IVAR(child);
- resource_int_value(dname, dunit, "pins", &pins);
- if (gpiobus_parse_pins(sc, child, pins)) {
- resource_list_free(&devi->rl);
- free(devi, M_DEVBUF);
- device_delete_child(bus, child);
+ if (resource_int_value(dname, dunit, "pins", &pinmask) == 0) {
+ if (gpiobus_parse_pins(sc, child, pinmask)) {
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
+ device_delete_child(bus, child);
+ return;
+ }
+ }
+ else if (resource_string_value(dname, dunit, "pin_list", &pins) == 0) {
+ if (gpiobus_parse_pin_list(sc, child, pins)) {
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
+ device_delete_child(bus, child);
+ return;
+ }
}
if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
@@ -576,6 +654,61 @@ gpiobus_set_resource(device_t dev, device_t child, int type, int rid,
return (0);
}
+static int
+gpiobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct gpiobus_ivar *devi;
+
+ devi = GPIOBUS_IVAR(child);
+ switch (which) {
+ case GPIOBUS_IVAR_NPINS:
+ *result = devi->npins;
+ break;
+ case GPIOBUS_IVAR_PINS:
+ /* Children do not ever need to directly examine this. */
+ return (ENOTSUP);
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+static int
+gpiobus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct gpiobus_ivar *devi;
+ const uint32_t *ptr;
+ int i;
+
+ devi = GPIOBUS_IVAR(child);
+ switch (which) {
+ case GPIOBUS_IVAR_NPINS:
+ /* GPIO ivars are set once. */
+ if (devi->npins != 0) {
+ return (EBUSY);
+ }
+ devi->npins = value;
+ if (gpiobus_alloc_ivars(devi) != 0) {
+ device_printf(child, "cannot allocate device ivars\n");
+ devi->npins = 0;
+ return (ENOMEM);
+ }
+ break;
+ case GPIOBUS_IVAR_PINS:
+ ptr = (const uint32_t *)value;
+ for (i = 0; i < devi->npins; i++)
+ devi->pins[i] = ptr[i];
+ if (gpiobus_acquire_child_pins(dev, child) != 0)
+ return (EBUSY);
+ break;
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
static struct resource *
gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
@@ -835,6 +968,8 @@ static device_method_t gpiobus_methods[] = {
DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str),
DEVMETHOD(bus_child_location_str, gpiobus_child_location_str),
DEVMETHOD(bus_hinted_child, gpiobus_hinted_child),
+ DEVMETHOD(bus_read_ivar, gpiobus_read_ivar),
+ DEVMETHOD(bus_write_ivar, gpiobus_write_ivar),
/* GPIO protocol */
DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus),
diff --git a/freebsd/sys/dev/gpio/gpiobusvar.h b/freebsd/sys/dev/gpio/gpiobusvar.h
index 29677298..3ba8993e 100644
--- a/freebsd/sys/dev/gpio/gpiobusvar.h
+++ b/freebsd/sys/dev/gpio/gpiobusvar.h
@@ -107,10 +107,22 @@ struct gpiobus_ivar
{
struct resource_list rl; /* isr resource list */
uint32_t npins; /* pins total */
- uint32_t *flags; /* pins flags */
uint32_t *pins; /* pins map */
};
+enum gpiobus_ivars {
+ GPIOBUS_IVAR_NPINS = 10500,
+ GPIOBUS_IVAR_PINS,
+};
+
+#define GPIOBUS_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(gpiobus, var, GPIOBUS, ivar, type)
+
+GPIOBUS_ACCESSOR(npins, NPINS, uint32_t)
+GPIOBUS_ACCESSOR(pins, PINS, const uint32_t *)
+
+#undef GPIOBUS_ACCESSOR
+
#ifdef FDT
struct ofw_gpiobus_devinfo {
struct gpiobus_ivar opd_dinfo;
diff --git a/freebsd/sys/dev/gpio/ofw_gpiobus.c b/freebsd/sys/dev/gpio/ofw_gpiobus.c
index ac0ea9bf..1cf3aa82 100644
--- a/freebsd/sys/dev/gpio/ofw_gpiobus.c
+++ b/freebsd/sys/dev/gpio/ofw_gpiobus.c
@@ -327,10 +327,8 @@ ofw_gpiobus_setup_devinfo(device_t bus, device_t child, phandle_t node)
ofw_gpiobus_destroy_devinfo(bus, dinfo);
return (NULL);
}
- for (i = 0; i < devi->npins; i++) {
- devi->flags[i] = pins[i].flags;
+ for (i = 0; i < devi->npins; i++)
devi->pins[i] = pins[i].pin;
- }
free(pins, M_DEVBUF);
/* Parse the interrupt resources. */
if (ofw_bus_intr_to_rl(bus, node, &dinfo->opd_dinfo.rl, NULL) != 0) {
diff --git a/freebsd/sys/dev/iicbus/iicbus.c b/freebsd/sys/dev/iicbus/iicbus.c
index d1e55483..db8c8d92 100644
--- a/freebsd/sys/dev/iicbus/iicbus.c
+++ b/freebsd/sys/dev/iicbus/iicbus.c
@@ -196,9 +196,6 @@ iicbus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
case IICBUS_IVAR_ADDR:
*result = devi->addr;
break;
- case IICBUS_IVAR_NOSTOP:
- *result = devi->nostop;
- break;
}
return (0);
}
@@ -215,9 +212,6 @@ iicbus_write_ivar(device_t bus, device_t child, int which, uintptr_t value)
if (devi->addr != 0)
return (EINVAL);
devi->addr = value;
- case IICBUS_IVAR_NOSTOP:
- devi->nostop = value;
- break;
}
return (0);
}
diff --git a/freebsd/sys/dev/iicbus/iicbus.h b/freebsd/sys/dev/iicbus/iicbus.h
index 503305c7..c6382b63 100644
--- a/freebsd/sys/dev/iicbus/iicbus.h
+++ b/freebsd/sys/dev/iicbus/iicbus.h
@@ -41,6 +41,7 @@ struct iicbus_softc
{
device_t dev; /* Myself */
device_t owner; /* iicbus owner device structure */
+ device_t busydev; /* iicbus_release_bus calls unbusy on this */
u_int owncount; /* iicbus ownership nesting count */
u_char started; /* address of the 'started' slave
* 0 if no start condition succeeded */
@@ -54,24 +55,27 @@ struct iicbus_ivar
{
uint32_t addr;
struct resource_list rl;
- bool nostop;
};
enum {
- IICBUS_IVAR_ADDR, /* Address or base address */
- IICBUS_IVAR_NOSTOP, /* nostop defaults */
+ IICBUS_IVAR_ADDR /* Address or base address */
};
#define IICBUS_ACCESSOR(A, B, T) \
__BUS_ACCESSOR(iicbus, A, IICBUS, B, T)
IICBUS_ACCESSOR(addr, ADDR, uint32_t)
-IICBUS_ACCESSOR(nostop, NOSTOP, bool)
#define IICBUS_LOCK(sc) mtx_lock(&(sc)->lock)
#define IICBUS_UNLOCK(sc) mtx_unlock(&(sc)->lock)
#define IICBUS_ASSERT_LOCKED(sc) mtx_assert(&(sc)->lock, MA_OWNED)
+#ifdef FDT
+#define IICBUS_FDT_PNP_INFO(t) FDTCOMPAT_PNP_INFO(t, iicbus)
+#else
+#define IICBUS_FDT_PNP_INFO(t)
+#endif
+
int iicbus_generic_intr(device_t dev, int event, char *buf);
void iicbus_init_frequency(device_t dev, u_int bus_freq);
diff --git a/freebsd/sys/dev/iicbus/iiconf.c b/freebsd/sys/dev/iicbus/iiconf.c
index afdce118..c4926852 100644
--- a/freebsd/sys/dev/iicbus/iiconf.c
+++ b/freebsd/sys/dev/iicbus/iiconf.c
@@ -44,6 +44,18 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/iicbus_if.h>
/*
+ * Encode a system errno value into the IIC_Exxxxx space by setting the
+ * IIC_ERRNO marker bit, so that iic2errno() can turn it back into a plain
+ * system errno value later. This lets controller- and bus-layer code get
+ * important system errno values (such as EINTR/ERESTART) back to the caller.
+ */
+int
+errno2iic(int error)
+{
+ return ((error == 0) ? 0 : error | IIC_ERRNO);
+}
+
+/*
* Translate IIC_Exxxxx status values to vaguely-equivelent errno values.
*/
int
@@ -61,7 +73,22 @@ iic2errno(int iic_status)
case IIC_ENOTSUPP: return (EOPNOTSUPP);
case IIC_ENOADDR: return (EADDRNOTAVAIL);
case IIC_ERESOURCE: return (ENOMEM);
- default: return (EIO);
+ default:
+ /*
+ * If the high bit is set, that means it's a system errno value
+ * that was encoded into the IIC_Exxxxxx space by setting the
+ * IIC_ERRNO marker bit. If lots of high-order bits are set,
+ * then it's one of the negative pseudo-errors such as ERESTART
+ * and we return it as-is. Otherwise it's a plain "small
+ * positive integer" errno, so just remove the IIC_ERRNO marker
+ * bit. If it's some unknown number without the high bit set,
+ * there isn't much we can do except call it an I/O error.
+ */
+ if ((iic_status & IIC_ERRNO) == 0)
+ return (EIO);
+ if ((iic_status & 0xFFFF0000) != 0)
+ return (iic_status);
+ return (iic_status & ~IIC_ERRNO);
}
}
@@ -99,7 +126,7 @@ iicbus_poll(struct iicbus_softc *sc, int how)
return (IIC_EBUSBSY);
}
- return (error);
+ return (errno2iic(error));
}
/*
@@ -130,6 +157,18 @@ iicbus_request_bus(device_t bus, device_t dev, int how)
++sc->owncount;
if (sc->owner == NULL) {
sc->owner = dev;
+ /*
+ * Mark the device busy while it owns the bus, to
+ * prevent detaching the device, bus, or hardware
+ * controller, until ownership is relinquished. If the
+ * device is doing IO from its probe method before
+ * attaching, it cannot be busied; mark the bus busy.
+ */
+ if (device_get_state(dev) < DS_ATTACHING)
+ sc->busydev = bus;
+ else
+ sc->busydev = dev;
+ device_busy(sc->busydev);
/*
* Drop the lock around the call to the bus driver, it
* should be allowed to sleep in the IIC_WAIT case.
@@ -146,6 +185,7 @@ iicbus_request_bus(device_t bus, device_t dev, int how)
sc->owner = NULL;
sc->owncount = 0;
wakeup_one(sc);
+ device_unbusy(sc->busydev);
}
}
}
@@ -179,6 +219,7 @@ iicbus_release_bus(device_t bus, device_t dev)
IICBUS_LOCK(sc);
sc->owner = NULL;
wakeup_one(sc);
+ device_unbusy(sc->busydev);
}
IICBUS_UNLOCK(sc);
return (0);
@@ -422,7 +463,7 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
{
int i, error, lenread, lenwrote, nkid, rpstart, addr;
device_t *children, bus;
- bool nostop, started;
+ bool started;
if ((error = device_get_children(dev, &children, &nkid)) != 0)
return (IIC_ERESOURCE);
@@ -433,7 +474,6 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
bus = children[0];
rpstart = 0;
free(children, M_TEMP);
- nostop = iicbus_get_nostop(dev);
started = false;
for (i = 0, error = 0; i < nmsgs && error == 0; i++) {
addr = msgs[i].slave;
@@ -461,12 +501,11 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
if (error != 0)
break;
- if ((msgs[i].flags & IIC_M_NOSTOP) != 0 ||
- (nostop && i + 1 < nmsgs)) {
- rpstart = 1; /* Next message gets repeated start */
- } else {
+ if (!(msgs[i].flags & IIC_M_NOSTOP)) {
rpstart = 0;
iicbus_stop(bus);
+ } else {
+ rpstart = 1; /* Next message gets repeated start */
}
}
if (error != 0 && started)
diff --git a/freebsd/sys/dev/iicbus/iiconf.h b/freebsd/sys/dev/iicbus/iiconf.h
index c264183e..5fbfcea5 100644
--- a/freebsd/sys/dev/iicbus/iiconf.h
+++ b/freebsd/sys/dev/iicbus/iiconf.h
@@ -96,12 +96,14 @@
#define IIC_ENOTSUPP 0x8 /* request not supported */
#define IIC_ENOADDR 0x9 /* no address assigned to the interface */
#define IIC_ERESOURCE 0xa /* resources (memory, whatever) unavailable */
+#define IIC_ERRNO INT_MIN /* marker bit: errno is in low-order bits */
/*
* Note that all iicbus functions return IIC_Exxxxx status values,
* except iic2errno() (obviously) and iicbus_started() (returns bool).
*/
extern int iic2errno(int);
+extern int errno2iic(int);
extern int iicbus_request_bus(device_t, device_t, int);
extern int iicbus_release_bus(device_t, device_t);
extern device_t iicbus_alloc_bus(device_t);
diff --git a/freebsd/sys/dev/led/led.c b/freebsd/sys/dev/led/led.c
index 70de95bb..43ae2f66 100644
--- a/freebsd/sys/dev/led/led.c
+++ b/freebsd/sys/dev/led/led.c
@@ -17,16 +17,19 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/conf.h>
+#include <sys/ctype.h>
#include <sys/kernel.h>
-#include <sys/systm.h>
#include <sys/limits.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/ctype.h>
-#include <sys/sbuf.h>
+#include <sys/mutex.h>
#include <sys/queue.h>
-#include <dev/led/led.h>
-#include <sys/uio.h>
+#include <sys/sbuf.h>
#include <sys/sx.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <dev/led/led.h>
struct ledsc {
LIST_ENTRY(ledsc) list;
@@ -263,7 +266,7 @@ led_set(char const *name, char const *cmd)
mtx_unlock(&led_mtx);
if (sb != NULL)
sbuf_delete(sb);
- return (0);
+ return (error);
}
static struct cdevsw led_cdevsw = {
diff --git a/freebsd/sys/dev/mii/micphy.c b/freebsd/sys/dev/mii/micphy.c
index 01e75357..f9493332 100644
--- a/freebsd/sys/dev/mii/micphy.c
+++ b/freebsd/sys/dev/mii/micphy.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
- * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2014,2019 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -34,7 +34,7 @@
__FBSDID("$FreeBSD$");
/*
- * Micrel KSZ9021 Gigabit Ethernet Transceiver
+ * Micrel KSZ8081/KSZ9021/KSZ9031 Gigabit Ethernet Transceiver
*/
#include <sys/param.h>
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/mii/mii_fdt.h>
#define MII_KSZPHY_EXTREG 0x0b
#define KSZPHY_EXTREG_WRITE (1 << 15)
@@ -253,6 +254,7 @@ micphy_probe(device_t dev)
static int
micphy_attach(device_t dev)
{
+ mii_fdt_phy_config_t *cfg;
struct mii_softc *sc;
phandle_t node;
device_t miibus;
@@ -273,10 +275,12 @@ micphy_attach(device_t dev)
if ((node = ofw_bus_get_node(parent)) == -1)
return (ENXIO);
+ cfg = mii_fdt_get_config(dev);
+
if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ9031)
- ksz9031_load_values(sc, node);
+ ksz9031_load_values(sc, cfg->phynode);
else
- ksz9021_load_values(sc, node);
+ ksz9021_load_values(sc, cfg->phynode);
return (0);
}
diff --git a/freebsd/sys/dev/mmc/bridge.h b/freebsd/sys/dev/mmc/bridge.h
index 7af811f1..d32abbac 100644
--- a/freebsd/sys/dev/mmc/bridge.h
+++ b/freebsd/sys/dev/mmc/bridge.h
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/freebsd/sys/dev/mmc/mmc.c b/freebsd/sys/dev/mmc/mmc.c
index 4c8aefcf..5bc3bbf7 100644
--- a/freebsd/sys/dev/mmc/mmc.c
+++ b/freebsd/sys/dev/mmc/mmc.c
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Bernd Walter. All rights reserved.
- * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh.
* Copyright (c) 2017 Marius Strobl <marius@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
diff --git a/freebsd/sys/dev/mmc/mmc_private.h b/freebsd/sys/dev/mmc/mmc_private.h
index 633d0784..a633d235 100644
--- a/freebsd/sys/dev/mmc/mmc_private.h
+++ b/freebsd/sys/dev/mmc/mmc_private.h
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2006 Bernd Walter. All rights reserved.
- * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/freebsd/sys/dev/mmc/mmc_subr.c b/freebsd/sys/dev/mmc/mmc_subr.c
index 76a14028..1e3bef16 100644
--- a/freebsd/sys/dev/mmc/mmc_subr.c
+++ b/freebsd/sys/dev/mmc/mmc_subr.c
@@ -2,7 +2,7 @@
/*-
* Copyright (c) 2006 Bernd Walter. All rights reserved.
- * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/freebsd/sys/dev/mmc/mmc_subr.h b/freebsd/sys/dev/mmc/mmc_subr.h
index 33ea6760..80c1ce2f 100644
--- a/freebsd/sys/dev/mmc/mmc_subr.h
+++ b/freebsd/sys/dev/mmc/mmc_subr.h
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2006 Bernd Walter. All rights reserved.
- * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/freebsd/sys/dev/mmc/mmcbrvar.h b/freebsd/sys/dev/mmc/mmcbrvar.h
index acddd3a3..f2f107c7 100644
--- a/freebsd/sys/dev/mmc/mmcbrvar.h
+++ b/freebsd/sys/dev/mmc/mmcbrvar.h
@@ -2,7 +2,7 @@
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Bernd Walter. All rights reserved.
- * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/freebsd/sys/dev/mmc/mmcreg.h b/freebsd/sys/dev/mmc/mmcreg.h
index 4b1f8a0e..f6031410 100644
--- a/freebsd/sys/dev/mmc/mmcreg.h
+++ b/freebsd/sys/dev/mmc/mmcreg.h
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh.
* Copyright (c) 2017 Marius Strobl <marius@FreeBSD.org>
* Copyright (c) 2015-2016 Ilya Bakulin <kibab@FreeBSD.org>
*
@@ -200,7 +200,10 @@ struct mmc_data {
#define MMC_DATA_READ (1UL << 1)
#define MMC_DATA_STREAM (1UL << 2)
#define MMC_DATA_MULTI (1UL << 3)
+#define MMC_DATA_BLOCK_SIZE (1UL << 4)
struct mmc_request *mrq;
+ size_t block_size; /* block size for CMD53 */
+ size_t block_count; /* block count for CMD53 */
};
struct mmc_request {
@@ -554,30 +557,39 @@ struct mmc_request {
#define SD_IO_RW_LEN(x) (((x) & 0xFF) << 0)
#define SD_IOE_RW_LEN(x) (((x) & 0x1FF) << 0)
+#define SD_IOE_RW_ADR(x) (((x) & 0x1FFFF) << 9)
+#define SD_IOE_RW_INCR (1u << 26)
#define SD_IOE_RW_BLK (1u << 27)
+#define SD_IOE_RW_FUNC(x) (((x) & 0x7) << 28)
+#define SD_IOE_RW_WR (1u << 31)
/* Card Common Control Registers (CCCR) */
-#define SD_IO_CCCR_START 0x00000
-#define SD_IO_CCCR_SIZE 0x100
-#define SD_IO_CCCR_FN_ENABLE 0x02
-#define SD_IO_CCCR_FN_READY 0x03
-#define SD_IO_CCCR_INT_ENABLE 0x04
-#define SD_IO_CCCR_INT_PENDING 0x05
-#define SD_IO_CCCR_CTL 0x06
-#define CCCR_CTL_RES (1 << 3)
-#define SD_IO_CCCR_BUS_WIDTH 0x07
+#define SD_IO_CCCR_START 0x00000 /* Offset in F0 address space */
+#define SD_IO_CCCR_SIZE 0x100 /* Total size of CCCR */
+#define SD_IO_CCCR_FN_ENABLE 0x02 /* Enabled functions */
+#define SD_IO_CCCR_FN_READY 0x03 /* Function ready status */
+#define SD_IO_CCCR_INT_ENABLE 0x04 /* Per-function interrupt enable */
+#define SD_IO_CCCR_INT_PENDING 0x05 /* Per-function interrupt pending */
+#define SD_IO_CCCR_CTL 0x06 /* I/O Abort register */
+#define CCCR_CTL_RES (1 << 3) /* Perform SDIO reset */
+#define SD_IO_CCCR_BUS_WIDTH 0x07 /* Bus Width register */
#define CCCR_BUS_WIDTH_4 (1 << 1)
#define CCCR_BUS_WIDTH_1 (1 << 0)
-#define SD_IO_CCCR_CARDCAP 0x08
-#define SD_IO_CCCR_CISPTR 0x09 /* XXX 9-10, 10-11, or 9-12 */
-
+#define SD_IO_CCCR_CARDCAP 0x08 /* SDIO card capabilities */
+#define CCCR_CC_SMB (1 << 1) /* CMD53 block mode support */
+#define SD_IO_CCCR_CISPTR 0x09 /* 0x09 - 0x0B */
+#define SD_IO_CCCR_FN0_BLKSZ 0x10 /* 0x10 - 0x11 */
/* Function Basic Registers (FBR) */
-#define SD_IO_FBR_START 0x00100
-#define SD_IO_FBR_SIZE 0x00700
+#define SD_IO_FBR_START 0x00100 /* Offset in F0 address space */
+#define SD_IO_FBR_SIZE 0x00700 /* Total size of FBR */
+#define SD_IO_FBR_F_SIZE 0x00100 /* Size of each function */
+#define SD_IO_FBR_START_F(n) (SD_IO_FBR_START + (n-1) * SD_IO_FBR_F_SIZE)
+#define SD_IO_FBR_CIS_OFFSET 0x9 /* Offset of this function's info block within CIS area */
+#define SD_IO_FBR_IOBLKSZ 0x10 /* Block size for CMD53 block mode operations */
/* Card Information Structure (CIS) */
-#define SD_IO_CIS_START 0x01000
-#define SD_IO_CIS_SIZE 0x17000
+#define SD_IO_CIS_START 0x01000 /* Offset in F0 address space */
+#define SD_IO_CIS_SIZE 0x17000 /* Total size of CIS */
/* CIS tuple codes (based on PC Card 16) */
#define SD_IO_CISTPL_VERS_1 0x15
diff --git a/freebsd/sys/dev/mmc/mmcsd.c b/freebsd/sys/dev/mmc/mmcsd.c
index e469c1d5..8fc06eb2 100644
--- a/freebsd/sys/dev/mmc/mmcsd.c
+++ b/freebsd/sys/dev/mmc/mmcsd.c
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Bernd Walter. All rights reserved.
- * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh.
* Copyright (c) 2017 Marius Strobl <marius@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -813,7 +813,7 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
speed / 1000000, (speed / 100000) % 10,
mmcsd_bus_bit_width(dev), sc->max_data);
} else if (type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
- printf("%s: %ju%sB partion %d%s at %s\n", part->name, bytes,
+ printf("%s: %ju%sB partition %d%s at %s\n", part->name, bytes,
unit, type, ro ? " (read-only)" : "",
device_get_nameunit(dev));
} else {
@@ -849,12 +849,12 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
}
}
if (ext == NULL)
- printf("%s%d: %ju%sB partion %d%s%s at %s\n",
+ printf("%s%d: %ju%sB partition %d%s%s at %s\n",
part->name, cnt, bytes, unit, type, enh ?
" enhanced" : "", ro ? " (read-only)" : "",
device_get_nameunit(dev));
else
- printf("%s%d: %ju%sB partion %d extended 0x%x "
+ printf("%s%d: %ju%sB partition %d extended 0x%x "
"(%s)%s at %s\n", part->name, cnt, bytes, unit,
type, extattr, ext, ro ? " (read-only)" : "",
device_get_nameunit(dev));
diff --git a/freebsd/sys/dev/mmc/mmcvar.h b/freebsd/sys/dev/mmc/mmcvar.h
index 1604c306..8d8c5547 100644
--- a/freebsd/sys/dev/mmc/mmcvar.h
+++ b/freebsd/sys/dev/mmc/mmcvar.h
@@ -2,7 +2,7 @@
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Bernd Walter. All rights reserved.
- * Copyright (c) 2006 M. Warner Losh. All rights reserved.
+ * Copyright (c) 2006 M. Warner Losh.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/freebsd/sys/dev/nvme/nvme.h b/freebsd/sys/dev/nvme/nvme.h
index 845ba75b..0d4a18b7 100644
--- a/freebsd/sys/dev/nvme/nvme.h
+++ b/freebsd/sys/dev/nvme/nvme.h
@@ -40,6 +40,7 @@
#define NVME_PASSTHROUGH_CMD _IOWR('n', 0, struct nvme_pt_command)
#define NVME_RESET_CONTROLLER _IO('n', 1)
+#define NVME_GET_NSID _IOR('n', 2, struct nvme_get_nsid)
#define NVME_IO_TEST _IOWR('n', 100, struct nvme_io_test)
#define NVME_BIO_TEST _IOWR('n', 101, struct nvme_io_test)
@@ -69,15 +70,39 @@
#define NVME_CAP_LO_REG_AMS_MASK (0x3)
#define NVME_CAP_LO_REG_TO_SHIFT (24)
#define NVME_CAP_LO_REG_TO_MASK (0xFF)
+#define NVME_CAP_LO_MQES(x) \
+ (((x) >> NVME_CAP_LO_REG_MQES_SHIFT) & NVME_CAP_LO_REG_MQES_MASK)
+#define NVME_CAP_LO_CQR(x) \
+ (((x) >> NVME_CAP_LO_REG_CQR_SHIFT) & NVME_CAP_LO_REG_CQR_MASK)
+#define NVME_CAP_LO_AMS(x) \
+ (((x) >> NVME_CAP_LO_REG_AMS_SHIFT) & NVME_CAP_LO_REG_AMS_MASK)
+#define NVME_CAP_LO_TO(x) \
+ (((x) >> NVME_CAP_LO_REG_TO_SHIFT) & NVME_CAP_LO_REG_TO_MASK)
#define NVME_CAP_HI_REG_DSTRD_SHIFT (0)
#define NVME_CAP_HI_REG_DSTRD_MASK (0xF)
+#define NVME_CAP_HI_REG_NSSRS_SHIFT (4)
+#define NVME_CAP_HI_REG_NSSRS_MASK (0x1)
#define NVME_CAP_HI_REG_CSS_NVM_SHIFT (5)
#define NVME_CAP_HI_REG_CSS_NVM_MASK (0x1)
+#define NVME_CAP_HI_REG_BPS_SHIFT (13)
+#define NVME_CAP_HI_REG_BPS_MASK (0x1)
#define NVME_CAP_HI_REG_MPSMIN_SHIFT (16)
#define NVME_CAP_HI_REG_MPSMIN_MASK (0xF)
#define NVME_CAP_HI_REG_MPSMAX_SHIFT (20)
#define NVME_CAP_HI_REG_MPSMAX_MASK (0xF)
+#define NVME_CAP_HI_REG_PMRS_SHIFT (24)
+#define NVME_CAP_HI_REG_PMRS_MASK (0x1)
+#define NVME_CAP_HI_REG_CMBS_SHIFT (25)
+#define NVME_CAP_HI_REG_CMBS_MASK (0x1)
+#define NVME_CAP_HI_DSTRD(x) \
+ (((x) >> NVME_CAP_HI_REG_DSTRD_SHIFT) & NVME_CAP_HI_REG_DSTRD_MASK)
+#define NVME_CAP_HI_CSS_NVM(x) \
+ (((x) >> NVME_CAP_HI_REG_CSS_NVM_SHIFT) & NVME_CAP_HI_REG_CSS_NVM_MASK)
+#define NVME_CAP_HI_MPSMIN(x) \
+ (((x) >> NVME_CAP_HI_REG_MPSMIN_SHIFT) & NVME_CAP_HI_REG_MPSMIN_MASK)
+#define NVME_CAP_HI_MPSMAX(x) \
+ (((x) >> NVME_CAP_HI_REG_MPSMAX_SHIFT) & NVME_CAP_HI_REG_MPSMAX_MASK)
#define NVME_CC_REG_EN_SHIFT (0)
#define NVME_CC_REG_EN_MASK (0x1)
@@ -100,6 +125,10 @@
#define NVME_CSTS_REG_CFS_MASK (0x1)
#define NVME_CSTS_REG_SHST_SHIFT (2)
#define NVME_CSTS_REG_SHST_MASK (0x3)
+#define NVME_CSTS_REG_NVSRO_SHIFT (4)
+#define NVME_CSTS_REG_NVSRO_MASK (0x1)
+#define NVME_CSTS_REG_PP_SHIFT (5)
+#define NVME_CSTS_REG_PP_MASK (0x1)
#define NVME_CSTS_GET_SHST(csts) (((csts) >> NVME_CSTS_REG_SHST_SHIFT) & NVME_CSTS_REG_SHST_MASK)
@@ -119,6 +148,8 @@
#define NVME_STATUS_SC_MASK (0xFF)
#define NVME_STATUS_SCT_SHIFT (9)
#define NVME_STATUS_SCT_MASK (0x7)
+#define NVME_STATUS_CRD_SHIFT (12)
+#define NVME_STATUS_CRD_MASK (0x3)
#define NVME_STATUS_M_SHIFT (14)
#define NVME_STATUS_M_MASK (0x1)
#define NVME_STATUS_DNR_SHIFT (15)
@@ -159,6 +190,9 @@
/* SR-IOV Virtual Function */
#define NVME_CTRLR_DATA_MIC_SRIOVVF_SHIFT (2)
#define NVME_CTRLR_DATA_MIC_SRIOVVF_MASK (0x1)
+/* Asymmetric Namespace Access Reporting */
+#define NVME_CTRLR_DATA_MIC_ANAR_SHIFT (3)
+#define NVME_CTRLR_DATA_MIC_ANAR_MASK (0x1)
/** OACS - optional admin command support */
/* supports security send/receive commands */
@@ -188,6 +222,9 @@
/* supports Doorbell Buffer Config */
#define NVME_CTRLR_DATA_OACS_DBBUFFER_SHIFT (8)
#define NVME_CTRLR_DATA_OACS_DBBUFFER_MASK (0x1)
+/* supports Get LBA Status */
+#define NVME_CTRLR_DATA_OACS_GETLBA_SHIFT (9)
+#define NVME_CTRLR_DATA_OACS_GETLBA_MASK (0x1)
/** firmware updates */
/* first slot is read-only */
@@ -196,6 +233,9 @@
/* number of firmware slots */
#define NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT (1)
#define NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK (0x7)
+/* firmware activation without reset */
+#define NVME_CTRLR_DATA_FRMW_ACT_WO_RESET_SHIFT (4)
+#define NVME_CTRLR_DATA_FRMW_ACT_WO_RESET_MASK (0x1)
/** log page attributes */
/* per namespace smart/health log page */
@@ -212,6 +252,26 @@
#define NVME_CTRLR_DATA_APSTA_APST_SUPP_SHIFT (0)
#define NVME_CTRLR_DATA_APSTA_APST_SUPP_MASK (0x1)
+/** Sanitize Capabilities */
+/* Crypto Erase Support */
+#define NVME_CTRLR_DATA_SANICAP_CES_SHIFT (0)
+#define NVME_CTRLR_DATA_SANICAP_CES_MASK (0x1)
+/* Block Erase Support */
+#define NVME_CTRLR_DATA_SANICAP_BES_SHIFT (1)
+#define NVME_CTRLR_DATA_SANICAP_BES_MASK (0x1)
+/* Overwrite Support */
+#define NVME_CTRLR_DATA_SANICAP_OWS_SHIFT (2)
+#define NVME_CTRLR_DATA_SANICAP_OWS_MASK (0x1)
+/* No-Deallocate Inhibited */
+#define NVME_CTRLR_DATA_SANICAP_NDI_SHIFT (29)
+#define NVME_CTRLR_DATA_SANICAP_NDI_MASK (0x1)
+/* No-Deallocate Modifies Media After Sanitize */
+#define NVME_CTRLR_DATA_SANICAP_NODMMAS_SHIFT (30)
+#define NVME_CTRLR_DATA_SANICAP_NODMMAS_MASK (0x3)
+#define NVME_CTRLR_DATA_SANICAP_NODMMAS_UNDEF (0)
+#define NVME_CTRLR_DATA_SANICAP_NODMMAS_NO (1)
+#define NVME_CTRLR_DATA_SANICAP_NODMMAS_YES (2)
+
/** submission queue entry size */
#define NVME_CTRLR_DATA_SQES_MIN_SHIFT (0)
#define NVME_CTRLR_DATA_SQES_MIN_MASK (0xF)
@@ -239,6 +299,8 @@
#define NVME_CTRLR_DATA_ONCS_RESERV_MASK (0x1)
#define NVME_CTRLR_DATA_ONCS_TIMESTAMP_SHIFT (6)
#define NVME_CTRLR_DATA_ONCS_TIMESTAMP_MASK (0x1)
+#define NVME_CTRLR_DATA_ONCS_VERIFY_SHIFT (7)
+#define NVME_CTRLR_DATA_ONCS_VERIFY_MASK (0x1)
/** Fused Operation Support */
#define NVME_CTRLR_DATA_FUSES_CNW_SHIFT (0)
@@ -253,8 +315,15 @@
#define NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_MASK (0x1)
/** volatile write cache */
+/* volatile write cache present */
#define NVME_CTRLR_DATA_VWC_PRESENT_SHIFT (0)
#define NVME_CTRLR_DATA_VWC_PRESENT_MASK (0x1)
+/* flush all namespaces supported */
+#define NVME_CTRLR_DATA_VWC_ALL_SHIFT (1)
+#define NVME_CTRLR_DATA_VWC_ALL_MASK (0x3)
+#define NVME_CTRLR_DATA_VWC_ALL_UNKNOWN (0)
+#define NVME_CTRLR_DATA_VWC_ALL_NO (2)
+#define NVME_CTRLR_DATA_VWC_ALL_YES (3)
/** namespace features */
/* thin provisioning */
@@ -269,6 +338,9 @@
/* NGUID and EUI64 fields are not reusable */
#define NVME_NS_DATA_NSFEAT_NO_ID_REUSE_SHIFT (3)
#define NVME_NS_DATA_NSFEAT_NO_ID_REUSE_MASK (0x1)
+/* NPWG, NPWA, NPDG, NPDA, and NOWS are valid */
+#define NVME_NS_DATA_NSFEAT_NPVALID_SHIFT (4)
+#define NVME_NS_DATA_NSFEAT_NPVALID_MASK (0x1)
/** formatted lba size */
#define NVME_NS_DATA_FLBAS_FORMAT_SHIFT (0)
@@ -349,6 +421,20 @@
#define NVME_NS_DATA_FPI_SUPP_SHIFT (7)
#define NVME_NS_DATA_FPI_SUPP_MASK (0x1)
+/** Deallocate Logical Block Features */
+/* deallocated logical block read behavior */
+#define NVME_NS_DATA_DLFEAT_READ_SHIFT (0)
+#define NVME_NS_DATA_DLFEAT_READ_MASK (0x07)
+#define NVME_NS_DATA_DLFEAT_READ_NR (0x00)
+#define NVME_NS_DATA_DLFEAT_READ_00 (0x01)
+#define NVME_NS_DATA_DLFEAT_READ_FF (0x02)
+/* supports the Deallocate bit in the Write Zeroes */
+#define NVME_NS_DATA_DLFEAT_DWZ_SHIFT (3)
+#define NVME_NS_DATA_DLFEAT_DWZ_MASK (0x01)
+/* Guard field for deallocated logical blocks is set to the CRC */
+#define NVME_NS_DATA_DLFEAT_GCRC_SHIFT (4)
+#define NVME_NS_DATA_DLFEAT_GCRC_MASK (0x01)
+
/** lba format support */
/* metadata size */
#define NVME_NS_DATA_LBAF_MS_SHIFT (0)
@@ -373,6 +459,35 @@ enum nvme_critical_warning_state {
#define NVME_FIRMWARE_PAGE_AFI_SLOT_SHIFT (0)
#define NVME_FIRMWARE_PAGE_AFI_SLOT_MASK (0x7)
+/* Commands Supported and Effects */
+#define NVME_CE_PAGE_CSUP_SHIFT (0)
+#define NVME_CE_PAGE_CSUP_MASK (0x1)
+#define NVME_CE_PAGE_LBCC_SHIFT (1)
+#define NVME_CE_PAGE_LBCC_MASK (0x1)
+#define NVME_CE_PAGE_NCC_SHIFT (2)
+#define NVME_CE_PAGE_NCC_MASK (0x1)
+#define NVME_CE_PAGE_NIC_SHIFT (3)
+#define NVME_CE_PAGE_NIC_MASK (0x1)
+#define NVME_CE_PAGE_CCC_SHIFT (4)
+#define NVME_CE_PAGE_CCC_MASK (0x1)
+#define NVME_CE_PAGE_CSE_SHIFT (16)
+#define NVME_CE_PAGE_CSE_MASK (0x7)
+#define NVME_CE_PAGE_UUID_SHIFT (19)
+#define NVME_CE_PAGE_UUID_MASK (0x1)
+
+/* Sanitize Status */
+#define NVME_SS_PAGE_SSTAT_STATUS_SHIFT (0)
+#define NVME_SS_PAGE_SSTAT_STATUS_MASK (0x7)
+#define NVME_SS_PAGE_SSTAT_STATUS_NEVER (0)
+#define NVME_SS_PAGE_SSTAT_STATUS_COMPLETED (1)
+#define NVME_SS_PAGE_SSTAT_STATUS_INPROG (2)
+#define NVME_SS_PAGE_SSTAT_STATUS_FAILED (3)
+#define NVME_SS_PAGE_SSTAT_STATUS_COMPLETEDWD (4)
+#define NVME_SS_PAGE_SSTAT_PASSES_SHIFT (3)
+#define NVME_SS_PAGE_SSTAT_PASSES_MASK (0x1f)
+#define NVME_SS_PAGE_SSTAT_GDE_SHIFT (8)
+#define NVME_SS_PAGE_SSTAT_GDE_MASK (0x1)
+
/* CC register SHN field values */
enum shn_value {
NVME_SHN_NORMAL = 0x1,
@@ -388,34 +503,37 @@ enum shst_value {
struct nvme_registers
{
- /** controller capabilities */
- uint32_t cap_lo;
- uint32_t cap_hi;
-
- uint32_t vs; /* version */
- uint32_t intms; /* interrupt mask set */
- uint32_t intmc; /* interrupt mask clear */
-
- /** controller configuration */
- uint32_t cc;
-
- uint32_t reserved1;
-
- /** controller status */
- uint32_t csts;
-
- uint32_t reserved2;
-
- /** admin queue attributes */
- uint32_t aqa;
-
- uint64_t asq; /* admin submission queue base addr */
- uint64_t acq; /* admin completion queue base addr */
- uint32_t reserved3[0x3f2];
-
+ uint32_t cap_lo; /* controller capabilities */
+ uint32_t cap_hi;
+ uint32_t vs; /* version */
+ uint32_t intms; /* interrupt mask set */
+ uint32_t intmc; /* interrupt mask clear */
+ uint32_t cc; /* controller configuration */
+ uint32_t reserved1;
+ uint32_t csts; /* controller status */
+ uint32_t nssr; /* NVM Subsystem Reset */
+ uint32_t aqa; /* admin queue attributes */
+ uint64_t asq; /* admin submission queue base addr */
+ uint64_t acq; /* admin completion queue base addr */
+ uint32_t cmbloc; /* Controller Memory Buffer Location */
+ uint32_t cmbsz; /* Controller Memory Buffer Size */
+ uint32_t bpinfo; /* Boot Partition Information */
+ uint32_t bprsel; /* Boot Partition Read Select */
+ uint64_t bpmbl; /* Boot Partition Memory Buffer Location */
+ uint64_t cmbmsc; /* Controller Memory Buffer Memory Space Control */
+ uint32_t cmbsts; /* Controller Memory Buffer Status */
+ uint8_t reserved3[3492]; /* 5Ch - DFFh */
+ uint32_t pmrcap; /* Persistent Memory Capabilities */
+ uint32_t pmrctl; /* Persistent Memory Region Control */
+ uint32_t pmrsts; /* Persistent Memory Region Status */
+ uint32_t pmrebs; /* Persistent Memory Region Elasticity Buffer Size */
+ uint32_t pmrswtp; /* Persistent Memory Region Sustained Write Throughput */
+ uint32_t pmrmsc_lo; /* Persistent Memory Region Controller Memory Space Control */
+ uint32_t pmrmsc_hi;
+ uint8_t reserved4[484]; /* E1Ch - FFFh */
struct {
- uint32_t sq_tdbl; /* submission queue tail doorbell */
- uint32_t cq_hdbl; /* completion queue head doorbell */
+ uint32_t sq_tdbl; /* submission queue tail doorbell */
+ uint32_t cq_hdbl; /* completion queue head doorbell */
} doorbell[1] __packed;
} __packed;
@@ -490,6 +608,7 @@ enum nvme_status_code_type {
NVME_SCT_GENERIC = 0x0,
NVME_SCT_COMMAND_SPECIFIC = 0x1,
NVME_SCT_MEDIA_ERROR = 0x2,
+ NVME_SCT_PATH_RELATED = 0x3,
/* 0x3-0x6 - reserved */
NVME_SCT_VENDOR_SPECIFIC = 0x7,
};
@@ -528,6 +647,9 @@ enum nvme_generic_command_status_code {
NVME_SC_SANITIZE_IN_PROGRESS = 0x1d,
NVME_SC_SGL_DATA_BLOCK_GRAN_INVALID = 0x1e,
NVME_SC_NOT_SUPPORTED_IN_CMB = 0x1f,
+ NVME_SC_NAMESPACE_IS_WRITE_PROTECTED = 0x20,
+ NVME_SC_COMMAND_INTERRUPTED = 0x21,
+ NVME_SC_TRANSIENT_TRANSPORT_ERROR = 0x22,
NVME_SC_LBA_OUT_OF_RANGE = 0x80,
NVME_SC_CAPACITY_EXCEEDED = 0x81,
@@ -573,6 +695,9 @@ enum nvme_command_specific_status_code {
NVME_SC_INVALID_SEC_CTRLR_STATE = 0x20,
NVME_SC_INVALID_NUM_OF_CTRLR_RESRC = 0x21,
NVME_SC_INVALID_RESOURCE_ID = 0x22,
+ NVME_SC_SANITIZE_PROHIBITED_WPMRE = 0x23,
+ NVME_SC_ANA_GROUP_ID_INVALID = 0x24,
+ NVME_SC_ANA_ATTACH_FAILED = 0x25,
NVME_SC_CONFLICTING_ATTRIBUTES = 0x80,
NVME_SC_INVALID_PROTECTION_INFO = 0x81,
@@ -591,6 +716,17 @@ enum nvme_media_error_status_code {
NVME_SC_DEALLOCATED_OR_UNWRITTEN = 0x87,
};
+/* path related status codes */
+enum nvme_path_related_status_code {
+ NVME_SC_INTERNAL_PATH_ERROR = 0x00,
+ NVME_SC_ASYMMETRIC_ACCESS_PERSISTENT_LOSS = 0x01,
+ NVME_SC_ASYMMETRIC_ACCESS_INACCESSIBLE = 0x02,
+ NVME_SC_ASYMMETRIC_ACCESS_TRANSITION = 0x03,
+ NVME_SC_CONTROLLER_PATHING_ERROR = 0x60,
+ NVME_SC_HOST_PATHING_ERROR = 0x70,
+ NVME_SC_COMMAND_ABOTHED_BY_HOST = 0x71,
+};
+
/* admin opcodes */
enum nvme_admin_opcode {
NVME_OPC_DELETE_IO_SQ = 0x00,
@@ -610,20 +746,27 @@ enum nvme_admin_opcode {
/* 0x0e-0x0f - reserved */
NVME_OPC_FIRMWARE_ACTIVATE = 0x10,
NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD = 0x11,
+ /* 0x12-0x13 - reserved */
NVME_OPC_DEVICE_SELF_TEST = 0x14,
NVME_OPC_NAMESPACE_ATTACHMENT = 0x15,
+ /* 0x16-0x17 - reserved */
NVME_OPC_KEEP_ALIVE = 0x18,
NVME_OPC_DIRECTIVE_SEND = 0x19,
NVME_OPC_DIRECTIVE_RECEIVE = 0x1a,
+ /* 0x1b - reserved */
NVME_OPC_VIRTUALIZATION_MANAGEMENT = 0x1c,
NVME_OPC_NVME_MI_SEND = 0x1d,
NVME_OPC_NVME_MI_RECEIVE = 0x1e,
+ /* 0x1f-0x7b - reserved */
NVME_OPC_DOORBELL_BUFFER_CONFIG = 0x7c,
NVME_OPC_FORMAT_NVM = 0x80,
NVME_OPC_SECURITY_SEND = 0x81,
NVME_OPC_SECURITY_RECEIVE = 0x82,
+ /* 0x83 - reserved */
NVME_OPC_SANITIZE = 0x84,
+ /* 0x85 - reserved */
+ NVME_OPC_GET_LBA_STATUS = 0x86,
};
/* nvme nvm opcodes */
@@ -634,11 +777,11 @@ enum nvme_nvm_opcode {
/* 0x03 - reserved */
NVME_OPC_WRITE_UNCORRECTABLE = 0x04,
NVME_OPC_COMPARE = 0x05,
- /* 0x06 - reserved */
+ /* 0x06-0x07 - reserved */
NVME_OPC_WRITE_ZEROES = 0x08,
- /* 0x07 - reserved */
NVME_OPC_DATASET_MANAGEMENT = 0x09,
- /* 0x0a-0x0c - reserved */
+ /* 0x0a-0x0b - reserved */
+ NVME_OPC_VERIFY = 0x0c,
NVME_OPC_RESERVATION_REGISTER = 0x0d,
NVME_OPC_RESERVATION_REPORT = 0x0e,
/* 0x0f-0x10 - reserved */
@@ -666,10 +809,21 @@ enum nvme_feature {
NVME_FEAT_KEEP_ALIVE_TIMER = 0x0F,
NVME_FEAT_HOST_CONTROLLED_THERMAL_MGMT = 0x10,
NVME_FEAT_NON_OP_POWER_STATE_CONFIG = 0x11,
- /* 0x12-0x77 - reserved */
+ NVME_FEAT_READ_RECOVERY_LEVEL_CONFIG = 0x12,
+ NVME_FEAT_PREDICTABLE_LATENCY_MODE_CONFIG = 0x13,
+ NVME_FEAT_PREDICTABLE_LATENCY_MODE_WINDOW = 0x14,
+ NVME_FEAT_LBA_STATUS_INFORMATION_ATTRIBUTES = 0x15,
+ NVME_FEAT_HOST_BEHAVIOR_SUPPORT = 0x16,
+ NVME_FEAT_SANITIZE_CONFIG = 0x17,
+ NVME_FEAT_ENDURANCE_GROUP_EVENT_CONFIGURATION = 0x18,
+ /* 0x19-0x77 - reserved */
/* 0x78-0x7f - NVMe Management Interface */
NVME_FEAT_SOFTWARE_PROGRESS_MARKER = 0x80,
- /* 0x81-0xBF - command set specific (reserved) */
+ NVME_FEAT_HOST_IDENTIFIER = 0x81,
+ NVME_FEAT_RESERVATION_NOTIFICATION_MASK = 0x82,
+ NVME_FEAT_RESERVATION_PERSISTENCE = 0x83,
+ NVME_FEAT_NAMESPACE_WRITE_PROTECTION_CONFIG = 0x84,
+ /* 0x85-0xBF - command set specific (reserved) */
/* 0xC0-0xFF - vendor specific */
};
@@ -763,12 +917,27 @@ struct nvme_controller_data {
/** Controller Attributes */
uint32_t ctratt; /* bitfield really */
- uint8_t reserved1[12];
+ /** Read Recovery Levels Supported */
+ uint16_t rrls;
+
+ uint8_t reserved1[9];
+
+ /** Controller Type */
+ uint8_t cntrltype;
/** FRU Globally Unique Identifier */
uint8_t fguid[16];
- uint8_t reserved2[128];
+ /** Command Retry Delay Time 1 */
+ uint16_t crdt1;
+
+ /** Command Retry Delay Time 2 */
+ uint16_t crdt2;
+
+ /** Command Retry Delay Time 3 */
+ uint16_t crdt3;
+
+ uint8_t reserved2[122];
/* bytes 256-511: admin command set attributes */
@@ -848,7 +1017,34 @@ struct nvme_controller_data {
/** Sanitize Capabilities */
uint32_t sanicap; /* Really a bitfield */
- uint8_t reserved3[180];
+ /** Host Memory Buffer Minimum Descriptor Entry Size */
+ uint32_t hmminds;
+
+ /** Host Memory Maximum Descriptors Entries */
+ uint16_t hmmaxd;
+
+ /** NVM Set Identifier Maximum */
+ uint16_t nsetidmax;
+
+ /** Endurance Group Identifier Maximum */
+ uint16_t endgidmax;
+
+ /** ANA Transition Time */
+ uint8_t anatt;
+
+ /** Asymmetric Namespace Access Capabilities */
+ uint8_t anacap;
+
+ /** ANA Group Identifier Maximum */
+ uint32_t anagrpmax;
+
+ /** Number of ANA Group Identifiers */
+ uint32_t nanagrpid;
+
+ /** Persistent Event Log Size */
+ uint32_t pels;
+
+ uint8_t reserved3[156];
/* bytes 512-703: nvm command set attributes */
/** submission queue entry size */
@@ -883,7 +1079,9 @@ struct nvme_controller_data {
/** NVM Vendor Specific Command Configuration */
uint8_t nvscc;
- uint8_t reserved5;
+
+ /** Namespace Write Protection Capabilities */
+ uint8_t nwpc;
/** Atomic Compare & Write Unit */
uint16_t acwu;
@@ -892,8 +1090,11 @@ struct nvme_controller_data {
/** SGL Support */
uint32_t sgls;
+ /** Maximum Number of Allowed Namespaces */
+ uint32_t mnan;
+
/* bytes 540-767: Reserved */
- uint8_t reserved7[228];
+ uint8_t reserved7[224];
/** NVM Subsystem NVMe Qualified Name */
uint8_t subnqn[256];
@@ -978,8 +1179,38 @@ struct nvme_namespace_data {
/** NVM Capacity */
uint8_t nvmcap[16];
- /* bytes 64-103: Reserved */
- uint8_t reserved5[40];
+ /** Namespace Preferred Write Granularity */
+ uint16_t npwg;
+
+ /** Namespace Preferred Write Alignment */
+ uint16_t npwa;
+
+ /** Namespace Preferred Deallocate Granularity */
+ uint16_t npdg;
+
+ /** Namespace Preferred Deallocate Alignment */
+ uint16_t npda;
+
+ /** Namespace Optimal Write Size */
+ uint16_t nows;
+
+ /* bytes 74-91: Reserved */
+ uint8_t reserved5[18];
+
+ /** ANA Group Identifier */
+ uint32_t anagrpid;
+
+ /* bytes 96-98: Reserved */
+ uint8_t reserved6[3];
+
+ /** Namespace Attributes */
+ uint8_t nsattr;
+
+ /** NVM Set Identifier */
+ uint16_t nvmsetid;
+
+ /** Endurance Group Identifier */
+ uint16_t endgid;
/** Namespace Globally Unique Identifier */
uint8_t nguid[16];
@@ -990,7 +1221,7 @@ struct nvme_namespace_data {
/** lba format support */
uint32_t lbaf[16];
- uint8_t reserved6[192];
+ uint8_t reserved7[192];
uint8_t vendor_specific[3712];
} __packed __aligned(4);
@@ -1005,9 +1236,21 @@ enum nvme_log_page {
NVME_LOG_FIRMWARE_SLOT = 0x03,
NVME_LOG_CHANGED_NAMESPACE = 0x04,
NVME_LOG_COMMAND_EFFECT = 0x05,
+ NVME_LOG_DEVICE_SELF_TEST = 0x06,
+ NVME_LOG_TELEMETRY_HOST_INITIATED = 0x07,
+ NVME_LOG_TELEMETRY_CONTROLLER_INITIATED = 0x08,
+ NVME_LOG_ENDURANCE_GROUP_INFORMATION = 0x09,
+ NVME_LOG_PREDICTABLE_LATENCY_PER_NVM_SET = 0x0a,
+ NVME_LOG_PREDICTABLE_LATENCY_EVENT_AGGREGATE = 0x0b,
+ NVME_LOG_ASYMMETRIC_NAMESPAVE_ACCESS = 0x0c,
+ NVME_LOG_PERSISTENT_EVENT_LOG = 0x0d,
+ NVME_LOG_LBA_STATUS_INFORMATION = 0x0e,
+ NVME_LOG_ENDURANCE_GROUP_EVENT_AGGREGATE = 0x0f,
/* 0x06-0x7F - reserved */
/* 0x80-0xBF - I/O command set specific */
NVME_LOG_RES_NOTIFICATION = 0x80,
+ NVME_LOG_SANITIZE_STATUS = 0x81,
+ /* 0x82-0xBF - reserved */
/* 0xC0-0xFF - vendor specific */
/*
@@ -1036,7 +1279,11 @@ struct nvme_error_information_entry {
uint64_t lba;
uint32_t nsid;
uint8_t vendor_specific;
- uint8_t reserved[35];
+ uint8_t trtype;
+ uint16_t reserved30;
+ uint64_t csi;
+ uint16_t ttsi;
+ uint8_t reserved[22];
} __packed __aligned(4);
_Static_assert(sizeof(struct nvme_error_information_entry) == 64, "bad size for nvme_error_information_entry");
@@ -1072,8 +1319,16 @@ struct nvme_health_information_page {
uint32_t warning_temp_time;
uint32_t error_temp_time;
uint16_t temp_sensor[8];
-
- uint8_t reserved2[296];
+ /* Thermal Management Temperature 1 Transition Count */
+ uint32_t tmt1tc;
+ /* Thermal Management Temperature 2 Transition Count */
+ uint32_t tmt2tc;
+ /* Total Time For Thermal Management Temperature 1 */
+ uint32_t ttftmt1;
+ /* Total Time For Thermal Management Temperature 2 */
+ uint32_t ttftmt2;
+
+ uint8_t reserved2[280];
} __packed __aligned(4);
_Static_assert(sizeof(struct nvme_health_information_page) == 512, "bad size for nvme_health_information_page");
@@ -1094,6 +1349,43 @@ struct nvme_ns_list {
_Static_assert(sizeof(struct nvme_ns_list) == 4096, "bad size for nvme_ns_list");
+struct nvme_command_effects_page {
+ uint32_t acs[256];
+ uint32_t iocs[256];
+ uint8_t reserved[2048];
+} __packed __aligned(4);
+
+_Static_assert(sizeof(struct nvme_command_effects_page) == 4096,
+ "bad size for nvme_command_effects_page");
+
+struct nvme_res_notification_page {
+ uint64_t log_page_count;
+ uint8_t log_page_type;
+ uint8_t available_log_pages;
+ uint8_t reserved2;
+ uint32_t nsid;
+ uint8_t reserved[48];
+} __packed __aligned(4);
+
+_Static_assert(sizeof(struct nvme_res_notification_page) == 64,
+ "bad size for nvme_res_notification_page");
+
+struct nvme_sanitize_status_page {
+ uint16_t sprog;
+ uint16_t sstat;
+ uint32_t scdw10;
+ uint32_t etfo;
+ uint32_t etfbe;
+ uint32_t etfce;
+ uint32_t etfownd;
+ uint32_t etfbewnd;
+ uint32_t etfcewnd;
+ uint8_t reserved[480];
+} __packed __aligned(4);
+
+_Static_assert(sizeof(struct nvme_sanitize_status_page) == 512,
+ "bad size for nvme_sanitize_status_page");
+
struct intel_log_temp_stats
{
uint64_t current;
@@ -1109,6 +1401,56 @@ struct intel_log_temp_stats
_Static_assert(sizeof(struct intel_log_temp_stats) == 13 * 8, "bad size for intel_log_temp_stats");
+struct nvme_resv_reg_ctrlr
+{
+ uint16_t ctrlr_id; /* Controller ID */
+ uint8_t rcsts; /* Reservation Status */
+ uint8_t reserved3[5];
+ uint64_t hostid; /* Host Identifier */
+ uint64_t rkey; /* Reservation Key */
+} __packed __aligned(4);
+
+_Static_assert(sizeof(struct nvme_resv_reg_ctrlr) == 24, "bad size for nvme_resv_reg_ctrlr");
+
+struct nvme_resv_reg_ctrlr_ext
+{
+ uint16_t ctrlr_id; /* Controller ID */
+ uint8_t rcsts; /* Reservation Status */
+ uint8_t reserved3[5];
+ uint64_t rkey; /* Reservation Key */
+ uint64_t hostid[2]; /* Host Identifier */
+ uint8_t reserved32[32];
+} __packed __aligned(4);
+
+_Static_assert(sizeof(struct nvme_resv_reg_ctrlr_ext) == 64, "bad size for nvme_resv_reg_ctrlr_ext");
+
+struct nvme_resv_status
+{
+ uint32_t gen; /* Generation */
+ uint8_t rtype; /* Reservation Type */
+ uint8_t regctl[2]; /* Number of Registered Controllers */
+ uint8_t reserved7[2];
+ uint8_t ptpls; /* Persist Through Power Loss State */
+ uint8_t reserved10[14];
+ struct nvme_resv_reg_ctrlr ctrlr[0];
+} __packed __aligned(4);
+
+_Static_assert(sizeof(struct nvme_resv_status) == 24, "bad size for nvme_resv_status");
+
+struct nvme_resv_status_ext
+{
+ uint32_t gen; /* Generation */
+ uint8_t rtype; /* Reservation Type */
+ uint8_t regctl[2]; /* Number of Registered Controllers */
+ uint8_t reserved7[2];
+ uint8_t ptpls; /* Persist Through Power Loss State */
+ uint8_t reserved10[14];
+ uint8_t reserved24[40];
+ struct nvme_resv_reg_ctrlr_ext ctrlr[0];
+} __packed __aligned(4);
+
+_Static_assert(sizeof(struct nvme_resv_status_ext) == 64, "bad size for nvme_resv_status_ext");
+
#define NVME_TEST_MAX_THREADS 128
struct nvme_io_test {
@@ -1184,6 +1526,11 @@ struct nvme_pt_command {
struct mtx * driver_lock;
};
+struct nvme_get_nsid {
+ char cdev[SPECNAMELEN + 1];
+ uint32_t nsid;
+};
+
#define nvme_completion_is_error(cpl) \
(NVME_STATUS_GET_SC((cpl)->status) != 0 || NVME_STATUS_GET_SCT((cpl)->status) != 0)
@@ -1192,6 +1539,7 @@ void nvme_strvis(uint8_t *dst, const uint8_t *src, int dstlen, int srclen);
#ifdef _KERNEL
struct bio;
+struct thread;
struct nvme_namespace;
struct nvme_controller;
@@ -1281,6 +1629,8 @@ uint32_t nvme_ns_get_stripesize(struct nvme_namespace *ns);
int nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp,
nvme_cb_fn_t cb_fn);
+int nvme_ns_ioctl_process(struct nvme_namespace *ns, u_long cmd,
+ caddr_t arg, int flag, struct thread *td);
/*
* Command building helper functions -- shared with CAM
@@ -1372,6 +1722,10 @@ void nvme_controller_data_swapbytes(struct nvme_controller_data *s)
s->rtd3e = le32toh(s->rtd3e);
s->oaes = le32toh(s->oaes);
s->ctratt = le32toh(s->ctratt);
+ s->rrls = le16toh(s->rrls);
+ s->crdt1 = le16toh(s->crdt1);
+ s->crdt2 = le16toh(s->crdt2);
+ s->crdt3 = le16toh(s->crdt3);
s->oacs = le16toh(s->oacs);
s->wctemp = le16toh(s->wctemp);
s->cctemp = le16toh(s->cctemp);
@@ -1385,6 +1739,13 @@ void nvme_controller_data_swapbytes(struct nvme_controller_data *s)
s->mntmt = le16toh(s->mntmt);
s->mxtmt = le16toh(s->mxtmt);
s->sanicap = le32toh(s->sanicap);
+ s->hmminds = le32toh(s->hmminds);
+ s->hmmaxd = le16toh(s->hmmaxd);
+ s->nsetidmax = le16toh(s->nsetidmax);
+ s->endgidmax = le16toh(s->endgidmax);
+ s->anagrpmax = le32toh(s->anagrpmax);
+ s->nanagrpid = le32toh(s->nanagrpid);
+ s->pels = le32toh(s->pels);
s->maxcmd = le16toh(s->maxcmd);
s->nn = le32toh(s->nn);
s->oncs = le16toh(s->oncs);
@@ -1393,6 +1754,7 @@ void nvme_controller_data_swapbytes(struct nvme_controller_data *s)
s->awupf = le16toh(s->awupf);
s->acwu = le16toh(s->acwu);
s->sgls = le32toh(s->sgls);
+ s->mnan = le32toh(s->mnan);
for (i = 0; i < 32; i++)
nvme_power_state_swapbytes(&s->power_state[i]);
}
@@ -1412,6 +1774,14 @@ void nvme_namespace_data_swapbytes(struct nvme_namespace_data *s)
s->nabo = le16toh(s->nabo);
s->nabspf = le16toh(s->nabspf);
s->noiob = le16toh(s->noiob);
+ s->npwg = le16toh(s->npwg);
+ s->npwa = le16toh(s->npwa);
+ s->npdg = le16toh(s->npdg);
+ s->npda = le16toh(s->npda);
+ s->nows = le16toh(s->nows);
+ s->anagrpid = le32toh(s->anagrpid);
+ s->nvmsetid = le16toh(s->nvmsetid);
+ s->endgid = le16toh(s->endgid);
for (i = 0; i < 16; i++)
s->lbaf[i] = le32toh(s->lbaf[i]);
}
@@ -1427,6 +1797,8 @@ void nvme_error_information_entry_swapbytes(struct nvme_error_information_entry
s->error_location = le16toh(s->error_location);
s->lba = le64toh(s->lba);
s->nsid = le32toh(s->nsid);
+ s->csi = le64toh(s->csi);
+ s->ttsi = le16toh(s->ttsi);
}
static inline
@@ -1467,6 +1839,10 @@ void nvme_health_information_page_swapbytes(struct nvme_health_information_page
s->error_temp_time = le32toh(s->error_temp_time);
for (i = 0; i < 8; i++)
s->temp_sensor[i] = le16toh(s->temp_sensor[i]);
+ s->tmt1tc = le32toh(s->tmt1tc);
+ s->tmt2tc = le32toh(s->tmt2tc);
+ s->ttftmt1 = le32toh(s->ttftmt1);
+ s->ttftmt2 = le32toh(s->ttftmt2);
}
@@ -1489,6 +1865,38 @@ void nvme_ns_list_swapbytes(struct nvme_ns_list *s)
}
static inline
+void nvme_command_effects_page_swapbytes(struct nvme_command_effects_page *s)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ s->acs[i] = le32toh(s->acs[i]);
+ for (i = 0; i < 256; i++)
+ s->iocs[i] = le32toh(s->iocs[i]);
+}
+
+static inline
+void nvme_res_notification_page_swapbytes(struct nvme_res_notification_page *s)
+{
+ s->log_page_count = le64toh(s->log_page_count);
+ s->nsid = le32toh(s->nsid);
+}
+
+static inline
+void nvme_sanitize_status_page_swapbytes(struct nvme_sanitize_status_page *s)
+{
+ s->sprog = le16toh(s->sprog);
+ s->sstat = le16toh(s->sstat);
+ s->scdw10 = le32toh(s->scdw10);
+ s->etfo = le32toh(s->etfo);
+ s->etfbe = le32toh(s->etfbe);
+ s->etfce = le32toh(s->etfce);
+ s->etfownd = le32toh(s->etfownd);
+ s->etfbewnd = le32toh(s->etfbewnd);
+ s->etfcewnd = le32toh(s->etfcewnd);
+}
+
+static inline
void intel_log_temp_stats_swapbytes(struct intel_log_temp_stats *s)
{
@@ -1503,4 +1911,34 @@ void intel_log_temp_stats_swapbytes(struct intel_log_temp_stats *s)
s->est_offset = le64toh(s->est_offset);
}
+static inline
+void nvme_resv_status_swapbytes(struct nvme_resv_status *s, size_t size)
+{
+ u_int i, n;
+
+ s->gen = le32toh(s->gen);
+ n = (s->regctl[1] << 8) | s->regctl[0];
+ n = MIN(n, (size - sizeof(s)) / sizeof(s->ctrlr[0]));
+ for (i = 0; i < n; i++) {
+ s->ctrlr[i].ctrlr_id = le16toh(s->ctrlr[i].ctrlr_id);
+ s->ctrlr[i].hostid = le64toh(s->ctrlr[i].hostid);
+ s->ctrlr[i].rkey = le64toh(s->ctrlr[i].rkey);
+ }
+}
+
+static inline
+void nvme_resv_status_ext_swapbytes(struct nvme_resv_status_ext *s, size_t size)
+{
+ u_int i, n;
+
+ s->gen = le32toh(s->gen);
+ n = (s->regctl[1] << 8) | s->regctl[0];
+ n = MIN(n, (size - sizeof(s)) / sizeof(s->ctrlr[0]));
+ for (i = 0; i < n; i++) {
+ s->ctrlr[i].ctrlr_id = le16toh(s->ctrlr[i].ctrlr_id);
+ s->ctrlr[i].rkey = le64toh(s->ctrlr[i].rkey);
+ nvme_le128toh((void *)s->ctrlr[i].hostid);
+ }
+}
+
#endif /* __NVME_H__ */
diff --git a/freebsd/sys/dev/ofw/ofw_bus_subr.h b/freebsd/sys/dev/ofw/ofw_bus_subr.h
index 468fdc39..218ba710 100644
--- a/freebsd/sys/dev/ofw/ofw_bus_subr.h
+++ b/freebsd/sys/dev/ofw/ofw_bus_subr.h
@@ -65,9 +65,11 @@ struct intr_map_data_fdt {
};
#endif
-#define SIMPLEBUS_PNP_DESCR "Z:compat;P:#;"
-#define SIMPLEBUS_PNP_INFO(t) \
- MODULE_PNP_INFO(SIMPLEBUS_PNP_DESCR, simplebus, t, t, sizeof(t) / sizeof(t[0]));
+#define FDTCOMPAT_PNP_DESCR "Z:compat;P:#;"
+#define FDTCOMPAT_PNP_INFO(t, busname) \
+ MODULE_PNP_INFO(FDTCOMPAT_PNP_DESCR, busname, t, t, sizeof(t) / sizeof(t[0]));
+
+#define SIMPLEBUS_PNP_INFO(t) FDTCOMPAT_PNP_INFO(t, simplebus)
/* Generic implementation of ofw_bus_if.m methods and helper routines */
int ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *, phandle_t);
diff --git a/freebsd/sys/dev/ofw/ofw_subr.c b/freebsd/sys/dev/ofw/ofw_subr.c
index 4a20727c..7483a2d2 100644
--- a/freebsd/sys/dev/ofw/ofw_subr.c
+++ b/freebsd/sys/dev/ofw/ofw_subr.c
@@ -81,7 +81,8 @@ int
ofw_reg_to_paddr(phandle_t dev, int regno, bus_addr_t *paddr,
bus_size_t *psize, pcell_t *ppci_hi)
{
- pcell_t cell[32], pci_hi;
+ static pcell_t cell[256];
+ pcell_t pci_hi;
uint64_t addr, raddr, baddr;
uint64_t size, rsize;
uint32_t c, nbridge, naddr, nsize;
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c
index f2a46d03..5402cb66 100644
--- a/freebsd/sys/dev/pci/pci.c
+++ b/freebsd/sys/dev/pci/pci.c
@@ -33,20 +33,22 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <rtems/bsd/local/opt_acpi.h>
#include <rtems/bsd/local/opt_bus.h>
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/limits.h>
-#include <sys/linker.h>
-#include <sys/fcntl.h>
#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/eventhandler.h>
+#include <sys/fcntl.h>
#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/linker.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
-#include <sys/endian.h>
+#include <sys/systm.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -137,6 +139,10 @@ static int pci_remap_intr_method(device_t bus, device_t dev,
static void pci_hint_device_unit(device_t acdev, device_t child,
const char *name, int *unitp);
#endif /* __rtems__ */
+static int pci_reset_post(device_t dev, device_t child);
+static int pci_reset_prepare(device_t dev, device_t child);
+static int pci_reset_child(device_t dev, device_t child,
+ int flags);
static int pci_get_id_method(device_t dev, device_t child,
enum pci_id_type type, uintptr_t *rid);
@@ -161,6 +167,9 @@ static device_method_t pci_methods[] = {
DEVMETHOD(bus_driver_added, pci_driver_added),
DEVMETHOD(bus_setup_intr, pci_setup_intr),
DEVMETHOD(bus_teardown_intr, pci_teardown_intr),
+ DEVMETHOD(bus_reset_prepare, pci_reset_prepare),
+ DEVMETHOD(bus_reset_post, pci_reset_post),
+ DEVMETHOD(bus_reset_child, pci_reset_child),
DEVMETHOD(bus_get_dma_tag, pci_get_dma_tag),
DEVMETHOD(bus_get_resource_list,pci_get_resource_list),
@@ -355,7 +364,7 @@ SYSCTL_INT(_hw_pci, OID_AUTO, enable_io_modes, CTLFLAG_RWTUN,
" enable these bits correctly. We'd like to do this all the time, but"
" there are some peripherals that this causes problems with.");
-static int pci_do_realloc_bars = 0;
+static int pci_do_realloc_bars = 1;
SYSCTL_INT(_hw_pci, OID_AUTO, realloc_bars, CTLFLAG_RWTUN,
&pci_do_realloc_bars, 0,
"Attempt to allocate a new range for any BARs whose original "
@@ -1678,10 +1687,13 @@ pci_mask_msix(device_t dev, u_int index)
KASSERT(msix->msix_msgnum > index, ("bogus index"));
offset = msix->msix_table_offset + index * 16 + 12;
val = bus_read_4(msix->msix_table_res, offset);
- if (!(val & PCIM_MSIX_VCTRL_MASK)) {
- val |= PCIM_MSIX_VCTRL_MASK;
- bus_write_4(msix->msix_table_res, offset, val);
- }
+ val |= PCIM_MSIX_VCTRL_MASK;
+
+ /*
+ * Some devices (e.g. Samsung PM961) do not support reads of this
+ * register, so always write the new value.
+ */
+ bus_write_4(msix->msix_table_res, offset, val);
}
void
@@ -1694,10 +1706,13 @@ pci_unmask_msix(device_t dev, u_int index)
KASSERT(msix->msix_table_len > index, ("bogus index"));
offset = msix->msix_table_offset + index * 16 + 12;
val = bus_read_4(msix->msix_table_res, offset);
- if (val & PCIM_MSIX_VCTRL_MASK) {
- val &= ~PCIM_MSIX_VCTRL_MASK;
- bus_write_4(msix->msix_table_res, offset, val);
- }
+ val &= ~PCIM_MSIX_VCTRL_MASK;
+
+ /*
+ * Some devices (e.g. Samsung PM961) do not support reads of this
+ * register, so always write the new value.
+ */
+ bus_write_4(msix->msix_table_res, offset, val);
}
int
@@ -4359,9 +4374,6 @@ pci_attach_common(device_t dev)
{
struct pci_softc *sc;
int busno, domain;
-#ifdef PCI_DMA_BOUNDARY
- int error, tag_valid;
-#endif
#ifdef PCI_RES_BUS
int rid;
#endif
@@ -4381,23 +4393,7 @@ pci_attach_common(device_t dev)
if (bootverbose)
device_printf(dev, "domain=%d, physical bus=%d\n",
domain, busno);
-#ifdef PCI_DMA_BOUNDARY
- tag_valid = 0;
- if (device_get_devclass(device_get_parent(device_get_parent(dev))) !=
- devclass_find("pci")) {
- error = bus_dma_tag_create(bus_get_dma_tag(dev), 1,
- PCI_DMA_BOUNDARY, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
- NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED,
- BUS_SPACE_MAXSIZE, 0, NULL, NULL, &sc->sc_dma_tag);
- if (error)
- device_printf(dev, "Failed to create DMA tag: %d\n",
- error);
- else
- tag_valid = 1;
- }
- if (!tag_valid)
-#endif
- sc->sc_dma_tag = bus_get_dma_tag(dev);
+ sc->sc_dma_tag = bus_get_dma_tag(dev);
return (0);
}
@@ -5730,6 +5726,26 @@ pci_get_resource_list (device_t dev, device_t child)
return (&dinfo->resources);
}
+#ifdef ACPI_DMAR
+bus_dma_tag_t dmar_get_dma_tag(device_t dev, device_t child);
+bus_dma_tag_t
+pci_get_dma_tag(device_t bus, device_t dev)
+{
+ bus_dma_tag_t tag;
+ struct pci_softc *sc;
+
+ if (device_get_parent(dev) == bus) {
+ /* try dmar and return if it works */
+ tag = dmar_get_dma_tag(bus, dev);
+ } else
+ tag = NULL;
+ if (tag == NULL) {
+ sc = device_get_softc(bus);
+ tag = sc->sc_dma_tag;
+ }
+ return (tag);
+}
+#else
bus_dma_tag_t
pci_get_dma_tag(device_t bus, device_t dev)
{
@@ -5737,6 +5753,7 @@ pci_get_dma_tag(device_t bus, device_t dev)
return (sc->sc_dma_tag);
}
+#endif
uint32_t
pci_read_config_method(device_t dev, device_t child, int reg, int width)
@@ -6402,6 +6419,94 @@ pcie_flr(device_t dev, u_int max_delay, bool force)
return (true);
}
+/*
+ * Attempt a power-management reset by cycling the device in/out of D3
+ * state. PCI spec says we can only go into D3 state from D0 state.
+ * Transition from D[12] into D0 before going to D3 state.
+ */
+int
+pci_power_reset(device_t dev)
+{
+ int ps;
+
+ ps = pci_get_powerstate(dev);
+ if (ps != PCI_POWERSTATE_D0 && ps != PCI_POWERSTATE_D3)
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ pci_set_powerstate(dev, PCI_POWERSTATE_D3);
+ pci_set_powerstate(dev, ps);
+ return (0);
+}
+
+/*
+ * Try link drop and retrain of the downstream port of upstream
+ * switch, for PCIe. According to the PCIe 3.0 spec 6.6.1, this must
+ * cause Conventional Hot reset of the device in the slot.
+ * Alternative, for PCIe, could be the secondary bus reset initiatied
+ * on the upstream switch PCIR_BRIDGECTL_1, bit 6.
+ */
+int
+pcie_link_reset(device_t port, int pcie_location)
+{
+ uint16_t v;
+
+ v = pci_read_config(port, pcie_location + PCIER_LINK_CTL, 2);
+ v |= PCIEM_LINK_CTL_LINK_DIS;
+ pci_write_config(port, pcie_location + PCIER_LINK_CTL, v, 2);
+ pause_sbt("pcier1", mstosbt(20), 0, 0);
+ v &= ~PCIEM_LINK_CTL_LINK_DIS;
+ v |= PCIEM_LINK_CTL_RETRAIN_LINK;
+ pci_write_config(port, pcie_location + PCIER_LINK_CTL, v, 2);
+ pause_sbt("pcier2", mstosbt(100), 0, 0); /* 100 ms */
+ v = pci_read_config(port, pcie_location + PCIER_LINK_STA, 2);
+ return ((v & PCIEM_LINK_STA_TRAINING) != 0 ? ETIMEDOUT : 0);
+}
+
+static int
+pci_reset_post(device_t dev, device_t child)
+{
+
+ if (dev == device_get_parent(child))
+ pci_restore_state(child);
+ return (0);
+}
+
+static int
+pci_reset_prepare(device_t dev, device_t child)
+{
+
+ if (dev == device_get_parent(child))
+ pci_save_state(child);
+ return (0);
+}
+
+static int
+pci_reset_child(device_t dev, device_t child, int flags)
+{
+ int error;
+
+ if (dev == NULL || device_get_parent(child) != dev)
+ return (0);
+ if ((flags & DEVF_RESET_DETACH) != 0) {
+ error = device_get_state(child) == DS_ATTACHED ?
+ device_detach(child) : 0;
+ } else {
+ error = BUS_SUSPEND_CHILD(dev, child);
+ }
+ if (error == 0) {
+ if (!pcie_flr(child, 1000, false)) {
+ error = BUS_RESET_PREPARE(dev, child);
+ if (error == 0)
+ pci_power_reset(child);
+ BUS_RESET_POST(dev, child);
+ }
+ if ((flags & DEVF_RESET_DETACH) != 0)
+ device_probe_and_attach(child);
+ else
+ BUS_RESUME_CHILD(dev, child);
+ }
+ return (error);
+}
+
const struct pci_device_table *
pci_match_device(device_t child, const struct pci_device_table *id, size_t nelt)
{
diff --git a/freebsd/sys/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c
index 607a0614..cdcba150 100644
--- a/freebsd/sys/dev/pci/pci_pci.c
+++ b/freebsd/sys/dev/pci/pci_pci.c
@@ -44,8 +44,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/pciio.h>
#include <sys/rman.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
@@ -82,6 +85,7 @@ static void pcib_pcie_dll_timeout(void *arg);
#endif
static int pcib_request_feature_default(device_t pcib, device_t dev,
enum pci_feature feature);
+static int pcib_reset_child(device_t dev, device_t child, int flags);
static device_method_t pcib_methods[] = {
/* Device interface */
@@ -108,6 +112,7 @@ static device_method_t pcib_methods[] = {
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_reset_child, pcib_reset_child),
/* pcib interface */
DEVMETHOD(pcib_maxslots, pcib_ari_maxslots),
@@ -1167,9 +1172,11 @@ pcib_pcie_intr_hotplug(void *arg)
{
struct pcib_softc *sc;
device_t dev;
+ uint16_t old_slot_sta;
sc = arg;
dev = sc->dev;
+ old_slot_sta = sc->pcie_slot_sta;
sc->pcie_slot_sta = pcie_read_config(dev, PCIER_SLOT_STA, 2);
/* Clear the events just reported. */
@@ -1185,7 +1192,8 @@ pcib_pcie_intr_hotplug(void *arg)
"Attention Button Pressed: Detach Cancelled\n");
sc->flags &= ~PCIB_DETACH_PENDING;
callout_stop(&sc->pcie_ab_timer);
- } else {
+ } else if (old_slot_sta & PCIEM_SLOT_STA_PDS) {
+ /* Only initiate detach sequence if device present. */
device_printf(dev,
"Attention Button Pressed: Detaching in 5 seconds\n");
sc->flags |= PCIB_DETACH_PENDING;
@@ -1266,11 +1274,8 @@ pcib_pcie_cc_timeout(void *arg)
mtx_assert(&Giant, MA_OWNED);
sta = pcie_read_config(dev, PCIER_SLOT_STA, 2);
if (!(sta & PCIEM_SLOT_STA_CC)) {
- device_printf(dev,
- "HotPlug Command Timed Out - forcing detach\n");
- sc->flags &= ~(PCIB_HOTPLUG_CMD_PENDING | PCIB_DETACH_PENDING);
- sc->flags |= PCIB_DETACHING;
- pcib_pcie_hotplug_update(sc, 0, 0, true);
+ device_printf(dev, "HotPlug Command Timed Out\n");
+ sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING;
} else {
device_printf(dev,
"Missed HotPlug interrupt waiting for Command Completion\n");
@@ -2911,3 +2916,31 @@ pcib_request_feature_default(device_t pcib, device_t dev,
bus = device_get_parent(pcib);
return (PCIB_REQUEST_FEATURE(device_get_parent(bus), dev, feature));
}
+
+static int
+pcib_reset_child(device_t dev, device_t child, int flags)
+{
+ struct pci_devinfo *pdinfo;
+ int error;
+
+ error = 0;
+ if (dev == NULL || device_get_parent(child) != dev)
+ goto out;
+ error = ENXIO;
+ if (device_get_devclass(child) != devclass_find("pci"))
+ goto out;
+ pdinfo = device_get_ivars(dev);
+ if (pdinfo->cfg.pcie.pcie_location != 0 &&
+ (pdinfo->cfg.pcie.pcie_type == PCIEM_TYPE_DOWNSTREAM_PORT ||
+ pdinfo->cfg.pcie.pcie_type == PCIEM_TYPE_ROOT_PORT)) {
+ error = bus_helper_reset_prepare(child, flags);
+ if (error == 0) {
+ error = pcie_link_reset(dev,
+ pdinfo->cfg.pcie.pcie_location);
+ /* XXXKIB call _post even if error != 0 ? */
+ bus_helper_reset_post(child, flags);
+ }
+ }
+out:
+ return (error);
+}
diff --git a/freebsd/sys/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c
index 3e2c3c7e..bdf8a935 100644
--- a/freebsd/sys/dev/pci/pci_user.c
+++ b/freebsd/sys/dev/pci/pci_user.c
@@ -858,6 +858,7 @@ pci_bar_mmap(device_t pcidev, struct pci_bar_mmap *pbm)
struct thread *td;
struct sglist *sg;
struct pci_map *pm;
+ vm_paddr_t membase;
vm_paddr_t pbase;
vm_size_t plen;
vm_offset_t addr;
@@ -880,8 +881,9 @@ pci_bar_mmap(device_t pcidev, struct pci_bar_mmap *pbm)
return (EBUSY); /* XXXKIB enable if _ACTIVATE */
if (!PCI_BAR_MEM(pm->pm_value))
return (EIO);
- pbase = trunc_page(pm->pm_value);
- plen = round_page(pm->pm_value + ((pci_addr_t)1 << pm->pm_size)) -
+ membase = pm->pm_value & PCIM_BAR_MEM_BASE;
+ pbase = trunc_page(membase);
+ plen = round_page(membase + ((pci_addr_t)1 << pm->pm_size)) -
pbase;
prot = VM_PROT_READ | (((pbm->pbm_flags & PCIIO_BAR_MMAP_RW) != 0) ?
VM_PROT_WRITE : 0);
@@ -913,7 +915,7 @@ pci_bar_mmap(device_t pcidev, struct pci_bar_mmap *pbm)
}
pbm->pbm_map_base = (void *)addr;
pbm->pbm_map_length = plen;
- pbm->pbm_bar_off = pm->pm_value - pbase;
+ pbm->pbm_bar_off = membase - pbase;
pbm->pbm_bar_length = (pci_addr_t)1 << pm->pm_size;
out:
diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h
index 2ea7b877..d27cd1d2 100644
--- a/freebsd/sys/dev/pci/pcivar.h
+++ b/freebsd/sys/dev/pci/pcivar.h
@@ -33,7 +33,7 @@
#define _PCIVAR_H_
#include <sys/queue.h>
-#include <sys/eventhandler.h>
+#include <sys/_eventhandler.h>
/* some PCI bus constants */
#define PCI_MAXMAPS_0 6 /* max. no. of memory/port maps */
@@ -259,6 +259,13 @@ typedef struct {
extern uint32_t pci_numdevs;
+/*
+ * The bitfield has to be stable and match the fields below (so that
+ * match_flag_vendor must be bit 0) so we have to do the endian dance. We can't
+ * use enums or #define constants because then the macros for subsetting matches
+ * wouldn't work. These tables are parsed by devmatch and others to connect
+ * modules with devices on the PCI bus.
+ */
struct pci_device_table {
#if BYTE_ORDER == LITTLE_ENDIAN
uint16_t
@@ -674,6 +681,7 @@ int pci_get_max_read_req(device_t dev);
void pci_restore_state(device_t dev);
void pci_save_state(device_t dev);
int pci_set_max_read_req(device_t dev, int size);
+int pci_power_reset(device_t dev);
uint32_t pcie_read_config(device_t dev, int reg, int width);
void pcie_write_config(device_t dev, int reg, uint32_t value, int width);
uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask,
@@ -681,17 +689,10 @@ uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask,
bool pcie_flr(device_t dev, u_int max_delay, bool force);
int pcie_get_max_completion_timeout(device_t dev);
bool pcie_wait_for_pending_transactions(device_t dev, u_int max_delay);
+int pcie_link_reset(device_t port, int pcie_location);
void pci_print_faulted_dev(void);
-#ifdef BUS_SPACE_MAXADDR
-#if (BUS_SPACE_MAXADDR > 0xFFFFFFFF)
-#define PCI_DMA_BOUNDARY 0x100000000
-#else
-#define PCI_DMA_BOUNDARY 0
-#endif
-#endif
-
#endif /* _SYS_BUS_H_ */
/*
diff --git a/freebsd/sys/dev/rtwn/if_rtwn.c b/freebsd/sys/dev/rtwn/if_rtwn.c
index 79868dc0..0ca83e8a 100644
--- a/freebsd/sys/dev/rtwn/if_rtwn.c
+++ b/freebsd/sys/dev/rtwn/if_rtwn.c
@@ -155,9 +155,6 @@ static void rtwn_stop(struct rtwn_softc *);
MALLOC_DEFINE(M_RTWN_PRIV, "rtwn_priv", "rtwn driver private state");
-static const uint8_t rtwn_chan_2ghz[] =
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
-
static const uint16_t wme2reg[] =
{ R92C_EDCA_BE_PARAM, R92C_EDCA_BK_PARAM,
R92C_EDCA_VI_PARAM, R92C_EDCA_VO_PARAM };
@@ -1536,9 +1533,8 @@ rtwn_getradiocaps(struct ieee80211com *ic,
setbit(bands, IEEE80211_MODE_11B);
setbit(bands, IEEE80211_MODE_11G);
setbit(bands, IEEE80211_MODE_11NG);
- ieee80211_add_channel_list_2ghz(chans, maxchans, nchans,
- rtwn_chan_2ghz, nitems(rtwn_chan_2ghz), bands,
- !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40));
+ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans,
+ bands, !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40));
/* XXX workaround add_channel_list() limitations */
setbit(bands, IEEE80211_MODE_11A);
@@ -1566,10 +1562,6 @@ rtwn_set_channel(struct ieee80211com *ic)
RTWN_LOCK(sc);
rtwn_set_chan(sc, c);
- sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq);
- sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags);
- sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq);
- sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags);
RTWN_UNLOCK(sc);
}
diff --git a/freebsd/sys/dev/rtwn/if_rtwnvar.h b/freebsd/sys/dev/rtwn/if_rtwnvar.h
index 3ebcba52..a6e7ea9f 100644
--- a/freebsd/sys/dev/rtwn/if_rtwnvar.h
+++ b/freebsd/sys/dev/rtwn/if_rtwnvar.h
@@ -62,9 +62,10 @@ struct rtwn_rx_radiotap_header {
struct rtwn_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
+ uint8_t wt_pad;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define RTWN_TX_RADIOTAP_PRESENT \
(1 << IEEE80211_RADIOTAP_FLAGS | \
diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.h b/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.h
index 6df5812e..796d8c4d 100644
--- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.h
+++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_attach.h
@@ -17,9 +17,11 @@
*/
void r92ce_attach(struct rtwn_pci_softc *);
+void r88ee_attach(struct rtwn_pci_softc *);
enum {
RTWN_CHIP_RTL8192CE,
+ RTWN_CHIP_RTL8188EE,
RTWN_CHIP_MAX_PCI
};
@@ -32,13 +34,16 @@ struct rtwn_pci_ident {
static const struct rtwn_pci_ident rtwn_pci_ident_table[] = {
{ 0x10ec, 0x8176, "Realtek RTL8188CE", RTWN_CHIP_RTL8192CE },
+ { 0x10ec, 0x8179, "Realtek RTL8188EE", RTWN_CHIP_RTL8188EE },
+ { 0x10ec, 0x8178, "Realtek RTL8192CE", RTWN_CHIP_RTL8192CE },
{ 0, 0, NULL, RTWN_CHIP_MAX_PCI }
};
typedef void (*chip_pci_attach)(struct rtwn_pci_softc *);
static const chip_pci_attach rtwn_chip_pci_attach[RTWN_CHIP_MAX_PCI] = {
- [RTWN_CHIP_RTL8192CE] = r92ce_attach
+ [RTWN_CHIP_RTL8192CE] = r92ce_attach,
+ [RTWN_CHIP_RTL8188EE] = r88ee_attach
};
static __inline void
diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_reg.c b/freebsd/sys/dev/rtwn/pci/rtwn_pci_reg.c
index 8ce54f0d..5b998b5a 100644
--- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_reg.c
+++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_reg.c
@@ -120,6 +120,6 @@ rtwn_pci_delay(struct rtwn_softc *sc, int usec)
DELAY(usec);
else {
(void) mtx_sleep(sc, &sc->sc_mtx, 0, "rtwn_pci",
- MAX(msecs_to_ticks(usec / 1000), 1));
+ msecs_to_ticks(usec / 1000));
}
}
diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c b/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c
index 1934b741..f97fea44 100644
--- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c
+++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_rx.c
@@ -85,12 +85,12 @@ rtwn_pci_setup_rx_desc(struct rtwn_pci_softc *pc,
}
static void
-rtwn_pci_rx_frame(struct rtwn_softc *sc, struct rtwn_rx_stat_pci *rx_desc,
- int desc_idx)
+rtwn_pci_rx_frame(struct rtwn_pci_softc *pc)
{
- struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
+ struct rtwn_softc *sc = &pc->pc_sc;
struct rtwn_rx_ring *ring = &pc->rx_ring;
- struct rtwn_rx_data *rx_data = &ring->rx_data[desc_idx];
+ struct rtwn_rx_stat_pci *rx_desc = &ring->desc[ring->cur];
+ struct rtwn_rx_data *rx_data = &ring->rx_data[ring->cur];
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
uint32_t rxdw0;
@@ -150,9 +150,6 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct rtwn_rx_stat_pci *rx_desc,
panic("%s: could not load old RX mbuf",
device_get_name(sc->sc_dev));
- /* Physical address may have changed. */
- rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr,
- MJUMPAGESIZE, desc_idx);
goto fail;
}
@@ -167,10 +164,6 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct rtwn_rx_stat_pci *rx_desc,
"%s: Rx frame len %d, infosz %d, shift %d\n",
__func__, pktlen, infosz, shift);
- /* Update RX descriptor. */
- rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MJUMPAGESIZE,
- desc_idx);
-
/* Send the frame to the 802.11 layer. */
RTWN_UNLOCK(sc);
if (ni != NULL) {
@@ -188,6 +181,72 @@ fail:
counter_u64_add(ic->ic_ierrors, 1);
}
+static int
+rtwn_pci_rx_buf_copy(struct rtwn_pci_softc *pc)
+{
+ struct rtwn_rx_ring *ring = &pc->rx_ring;
+ struct rtwn_rx_stat_pci *rx_desc = &ring->desc[ring->cur];
+ struct rtwn_rx_data *rx_data = &ring->rx_data[ring->cur];
+ uint32_t rxdw0;
+ int desc_size, pktlen;
+
+ /*
+ * NB: tx_report() / c2h_report() expects to see USB Rx
+ * descriptor - same as for PCIe, but without rxbufaddr* fields.
+ */
+ desc_size = sizeof(struct rtwn_rx_stat_common);
+ KASSERT(sizeof(pc->pc_rx_buf) >= desc_size,
+ ("adjust size for PCIe Rx buffer!"));
+
+ memcpy(pc->pc_rx_buf, rx_desc, desc_size);
+
+ rxdw0 = le32toh(rx_desc->rxdw0);
+ pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN);
+
+ if (pktlen > sizeof(pc->pc_rx_buf) - desc_size)
+ {
+ /* Looks like an ordinary Rx frame. */
+ return (desc_size);
+ }
+
+ bus_dmamap_sync(ring->data_dmat, rx_data->map, BUS_DMASYNC_POSTREAD);
+ memcpy(pc->pc_rx_buf + desc_size, mtod(rx_data->m, void *), pktlen);
+
+ return (desc_size + pktlen);
+}
+
+static void
+rtwn_pci_tx_report(struct rtwn_pci_softc *pc, int len)
+{
+ struct rtwn_softc *sc = &pc->pc_sc;
+
+ if (sc->sc_ratectl != RTWN_RATECTL_NET80211) {
+ /* shouldn't happen */
+ device_printf(sc->sc_dev,
+ "%s called while ratectl = %d!\n",
+ __func__, sc->sc_ratectl);
+ return;
+ }
+
+ RTWN_NT_LOCK(sc);
+ rtwn_handle_tx_report(sc, pc->pc_rx_buf, len);
+ RTWN_NT_UNLOCK(sc);
+
+#ifdef IEEE80211_SUPPORT_SUPERG
+ /*
+ * NB: this will executed only when 'report' bit is set.
+ */
+ if (sc->sc_tx_n_active > 0 && --sc->sc_tx_n_active <= 1)
+ rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
+#endif
+}
+
+static void
+rtwn_pci_c2h_report(struct rtwn_pci_softc *pc, int len)
+{
+ rtwn_handle_c2h_report(&pc->pc_sc, pc->pc_rx_buf, len);
+}
+
static void
rtwn_pci_tx_done(struct rtwn_softc *sc, int qid)
{
@@ -199,7 +258,8 @@ rtwn_pci_tx_done(struct rtwn_softc *sc, int qid)
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: qid %d, last %d, cur %d\n",
__func__, qid, ring->last, ring->cur);
- bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
while(ring->last != ring->cur) {
data = &ring->tx_data[ring->last];
@@ -264,21 +324,50 @@ rtwn_pci_rx_done(struct rtwn_softc *sc)
{
struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
struct rtwn_rx_ring *ring = &pc->rx_ring;
+ struct rtwn_rx_stat_pci *rx_desc;
+ struct rtwn_rx_data *rx_data;
+ int len;
bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD);
for (;;) {
- struct rtwn_rx_stat_pci *rx_desc = &ring->desc[ring->cur];
+ rx_desc = &ring->desc[ring->cur];
+ rx_data = &ring->rx_data[ring->cur];
if (le32toh(rx_desc->rxdw0) & RTWN_RXDW0_OWN)
break;
- rtwn_pci_rx_frame(sc, rx_desc, ring->cur);
+ len = rtwn_pci_rx_buf_copy(pc);
+
+ switch (rtwn_classify_intr(sc, pc->pc_rx_buf, len)) {
+ case RTWN_RX_DATA:
+ rtwn_pci_rx_frame(pc);
+ break;
+ case RTWN_RX_TX_REPORT:
+ rtwn_pci_tx_report(pc, len);
+ break;
+ case RTWN_RX_OTHER:
+ rtwn_pci_c2h_report(pc, len);
+ break;
+ default:
+ /* NOTREACHED */
+ KASSERT(0, ("unknown Rx classification code"));
+ break;
+ }
+
+ /* Update / reset RX descriptor (and set OWN bit). */
+ rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr,
+ MJUMPAGESIZE, ring->cur);
if (!(sc->sc_flags & RTWN_RUNNING))
return;
- ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT;
+ /* NB: device can reuse current descriptor. */
+ bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
+ BUS_DMASYNC_POSTREAD);
+
+ if (le32toh(rx_desc->rxdw0) & RTWN_RXDW0_OWN)
+ ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT;
}
}
@@ -290,13 +379,13 @@ rtwn_pci_intr(void *arg)
int i, status, tx_rings;
RTWN_LOCK(sc);
- status = rtwn_classify_intr(sc, &tx_rings, 0);
+ status = rtwn_pci_get_intr_status(pc, &tx_rings);
RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: status %08X, tx_rings %08X\n",
__func__, status, tx_rings);
if (status == 0 && tx_rings == 0)
goto unlock;
- if (status & RTWN_PCI_INTR_RX) {
+ if (status & (RTWN_PCI_INTR_RX | RTWN_PCI_INTR_TX_REPORT)) {
rtwn_pci_rx_done(sc);
if (!(sc->sc_flags & RTWN_RUNNING))
goto unlock;
diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_tx.c b/freebsd/sys/dev/rtwn/pci/rtwn_pci_tx.c
index 50e915ee..1d3852ca 100644
--- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_tx.c
+++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_tx.c
@@ -176,8 +176,8 @@ rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni,
rtwn_dump_tx_desc(sc, txd);
bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE);
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE);
data->m = m;
data->ni = ni;
diff --git a/freebsd/sys/dev/rtwn/pci/rtwn_pci_var.h b/freebsd/sys/dev/rtwn/pci/rtwn_pci_var.h
index 194fab4a..95b2effe 100644
--- a/freebsd/sys/dev/rtwn/pci/rtwn_pci_var.h
+++ b/freebsd/sys/dev/rtwn/pci/rtwn_pci_var.h
@@ -26,6 +26,9 @@
#define RTWN_PCI_RX_LIST_COUNT 256
#define RTWN_PCI_TX_LIST_COUNT 256
+/* sizeof(struct rtwn_rx_stat_common) + R88E_INTR_MSG_LEN */
+#define RTWN_PCI_RX_TMP_BUF_SIZE 84
+
struct rtwn_rx_data {
bus_dmamap_t map;
struct mbuf *m;
@@ -95,8 +98,8 @@ enum {
/* Shortcuts */
/* Vendor driver treats RX errors like ROK... */
#define RTWN_PCI_INTR_RX \
- (RTWN_PCI_INTR_RX_OVERFLOW | RTWN_PCI_INTR_RX_DESC_UNAVAIL | \
- RTWN_PCI_INTR_RX_DONE)
+ (RTWN_PCI_INTR_RX_ERROR | RTWN_PCI_INTR_RX_OVERFLOW | \
+ RTWN_PCI_INTR_RX_DESC_UNAVAIL | RTWN_PCI_INTR_RX_DONE)
struct rtwn_pci_softc {
@@ -109,6 +112,7 @@ struct rtwn_pci_softc {
void *pc_ih;
bus_size_t pc_mapsize;
+ uint8_t pc_rx_buf[RTWN_PCI_RX_TMP_BUF_SIZE];
struct rtwn_rx_ring rx_ring;
struct rtwn_tx_ring tx_ring[RTWN_PCI_NTXQUEUES];
@@ -122,6 +126,8 @@ struct rtwn_pci_softc {
void *, bus_dma_segment_t *);
void (*pc_copy_tx_desc)(void *, const void *);
void (*pc_enable_intr)(struct rtwn_pci_softc *);
+ int (*pc_get_intr_status)(struct rtwn_pci_softc *,
+ int *);
};
#define RTWN_PCI_SOFTC(sc) ((struct rtwn_pci_softc *)(sc))
@@ -133,5 +139,7 @@ struct rtwn_pci_softc {
(((_pc)->pc_copy_tx_desc)((_dest), (_src)))
#define rtwn_pci_enable_intr(_pc) \
(((_pc)->pc_enable_intr)((_pc)))
+#define rtwn_pci_get_intr_status(_pc, _tx_rings) \
+ (((_pc)->pc_get_intr_status)((_pc), (_tx_rings)))
#endif /* RTWN_PCI_VAR_H */
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h
index 3a3c0865..ce9fa19a 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e.h
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e.h
@@ -24,9 +24,7 @@
/*
* Global definitions.
*/
-#define R88E_PUBQ_NPAGES 142
#define R88E_TXPKTBUF_COUNT 177
-#define R88E_TX_PAGE_COUNT 169
#define R88E_MACID_MAX 63
#define R88E_RX_DMA_BUFFER_SIZE 0x2400
@@ -67,9 +65,8 @@ int r88e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int);
#endif
/* r88e_init.c */
-void r88e_init_bb(struct rtwn_softc *);
+void r88e_init_bb_common(struct rtwn_softc *);
void r88e_init_rf(struct rtwn_softc *);
-int r88e_power_on(struct rtwn_softc *);
/* r88e_led.c */
void r88e_set_led(struct rtwn_softc *, int, int);
@@ -81,6 +78,7 @@ void r88e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
void r88e_parse_rom(struct rtwn_softc *, uint8_t *);
/* r88e_rx.c */
+int r88e_classify_intr(struct rtwn_softc *, void *, int);
void r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int);
void r88e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int);
int8_t r88e_get_rssi_cck(struct rtwn_softc *, void *);
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c
index 592f391a..94974983 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_calib.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
- * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
+ * Copyright (c) 2016-2019 Andriy Voskoboinyk <avos@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -44,16 +44,343 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
+#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8188e/r88e.h>
#include <dev/rtwn/rtl8188e/r88e_reg.h>
+/* Registers to save and restore during IQ calibration. */
+struct r88e_iq_cal_reg_vals {
+ uint32_t adda[16];
+ uint8_t txpause;
+ uint8_t bcn_ctrl[2];
+ uint32_t gpio_muxcfg;
+ uint32_t cck0_afesetting;
+ uint32_t ofdm0_trxpathena;
+ uint32_t ofdm0_trmuxpar;
+ uint32_t fpga0_rfifacesw0;
+ uint32_t fpga0_rfifacesw1;
+ uint32_t fpga0_rfifaceoe0;
+ uint32_t fpga0_rfifaceoe1;
+ uint32_t config_ant0;
+ uint32_t config_ant1;
+};
+
+static int
+r88e_iq_calib_chain(struct rtwn_softc *sc, uint16_t tx[2], uint16_t rx[2])
+{
+ uint32_t status;
+
+ /* Set Rx IQ calibration mode table. */
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0);
+ rtwn_rf_write(sc, 0, R88E_RF_WE_LUT, 0x800a0);
+ rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000);
+ rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0xf);
+ rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf117b);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
+
+ /* IQ calibration settings. */
+ rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
+ rtwn_bb_write(sc, R92C_RX_IQK, 0x81004800);
+
+ /* IQ calibration settings for chain 0. */
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1c);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x30008c1c);
+ rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160804);
+ rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160000);
+
+ /* LO calibration settings. */
+ rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911);
+
+ /* We're doing LO and IQ calibration in one shot. */
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
+
+ /* Give LO and IQ calibrations the time to complete. */
+ rtwn_delay(sc, 10000);
+
+ /* Read IQ calibration status. */
+ status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0));
+ if (status & (1 << 28))
+ return (0); /* Tx failed. */
+
+ /* Read Tx IQ calibration results. */
+ tx[0] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(0)),
+ R92C_POWER_IQK_RESULT);
+ tx[1] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(0)),
+ R92C_POWER_IQK_RESULT);
+ if (tx[0] == 0x142 || tx[1] == 0x042)
+ return (0); /* Tx failed. */
+
+ rtwn_bb_write(sc, R92C_TX_IQK, 0x80007c00 | (tx[0] << 16) | tx[1]);
+
+ /* Set Rx IQ calibration mode table. */
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0);
+ rtwn_rf_write(sc, 0, R88E_RF_WE_LUT, 0x800a0);
+ rtwn_rf_write(sc, 0, R92C_RF_RCK_OS, 0x30000);
+ rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(0), 0xf);
+ rtwn_rf_write(sc, 0, R92C_RF_TXPA_G(1), 0xf7ffa);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
+
+ /* IQ calibration settings. */
+ rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
+
+ /* IQ calibration settings for chain 0. */
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x30008c1c);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1c);
+ rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82160c05);
+ rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160c05);
+
+ /* LO calibration settings. */
+ rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x0046a911);
+
+ /* We're doing LO and IQ calibration in one shot. */
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
+
+ /* Give LO and IQ calibrations the time to complete. */
+ rtwn_delay(sc, 10000);
+
+ /* Read IQ calibration status. */
+ status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0));
+ if (status & (1 << 27))
+ return (1); /* Rx failed. */
+
+ /* Read Rx IQ calibration results. */
+ rx[0] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(0)),
+ R92C_POWER_IQK_RESULT);
+ rx[1] = MS(status, R92C_POWER_IQK_RESULT);
+ if (rx[0] == 0x132 || rx[1] == 0x036)
+ return (1); /* Rx failed. */
+
+ return (3); /* Both Tx and Rx succeeded. */
+}
+
+static void
+r88e_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2],
+ uint16_t rx[2], struct r88e_iq_cal_reg_vals *vals)
+{
+ /* Registers to save and restore during IQ calibration. */
+ static const uint16_t reg_adda[16] = {
+ 0x85c, 0xe6c, 0xe70, 0xe74,
+ 0xe78, 0xe7c, 0xe80, 0xe84,
+ 0xe88, 0xe8c, 0xed0, 0xed4,
+ 0xed8, 0xedc, 0xee0, 0xeec
+ };
+ int i;
+ uint32_t hssi_param1;
+
+ if (n == 0) {
+ for (i = 0; i < nitems(reg_adda); i++)
+ vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]);
+
+ vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE);
+ vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0));
+ vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1));
+ vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG);
+ }
+
+ rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0);
+ for (i = 1; i < nitems(reg_adda); i++)
+ rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0);
+
+ hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
+ if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
+ hssi_param1 | R92C_HSSI_PARAM1_PI);
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
+ hssi_param1 | R92C_HSSI_PARAM1_PI);
+ }
+
+ if (n == 0) {
+ vals->cck0_afesetting = rtwn_bb_read(sc, R92C_CCK0_AFESETTING);
+ vals->ofdm0_trxpathena =
+ rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA);
+ vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR);
+ vals->fpga0_rfifacesw0 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0));
+ vals->fpga0_rfifacesw1 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1));
+ vals->fpga0_rfifaceoe0 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0));
+ vals->fpga0_rfifaceoe1 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(1));
+ vals->config_ant0 = rtwn_bb_read(sc, R92C_CONFIG_ANT(0));
+ vals->config_ant1 = rtwn_bb_read(sc, R92C_CONFIG_ANT(1));
+ }
+
+ rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0, 0x0f000000);
+ rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
+ rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
+ rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(0), 0, 0x04000400);
+ rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0x400, 0);
+ rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(1), 0x400, 0);
+
+ rtwn_write_1(sc, R92C_TXPAUSE,
+ R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH);
+ rtwn_write_1(sc, R92C_BCN_CTRL(0),
+ vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN);
+ rtwn_write_1(sc, R92C_BCN_CTRL(1),
+ vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN);
+ rtwn_write_1(sc, R92C_GPIO_MUXCFG,
+ vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT);
+
+ rtwn_bb_write(sc, R92C_CONFIG_ANT(0), 0x0f600000);
+
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
+ rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
+ rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
+
+ /* Run IQ calibration twice. */
+ for (i = 0; i < 2; i++) {
+ int ret;
+
+ ret = r88e_iq_calib_chain(sc, tx, rx);
+ if (ret == 0) {
+ RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Tx failed.\n",
+ __func__);
+ tx[0] = 0xff;
+ tx[1] = 0xff;
+ rx[0] = 0xff;
+ rx[1] = 0xff;
+ } else if (ret == 1) {
+ RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Rx failed.\n",
+ __func__);
+ rx[0] = 0xff;
+ rx[1] = 0xff;
+ } else if (ret == 3) {
+ RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: Both Tx and Rx"
+ " succeeded.\n", __func__);
+ }
+ }
+
+ RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
+ "%s: results for run %d: tx[0] 0x%x, tx[1] 0x%x, rx[0] 0x%x, "
+ "rx[1] 0x%x\n", __func__, n, tx[0], tx[1], rx[0], rx[1]);
+
+ rtwn_bb_write(sc, R92C_CCK0_AFESETTING, vals->cck0_afesetting);
+ rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, vals->ofdm0_trxpathena);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(0), vals->fpga0_rfifacesw0);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), vals->fpga0_rfifacesw1);
+ rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(0), vals->fpga0_rfifaceoe0);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(1), vals->fpga0_rfifaceoe1);
+ rtwn_bb_write(sc, R92C_CONFIG_ANT(0), vals->config_ant0);
+ rtwn_bb_write(sc, R92C_CONFIG_ANT(1), vals->config_ant1);
+
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0);
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
+
+ if (n != 0) {
+ if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1);
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1);
+ }
+
+ for (i = 0; i < nitems(reg_adda); i++)
+ rtwn_bb_write(sc, reg_adda[i], vals->adda[i]);
+
+ rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause);
+ rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]);
+ rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]);
+ rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg);
+ }
+}
+
+#define RTWN_IQ_CAL_MAX_TOLERANCE 5
+static int
+r88e_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2],
+ uint16_t rx1[2], uint16_t tx2[2], uint16_t rx2[2])
+{
+ int i, tx_ok, rx_ok;
+
+ tx_ok = rx_ok = 0;
+ for (i = 0; i < 2; i++) {
+ if (tx1[i] == 0xff || tx2[i] == 0xff ||
+ rx1[i] == 0xff || rx2[i] == 0xff)
+ continue;
+
+ tx_ok = (abs(tx1[i] - tx2[i]) <= RTWN_IQ_CAL_MAX_TOLERANCE);
+ rx_ok = (abs(rx1[i] - rx2[i]) <= RTWN_IQ_CAL_MAX_TOLERANCE);
+ }
+
+ return (tx_ok && rx_ok);
+}
+#undef RTWN_IQ_CAL_MAX_TOLERANCE
+
+static void
+r88e_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2],
+ uint16_t rx[2])
+{
+ uint32_t reg, val, x;
+ long y, tx_c;
+
+ if (tx[0] == 0xff || tx[1] == 0xff)
+ return;
+
+ reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(0));
+ val = ((reg >> 22) & 0x3ff);
+ x = tx[0];
+ if (x & 0x00000200)
+ x |= 0xfffffc00;
+ reg = (((x * val) >> 8) & 0x3ff);
+ rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(0), 0x3ff, reg);
+ rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000,
+ ((x * val) & 0x80) << 24);
+
+ y = tx[1];
+ if (y & 0x00000200)
+ y |= 0xfffffc00;
+ tx_c = (y * val) >> 8;
+ rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(0), 0xf0000000,
+ (tx_c & 0x3c0) << 22);
+ rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(0), 0x003f0000,
+ (tx_c & 0x3f) << 16);
+ rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000,
+ ((y * val) & 0x80) << 22);
+
+ if (rx[0] == 0xff || rx[1] == 0xff)
+ return;
+
+ rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0x3ff,
+ rx[0] & 0x3ff);
+ rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(0), 0xfc00,
+ (rx[1] & 0x3f) << 10);
+ rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000,
+ (rx[1] & 0x3c0) << 22);
+}
+
+#define RTWN_IQ_CAL_NRUN 3
void
r88e_iq_calib(struct rtwn_softc *sc)
{
- /* XXX TODO */
+ struct r88e_iq_cal_reg_vals vals;
+ uint16_t tx[RTWN_IQ_CAL_NRUN][2], rx[RTWN_IQ_CAL_NRUN][2];
+ int n, valid;
+
+ KASSERT(sc->ntxchains == 1,
+ ("%s: only 1T1R configuration is supported!\n", __func__));
+
+ valid = 0;
+ for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) {
+ r88e_iq_calib_run(sc, n, tx[n], rx[n], &vals);
+
+ if (n == 0)
+ continue;
+
+ /* Valid results remain stable after consecutive runs. */
+ valid = r88e_iq_calib_compare_results(sc, tx[n - 1],
+ rx[n - 1], tx[n], rx[n]);
+ if (valid)
+ break;
+ }
+
+ if (valid)
+ r88e_iq_calib_write_results(sc, tx[n], rx[n]);
}
+#undef RTWN_IQ_CAL_NRUN
void
r88e_temp_measure(struct rtwn_softc *sc)
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c
index ddc9d0a4..ff48d244 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_fw.c
@@ -111,7 +111,11 @@ r88e_fw_reset(struct rtwn_softc *sc, int reason)
reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
- rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN);
+
+ if (reason != RTWN_FW_RESET_SHUTDOWN) {
+ rtwn_write_2(sc, R92C_SYS_FUNC_EN,
+ reg | R92C_SYS_FUNC_EN_CPUEN);
+ }
}
void
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c
index 5225c43f..8c5bbac2 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_init.c
@@ -72,20 +72,8 @@ r88e_crystalcap_write(struct rtwn_softc *sc)
}
void
-r88e_init_bb(struct rtwn_softc *sc)
+r88e_init_bb_common(struct rtwn_softc *sc)
{
-
- /* Enable BB and RF. */
- rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
- R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
- R92C_SYS_FUNC_EN_DIO_RF);
-
- rtwn_write_1(sc, R92C_RF_CTRL,
- R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
- rtwn_write_1(sc, R92C_SYS_FUNC_EN,
- R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
- R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
-
r92c_init_bb_common(sc);
rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422);
@@ -95,66 +83,3 @@ r88e_init_bb(struct rtwn_softc *sc)
r88e_crystalcap_write(sc);
}
-
-int
-r88e_power_on(struct rtwn_softc *sc)
-{
-#define RTWN_CHK(res) do { \
- if (res != 0) \
- return (EIO); \
-} while(0)
- int ntries;
-
- /* Wait for power ready bit. */
- for (ntries = 0; ntries < 5000; ntries++) {
- if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
- break;
- rtwn_delay(sc, 10);
- }
- if (ntries == 5000) {
- device_printf(sc->sc_dev,
- "timeout waiting for chip power up\n");
- return (ETIMEDOUT);
- }
-
- /* Reset BB. */
- RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN,
- R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0));
-
- RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80));
-
- /* Disable HWPDN. */
- RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
- R92C_APS_FSMCO_APDM_HPDN, 0, 1));
-
- /* Disable WL suspend. */
- RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
- R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
-
- RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
- 0, R92C_APS_FSMCO_APFM_ONMAC, 1));
- for (ntries = 0; ntries < 5000; ntries++) {
- if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
- R92C_APS_FSMCO_APFM_ONMAC))
- break;
- rtwn_delay(sc, 10);
- }
- if (ntries == 5000)
- return (ETIMEDOUT);
-
- /* Enable LDO normal mode. */
- RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL,
- R92C_LPLDO_CTRL_SLEEP, 0));
-
- /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
- RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0));
- RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
- R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
- R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
- R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
- ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
- R92C_CR_CALTMR_EN));
-
- return (0);
-#undef RTWN_CHK
-}
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h
index 28f4b1fb..8ec5502d 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_priv.h
@@ -37,7 +37,7 @@ struct rtwn_r88e_txpwr {
/*
* MAC initialization values.
*/
-static const struct rtwn_mac_prog rtl8188eu_mac[] = {
+static const struct rtwn_mac_prog rtl8188e_mac[] = {
{ 0x026, 0x41 }, { 0x027, 0x35 }, { 0x040, 0x00 }, { 0x428, 0x0a },
{ 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x01 }, { 0x432, 0x02 },
{ 0x433, 0x04 }, { 0x434, 0x05 }, { 0x435, 0x06 }, { 0x436, 0x07 },
@@ -66,7 +66,7 @@ static const struct rtwn_mac_prog rtl8188eu_mac[] = {
/*
* Baseband initialization values.
*/
-static const uint16_t rtl8188eu_bb_regs[] = {
+static const uint16_t rtl8188e_bb_regs[] = {
0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c,
0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c,
0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c,
@@ -93,7 +93,7 @@ static const uint16_t rtl8188eu_bb_regs[] = {
0xed8, 0xedc, 0xee0, 0xee8, 0xeec, 0xf14, 0xf4c, 0xf00
};
-static const uint32_t rtl8188eu_bb_vals[] = {
+static const uint32_t rtl8188e_bb_vals[] = {
0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331,
0x020c3d10, 0x02200385, 0x00000000, 0x01000100, 0x00390204,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -135,17 +135,17 @@ static const uint32_t rtl8188eu_bb_vals[] = {
0x00000000, 0x00000300
};
-static const struct rtwn_bb_prog rtl8188eu_bb[] = {
+static const struct rtwn_bb_prog rtl8188e_bb[] = {
{
- nitems(rtl8188eu_bb_regs),
- rtl8188eu_bb_regs,
- rtl8188eu_bb_vals,
+ nitems(rtl8188e_bb_regs),
+ rtl8188e_bb_regs,
+ rtl8188e_bb_vals,
{ 0 },
NULL
}
};
-static const uint32_t rtl8188eu_agc_vals[] = {
+static const uint32_t rtl8188e_agc_vals[] = {
0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001,
0xfb050001, 0xfa060001, 0xf9070001, 0xf8080001, 0xf7090001,
0xf60a0001, 0xf50b0001, 0xf40c0001, 0xf30d0001, 0xf20e0001,
@@ -174,10 +174,10 @@ static const uint32_t rtl8188eu_agc_vals[] = {
0x407d0001, 0x407e0001, 0x407f0001
};
-static const struct rtwn_agc_prog rtl8188eu_agc[] = {
+static const struct rtwn_agc_prog rtl8188e_agc[] = {
{
- nitems(rtl8188eu_agc_vals),
- rtl8188eu_agc_vals,
+ nitems(rtl8188e_agc_vals),
+ rtl8188e_agc_vals,
{ 0 },
NULL
}
@@ -186,7 +186,7 @@ static const struct rtwn_agc_prog rtl8188eu_agc[] = {
/*
* RF initialization values.
*/
-static const uint8_t rtl8188eu_rf_regs[] = {
+static const uint8_t rtl8188e_rf_regs[] = {
0x00, 0x08, 0x18, 0x19, 0x1e, 0x1f, 0x2f, 0x3f, 0x42, 0x57,
0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 0xb6, 0xb7, 0xb8,
0xb9, 0xba, 0xbb, 0xbf, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
@@ -199,7 +199,7 @@ static const uint8_t rtl8188eu_rf_regs[] = {
0x1f, 0xfe, 0xfe, 0x1e, 0x1f, 0x00
};
-static const uint32_t rtl8188eu_rf_vals[] = {
+static const uint32_t rtl8188e_rf_vals[] = {
0x30000, 0x84000, 0x00407, 0x00012, 0x80009, 0x00880, 0x1a060,
0x00000, 0x060c0, 0xd0000, 0xbe180, 0x01552, 0x00000, 0xff8fc,
0x54400, 0xccc19, 0x43003, 0x4953e, 0x1c718, 0x060ff, 0x80001,
@@ -216,11 +216,11 @@ static const uint32_t rtl8188eu_rf_vals[] = {
0x0c350, 0x0c350, 0x00001, 0x80000, 0x33e60
};
-static const struct rtwn_rf_prog rtl8188eu_rf[] = {
+static const struct rtwn_rf_prog rtl8188e_rf[] = {
{
- nitems(rtl8188eu_rf_regs),
- rtl8188eu_rf_regs,
- rtl8188eu_rf_vals,
+ nitems(rtl8188e_rf_regs),
+ rtl8188e_rf_regs,
+ rtl8188e_rf_vals,
{ 0 },
NULL
},
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h
index f6f26fa4..94b9a660 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_reg.h
@@ -32,6 +32,7 @@
#define R88E_HISR 0x0b4
#define R88E_HIMRE 0x0b8
#define R88E_HISRE 0x0bc
+#define R88E_XCK_OUT_CTRL 0x07c
/* MAC General Configuration. */
#define R88E_32K_CTRL 0x194
#define R88E_HMEBOX_EXT(idx) (0x1f0 + (idx) * 4)
@@ -45,16 +46,49 @@
/* Bits for R88E_HIMR. */
-#define R88E_HIMR_CPWM 0x00000100
-#define R88E_HIMR_CPWM2 0x00000200
-#define R88E_HIMR_TBDER 0x04000000
-#define R88E_HIMR_PSTIMEOUT 0x20000000
+#define R88E_HIMR_ROK 0x00000001 /* receive DMA OK */
+#define R88E_HIMR_RDU 0x00000002 /* Rx descriptor unavailable */
+#define R88E_HIMR_VODOK 0x00000004 /* AC_VO DMA OK */
+#define R88E_HIMR_VIDOK 0x00000008 /* AC_VI DMA OK */
+#define R88E_HIMR_BEDOK 0x00000010 /* AC_BE DMA OK */
+#define R88E_HIMR_BKDOK 0x00000020 /* AC_BK DMA OK */
+#define R88E_HIMR_MGNTDOK 0x00000040 /* management queue DMA OK */
+#define R88E_HIMR_HIGHDOK 0x00000080 /* high queue DMA OK */
+#define R88E_HIMR_CPWM 0x00000100 /* CPU power mode intr 1 */
+#define R88E_HIMR_CPWM2 0x00000200 /* CPU power mode intr 2 */
+#define R88E_HIMR_C2HCMD 0x00000400 /* C2H command interrupt */
+#define R88E_HIMR_HISR 0x00000800 /* (HISR & HIMR) != 0 */
+#define R88E_HIMR_ATIMEND 0x00001000 /* ATIM window end interrupt */
+#define R88E_HIMR_HSISR 0x00008000 /* (HSIMR & HSISR) != 0 */
+#define R88E_HIMR_BCNDERR 0x00010000 /* beacon queue DMA error */
+#define R88E_HIMR_BCNINT 0x00100000 /* beacon DMA interrupt 0 */
+#define R88E_HIMR_TSF32 0x01000000 /* TSF 32 bit interrupt */
+#define R88E_HIMR_TBDOK 0x02000000 /* beacon transmit OK */
+#define R88E_HIMR_TBDER 0x04000000 /* beacon transmit error */
+#define R88E_HIMR_GTIMER3 0x08000000 /* GTIMER3 interrupt */
+#define R88E_HIMR_GTIMER4 0x10000000 /* GTIMER4 interrupt */
+#define R88E_HIMR_PSTIMEOUT 0x20000000 /* powersave timeout */
+#define R88E_HIMR_TXRPT 0x40000000 /* Tx report interrupt */
/* Bits for R88E_HIMRE.*/
-#define R88E_HIMRE_RXFOVW 0x00000100
-#define R88E_HIMRE_TXFOVW 0x00000200
-#define R88E_HIMRE_RXERR 0x00000400
-#define R88E_HIMRE_TXERR 0x00000800
+#define R88E_HIMRE_RXFOVW 0x00000100 /* receive FIFO overflow */
+#define R88E_HIMRE_TXFOVW 0x00000200 /* transmit FIFO overflow */
+#define R88E_HIMRE_RXERR 0x00000400 /* receive error */
+#define R88E_HIMRE_TXERR 0x00000800 /* transmit error */
+#define R88E_HIMRE_BCNDOK1 0x00004000 /* beacon queue DMA OK (1) */
+#define R88E_HIMRE_BCNDOK2 0x00008000 /* beacon queue DMA OK (2) */
+#define R88E_HIMRE_BCNDOK3 0x00010000 /* beacon queue DMA OK (3) */
+#define R88E_HIMRE_BCNDOK4 0x00020000 /* beacon queue DMA OK (4) */
+#define R88E_HIMRE_BCNDOK5 0x00040000 /* beacon queue DMA OK (5) */
+#define R88E_HIMRE_BCNDOK6 0x00080000 /* beacon queue DMA OK (6) */
+#define R88E_HIMRE_BCNDOK7 0x00100000 /* beacon queue DMA OK (7) */
+#define R88E_HIMRE_BCNDMAINT1 0x00200000 /* beacon DMA interrupt 1 */
+#define R88E_HIMRE_BCNDMAINT2 0x00400000 /* beacon DMA interrupt 2 */
+#define R88E_HIMRE_BCNDMAINT3 0x00800000 /* beacon DMA interrupt 3 */
+#define R88E_HIMRE_BCNDMAINT4 0x01000000 /* beacon DMA interrupt 4 */
+#define R88E_HIMRE_BCNDMAINT5 0x02000000 /* beacon DMA interrupt 5 */
+#define R88E_HIMRE_BCNDMAINT6 0x04000000 /* beacon DMA interrupt 6 */
+#define R88E_HIMRE_BCNDMAINT7 0x08000000 /* beacon DMA interrupt 7 */
/* Bits for R88E_TX_RPT_CTRL. */
#define R88E_TX_RPT1_ENA 0x01
@@ -79,6 +113,7 @@
* RF (6052) registers.
*/
#define R88E_RF_T_METER 0x42
+#define R88E_RF_WE_LUT 0xef
/* Bits for R92C_RF_CHNLBW. */
#define R88E_RF_CHNLBW_BW20 0x00c00
@@ -88,4 +123,7 @@
#define R88E_RF_T_METER_VAL_S 10
#define R88E_RF_T_METER_START 0x30000
+/* Bits for R88E_XCK_OUT_CTRL. */
+#define R88E_XCK_OUT_CTRL_EN 1
+
#endif /* R88E_REG_H */
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c
index e1337dba..3afa2910 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom.c
@@ -83,5 +83,6 @@ r88e_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
__func__,rs->regulatory);
sc->thermal_meter = rom->thermal_meter;
- IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
+
+ rtwn_r92c_set_rom_opts(sc, buf);
}
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h
index c80028e0..d5d97ffb 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rom_image.h
@@ -44,11 +44,24 @@ struct r88e_rom {
uint8_t reserved4[3];
uint8_t rf_ant_opt;
uint8_t reserved5[6];
- uint16_t vid;
- uint16_t pid;
- uint8_t usb_opt;
- uint8_t reserved6[2];
- uint8_t macaddr[IEEE80211_ADDR_LEN];
+
+ union {
+ struct {
+ uint16_t vid;
+ uint16_t pid;
+ uint8_t usb_opt;
+ uint8_t reserved6[2];
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
+ } __packed usb;
+
+ struct {
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
+ uint16_t vid;
+ uint16_t pid;
+ uint8_t reserved6[3];
+ } __packed pci;
+ } __packed diff_d0;
+
uint8_t reserved7[2];
uint8_t string[33]; /* "realtek 802.11n NIC" */
uint8_t reserved8[256];
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c
index 53cc722f..eee2f63f 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c
+++ b/freebsd/sys/dev/rtwn/rtl8188e/r88e_rx.c
@@ -58,6 +58,25 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/rtl8188e/r88e_rx_desc.h>
+int
+r88e_classify_intr(struct rtwn_softc *sc, void *buf, int len)
+{
+ struct r92c_rx_stat *stat = buf;
+ int report_sel = MS(le32toh(stat->rxdw3), R88E_RXDW3_RPT);
+
+ switch (report_sel) {
+ case R88E_RXDW3_RPT_RX:
+ return (RTWN_RX_DATA);
+ case R88E_RXDW3_RPT_TX1: /* per-packet Tx report */
+ case R88E_RXDW3_RPT_TX2: /* periodical Tx report */
+ return (RTWN_RX_TX_REPORT);
+ case R88E_RXDW3_RPT_HIS:
+ return (RTWN_RX_OTHER);
+ default: /* shut up the compiler */
+ return (RTWN_RX_DATA);
+ }
+}
+
void
r88e_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len)
{
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h
index 85b637cb..e79b1387 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h
+++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu.h
@@ -25,15 +25,21 @@
/*
+ * Global definitions.
+ */
+#define R88EU_PUBQ_NPAGES 142
+#define R88EU_TX_PAGE_COUNT 169
+
+
+/*
* Function declarations.
*/
/* r88eu_init.c */
+void r88eu_init_bb(struct rtwn_softc *);
+int r88eu_power_on(struct rtwn_softc *);
void r88eu_power_off(struct rtwn_softc *);
void r88eu_init_intr(struct rtwn_softc *);
void r88eu_init_rx_agg(struct rtwn_softc *);
void r88eu_post_init(struct rtwn_softc *);
-/* r88eu_rx.c */
-int r88eu_classify_intr(struct rtwn_softc *, void *, int);
-
#endif /* RTL8188EU_H */
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c
index 73cc7856..6b153bcd 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c
+++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h>
#include <dev/rtwn/rtl8188e/r88e_priv.h>
+#include <dev/rtwn/rtl8188e/r88e_rom_image.h> /* for 'macaddr' field */
#include <dev/rtwn/rtl8188e/usb/r88eu.h>
@@ -68,6 +69,14 @@ static struct rtwn_r88e_txpwr r88e_txpwr;
void r88eu_attach(struct rtwn_usb_softc *);
static void
+r88eu_set_macaddr(struct rtwn_softc *sc, uint8_t *buf)
+{
+ struct r88e_rom *rom = (struct r88e_rom *)buf;
+
+ IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->diff_d0.usb.macaddr);
+}
+
+static void
r88e_postattach(struct rtwn_softc *sc)
{
struct r92c_softc *rs = sc->sc_priv;
@@ -95,7 +104,7 @@ r88eu_attach_private(struct rtwn_softc *sc)
rs->rs_tx_enable_ampdu = r88e_tx_enable_ampdu;
rs->rs_tx_setup_hwseq = r88e_tx_setup_hwseq;
rs->rs_tx_setup_macid = r88e_tx_setup_macid;
- rs->rs_set_name = rtwn_nop_softc; /* not used */
+ rs->rs_set_rom_opts = r88eu_set_macaddr;
rs->rf_read_delay[0] = 10;
rs->rf_read_delay[1] = 100;
@@ -132,7 +141,7 @@ r88eu_attach(struct rtwn_usb_softc *uc)
sc->sc_get_rx_stats = r88e_get_rx_stats;
sc->sc_get_rssi_cck = r88e_get_rssi_cck;
sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm;
- sc->sc_classify_intr = r88eu_classify_intr;
+ sc->sc_classify_intr = r88e_classify_intr;
sc->sc_handle_tx_report = r88e_ratectl_tx_complete;
sc->sc_handle_c2h_report = r88e_handle_c2h_report;
sc->sc_check_frame = rtwn_nop_int_softc_mbuf;
@@ -142,7 +151,7 @@ r88eu_attach(struct rtwn_usb_softc *uc)
sc->sc_efuse_postread = rtwn_nop_softc;
sc->sc_parse_rom = r88e_parse_rom;
sc->sc_set_led = r88e_set_led;
- sc->sc_power_on = r88e_power_on;
+ sc->sc_power_on = r88eu_power_on;
sc->sc_power_off = r88eu_power_off;
#ifndef RTWN_WITHOUT_UCODE
sc->sc_fw_reset = r88e_fw_reset;
@@ -151,7 +160,7 @@ r88eu_attach(struct rtwn_usb_softc *uc)
sc->sc_llt_init = r92c_llt_init;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
- sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */
+ sc->sc_iq_calib = r88e_iq_calib;
sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32;
sc->sc_adj_devcaps = r88eu_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
@@ -174,29 +183,29 @@ r88eu_attach(struct rtwn_usb_softc *uc)
sc->sc_init_ampdu = rtwn_nop_softc;
sc->sc_init_intr = r88eu_init_intr;
sc->sc_init_edca = r92c_init_edca;
- sc->sc_init_bb = r88e_init_bb;
+ sc->sc_init_bb = r88eu_init_bb;
sc->sc_init_rf = r92c_init_rf;
sc->sc_init_antsel = rtwn_nop_softc;
sc->sc_post_init = r88eu_post_init;
sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc;
- sc->mac_prog = &rtl8188eu_mac[0];
- sc->mac_size = nitems(rtl8188eu_mac);
- sc->bb_prog = &rtl8188eu_bb[0];
- sc->bb_size = nitems(rtl8188eu_bb);
- sc->agc_prog = &rtl8188eu_agc[0];
- sc->agc_size = nitems(rtl8188eu_agc);
- sc->rf_prog = &rtl8188eu_rf[0];
+ sc->mac_prog = &rtl8188e_mac[0];
+ sc->mac_size = nitems(rtl8188e_mac);
+ sc->bb_prog = &rtl8188e_bb[0];
+ sc->bb_size = nitems(rtl8188e_bb);
+ sc->agc_prog = &rtl8188e_agc[0];
+ sc->agc_size = nitems(rtl8188e_agc);
+ sc->rf_prog = &rtl8188e_rf[0];
sc->name = "RTL8188EU";
sc->fwname = "rtwn-rtl8188eufw";
sc->fwsig = 0x88e;
- sc->page_count = R88E_TX_PAGE_COUNT;
+ sc->page_count = R88EU_TX_PAGE_COUNT;
sc->pktbuf_count = R88E_TXPKTBUF_COUNT;
sc->ackto = 0x40;
- sc->npubqpages = R88E_PUBQ_NPAGES;
+ sc->npubqpages = R88EU_PUBQ_NPAGES;
sc->page_size = R92C_TX_PAGE_SIZE;
sc->txdesc_len = sizeof(struct r92cu_tx_desc);
diff --git a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c
index 2c776671..bfe3681e 100644
--- a/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c
+++ b/freebsd/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c
@@ -57,6 +57,87 @@ __FBSDID("$FreeBSD$");
void
+r88eu_init_bb(struct rtwn_softc *sc)
+{
+
+ /* Enable BB and RF. */
+ rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0,
+ R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
+ R92C_SYS_FUNC_EN_DIO_RF);
+
+ rtwn_write_1(sc, R92C_RF_CTRL,
+ R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
+ rtwn_write_1(sc, R92C_SYS_FUNC_EN,
+ R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
+ R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
+
+ r88e_init_bb_common(sc);
+}
+
+int
+r88eu_power_on(struct rtwn_softc *sc)
+{
+#define RTWN_CHK(res) do { \
+ if (res != 0) \
+ return (EIO); \
+} while(0)
+ int ntries;
+
+ /* Wait for power ready bit. */
+ for (ntries = 0; ntries < 5000; ntries++) {
+ if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST)
+ break;
+ rtwn_delay(sc, 10);
+ }
+ if (ntries == 5000) {
+ device_printf(sc->sc_dev,
+ "timeout waiting for chip power up\n");
+ return (ETIMEDOUT);
+ }
+
+ /* Reset BB. */
+ RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN,
+ R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0));
+
+ RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80));
+
+ /* Disable HWPDN. */
+ RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
+ R92C_APS_FSMCO_APDM_HPDN, 0, 1));
+
+ /* Disable WL suspend. */
+ RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
+ R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1));
+
+ RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO,
+ 0, R92C_APS_FSMCO_APFM_ONMAC, 1));
+ for (ntries = 0; ntries < 5000; ntries++) {
+ if (!(rtwn_read_2(sc, R92C_APS_FSMCO) &
+ R92C_APS_FSMCO_APFM_ONMAC))
+ break;
+ rtwn_delay(sc, 10);
+ }
+ if (ntries == 5000)
+ return (ETIMEDOUT);
+
+ /* Enable LDO normal mode. */
+ RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL,
+ R92C_LPLDO_CTRL_SLEEP, 0));
+
+ /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
+ RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0));
+ RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0,
+ R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN |
+ R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN |
+ R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN |
+ ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) |
+ R92C_CR_CALTMR_EN));
+
+ return (0);
+#undef RTWN_CHK
+}
+
+void
r88eu_power_off(struct rtwn_softc *sc)
{
uint8_t reg;
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce.h b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce.h
index 93379f8b..5d13f160 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce.h
+++ b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce.h
@@ -60,7 +60,7 @@ void r92ce_post_init(struct rtwn_softc *);
void r92ce_set_led(struct rtwn_softc *, int, int);
/* r92ce_rx.c */
-int r92ce_classify_intr(struct rtwn_softc *, void *, int);
+int r92ce_get_intr_status(struct rtwn_pci_softc *, int *);
void r92ce_enable_intr(struct rtwn_pci_softc *);
void r92ce_start_xfers(struct rtwn_softc *);
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
index e43d3ac0..61791c41 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
@@ -94,7 +94,7 @@ r92ce_postattach(struct rtwn_softc *sc)
}
static void
-r92ce_set_name(struct rtwn_softc *sc)
+r92ce_set_name(struct rtwn_softc *sc, uint8_t *buf)
{
struct r92c_softc *rs = sc->sc_priv;
@@ -119,7 +119,7 @@ r92ce_attach_private(struct rtwn_softc *sc)
rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu;
rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq;
rs->rs_tx_setup_macid = r92c_tx_setup_macid;
- rs->rs_set_name = r92ce_set_name;
+ rs->rs_set_rom_opts = r92ce_set_name;
/* XXX TODO: test with net80211 ratectl! */
#ifndef RTWN_WITHOUT_UCODE
@@ -157,6 +157,7 @@ r92ce_attach(struct rtwn_pci_softc *pc)
pc->pc_tx_postsetup = r92ce_tx_postsetup;
pc->pc_copy_tx_desc = r92ce_copy_tx_desc;
pc->pc_enable_intr = r92ce_enable_intr;
+ pc->pc_get_intr_status = r92ce_get_intr_status;
pc->pc_qmap = 0xf771;
pc->tcr =
@@ -177,7 +178,7 @@ r92ce_attach(struct rtwn_pci_softc *pc)
sc->sc_get_rx_stats = r92c_get_rx_stats;
sc->sc_get_rssi_cck = r92c_get_rssi_cck;
sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm;
- sc->sc_classify_intr = r92ce_classify_intr;
+ sc->sc_classify_intr = r92c_classify_intr;
sc->sc_handle_tx_report = rtwn_nop_softc_uint8_int;
sc->sc_handle_c2h_report = rtwn_nop_softc_uint8_int;
sc->sc_check_frame = rtwn_nop_int_softc_mbuf;
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c
index 070f6e1d..f1cd42e8 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c
@@ -77,55 +77,58 @@ r92ce_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2],
uint16_t rx[2])
{
uint32_t status;
- int offset = chain * 0x20;
if (chain == 0) { /* IQ calibration for chain 0. */
/* IQ calibration settings for chain 0. */
- rtwn_bb_write(sc, 0xe30, 0x10008c1f);
- rtwn_bb_write(sc, 0xe34, 0x10008c1f);
- rtwn_bb_write(sc, 0xe38, 0x82140102);
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1f);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1f);
+ rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82140102);
if (sc->ntxchains > 1) {
- rtwn_bb_write(sc, 0xe3c, 0x28160202); /* 2T */
+ rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160202);
/* IQ calibration settings for chain 1. */
- rtwn_bb_write(sc, 0xe50, 0x10008c22);
- rtwn_bb_write(sc, 0xe54, 0x10008c22);
- rtwn_bb_write(sc, 0xe58, 0x82140102);
- rtwn_bb_write(sc, 0xe5c, 0x28160202);
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE(1), 0x10008c22);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE(1), 0x10008c22);
+ rtwn_bb_write(sc, R92C_TX_IQK_PI(1), 0x82140102);
+ rtwn_bb_write(sc, R92C_RX_IQK_PI(1), 0x28160202);
} else
- rtwn_bb_write(sc, 0xe3c, 0x28160502); /* 1T */
+ rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160502);
/* LO calibration settings. */
- rtwn_bb_write(sc, 0xe4c, 0x001028d1);
+ rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x001028d1);
/* We're doing LO and IQ calibration in one shot. */
- rtwn_bb_write(sc, 0xe48, 0xf9000000);
- rtwn_bb_write(sc, 0xe48, 0xf8000000);
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
} else { /* IQ calibration for chain 1. */
/* We're doing LO and IQ calibration in one shot. */
- rtwn_bb_write(sc, 0xe60, 0x00000002);
- rtwn_bb_write(sc, 0xe60, 0x00000000);
+ rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 2);
+ rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 0);
}
/* Give LO and IQ calibrations the time to complete. */
rtwn_delay(sc, 1000);
/* Read IQ calibration status. */
- status = rtwn_bb_read(sc, 0xeac);
+ status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0));
if (status & (1 << (28 + chain * 3)))
return (0); /* Tx failed. */
/* Read Tx IQ calibration results. */
- tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff;
- tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff;
+ tx[0] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(chain)),
+ R92C_POWER_IQK_RESULT);
+ tx[1] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(chain)),
+ R92C_POWER_IQK_RESULT);
if (tx[0] == 0x142 || tx[1] == 0x042)
return (0); /* Tx failed. */
if (status & (1 << (27 + chain * 3)))
return (1); /* Rx failed. */
/* Read Rx IQ calibration results. */
- rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff;
- rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff;
+ rx[0] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(chain)),
+ R92C_POWER_IQK_RESULT);
+ rx[1] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(chain)),
+ R92C_POWER_IQK_RESULT);
if (rx[0] == 0x132 || rx[1] == 0x036)
return (1); /* Rx failed. */
@@ -202,18 +205,18 @@ r92ce_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
if (sc->ntxchains > 1)
rtwn_bb_write(sc, 0x0b6c, 0x00080000);
- rtwn_bb_write(sc, 0x0e28, 0x80800000);
- rtwn_bb_write(sc, 0x0e40, 0x01007c00);
- rtwn_bb_write(sc, 0x0e44, 0x01004800);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
+ rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
+ rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
rtwn_bb_write(sc, 0x0b68, 0x00080000);
for (chain = 0; chain < sc->ntxchains; chain++) {
if (chain > 0) {
/* Put chain 0 on standby. */
- rtwn_bb_write(sc, 0x0e28, 0x00);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0);
rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
- rtwn_bb_write(sc, 0x0e28, 0x80800000);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
/* Enable chain 1. */
for (i = 0; i < nitems(reg_adda); i++)
@@ -259,7 +262,7 @@ r92ce_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
vals->fpga0_rfifacesw1);
rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar);
- rtwn_bb_write(sc, 0x0e28, 0x00);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0);
rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
if (sc->ntxchains > 1)
rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3);
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c
index 203b0bf8..0f65d1bf 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c
@@ -60,10 +60,10 @@ __FBSDID("$FreeBSD$");
int
-r92ce_classify_intr(struct rtwn_softc *sc, void *arg, int len __unused)
+r92ce_get_intr_status(struct rtwn_pci_softc *pc, int *rings)
{
+ struct rtwn_softc *sc = &pc->pc_sc;
uint32_t status;
- int *rings = arg;
int ret;
*rings = 0;
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h
index d8f7afc8..f215e34f 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c.h
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c.h
@@ -102,6 +102,7 @@ void r92c_efuse_postread(struct rtwn_softc *);
void r92c_parse_rom(struct rtwn_softc *, uint8_t *);
/* r92c_rx.c */
+int r92c_classify_intr(struct rtwn_softc *, void *, int);
int8_t r92c_get_rssi_cck(struct rtwn_softc *, void *);
int8_t r92c_get_rssi_ofdm(struct rtwn_softc *, void *);
uint8_t r92c_rx_radiotap_flags(const void *);
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_calib.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_calib.c
index 6c18a606..ebb4f5cf 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_calib.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_calib.c
@@ -48,16 +48,366 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/if_rtwnreg.h>
#include <dev/rtwn/if_rtwnvar.h>
+#include <dev/rtwn/if_rtwn_debug.h>
#include <dev/rtwn/rtl8192c/r92c.h>
#include <dev/rtwn/rtl8192c/r92c_reg.h>
+/* Registers to save and restore during IQ calibration. */
+struct r92c_iq_cal_reg_vals {
+ uint32_t adda[16];
+ uint8_t txpause;
+ uint8_t bcn_ctrl[2];
+ uint32_t gpio_muxcfg;
+ uint32_t cck0_afesetting;
+ uint32_t ofdm0_trxpathena;
+ uint32_t ofdm0_trmuxpar;
+ uint32_t fpga0_rfifacesw0;
+ uint32_t fpga0_rfifacesw1;
+ uint32_t fpga0_rfifaceoe0;
+ uint32_t fpga0_rfifaceoe1;
+ uint32_t config_ant0;
+ uint32_t config_ant1;
+};
+
+/* XXX TODO: merge */
+static int
+r92c_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2],
+ uint16_t rx[2])
+{
+ uint32_t status;
+
+ if (chain == 0) { /* IQ calibration for chain 0. */
+ /* IQ calibration settings for chain 0. */
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x10008c1f);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x10008c1f);
+ rtwn_bb_write(sc, R92C_TX_IQK_PI(0), 0x82140102);
+
+ if (sc->ntxchains > 1) {
+ rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160202);
+ /* IQ calibration settings for chain 1. */
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE(1), 0x10008c22);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE(1), 0x10008c22);
+ rtwn_bb_write(sc, R92C_TX_IQK_PI(1), 0x82140102);
+ rtwn_bb_write(sc, R92C_RX_IQK_PI(1), 0x28160202);
+ } else
+ rtwn_bb_write(sc, R92C_RX_IQK_PI(0), 0x28160502);
+
+ /* LO calibration settings. */
+ rtwn_bb_write(sc, R92C_IQK_AGC_RSP, 0x001028d1);
+ /* We're doing LO and IQ calibration in one shot. */
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf9000000);
+ rtwn_bb_write(sc, R92C_IQK_AGC_PTS, 0xf8000000);
+
+ } else { /* IQ calibration for chain 1. */
+ /* We're doing LO and IQ calibration in one shot. */
+ rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 2);
+ rtwn_bb_write(sc, R92C_IQK_AGC_CONT, 0);
+ }
+
+ /* Give LO and IQ calibrations the time to complete. */
+ rtwn_delay(sc, 10000);
+
+ /* Read IQ calibration status. */
+ status = rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(0));
+
+ if (status & (1 << (28 + chain * 3)))
+ return (0); /* Tx failed. */
+ /* Read Tx IQ calibration results. */
+ tx[0] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_BEFORE(chain)),
+ R92C_POWER_IQK_RESULT);
+ tx[1] = MS(rtwn_bb_read(sc, R92C_TX_POWER_IQK_AFTER(chain)),
+ R92C_POWER_IQK_RESULT);
+ if (tx[0] == 0x142 || tx[1] == 0x042)
+ return (0); /* Tx failed. */
+
+ if (status & (1 << (27 + chain * 3)))
+ return (1); /* Rx failed. */
+ /* Read Rx IQ calibration results. */
+ rx[0] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_BEFORE(chain)),
+ R92C_POWER_IQK_RESULT);
+ rx[1] = MS(rtwn_bb_read(sc, R92C_RX_POWER_IQK_AFTER(chain)),
+ R92C_POWER_IQK_RESULT);
+ if (rx[0] == 0x132 || rx[1] == 0x036)
+ return (1); /* Rx failed. */
+
+ return (3); /* Both Tx and Rx succeeded. */
+}
+
+static void
+r92c_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
+ uint16_t rx[2][2], struct r92c_iq_cal_reg_vals *vals)
+{
+ /* Registers to save and restore during IQ calibration. */
+ static const uint16_t reg_adda[16] = {
+ 0x85c, 0xe6c, 0xe70, 0xe74,
+ 0xe78, 0xe7c, 0xe80, 0xe84,
+ 0xe88, 0xe8c, 0xed0, 0xed4,
+ 0xed8, 0xedc, 0xee0, 0xeec
+ };
+ int i, chain;
+ uint32_t hssi_param1;
+
+ if (n == 0) {
+ for (i = 0; i < nitems(reg_adda); i++)
+ vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]);
+
+ vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE);
+ vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0));
+ vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1));
+ vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG);
+ }
+
+ if (sc->ntxchains == 1) {
+ rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0);
+ for (i = 1; i < nitems(reg_adda); i++)
+ rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0);
+ } else {
+ for (i = 0; i < nitems(reg_adda); i++)
+ rtwn_bb_write(sc, reg_adda[i], 0x04db25a4);
+ }
+
+ hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
+ if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
+ hssi_param1 | R92C_HSSI_PARAM1_PI);
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
+ hssi_param1 | R92C_HSSI_PARAM1_PI);
+ }
+
+ if (n == 0) {
+ vals->cck0_afesetting = rtwn_bb_read(sc, R92C_CCK0_AFESETTING);
+ vals->ofdm0_trxpathena =
+ rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA);
+ vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR);
+ vals->fpga0_rfifacesw0 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(0));
+ vals->fpga0_rfifacesw1 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1));
+ vals->fpga0_rfifaceoe0 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0));
+ vals->fpga0_rfifaceoe1 =
+ rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(1));
+ vals->config_ant0 = rtwn_bb_read(sc, R92C_CONFIG_ANT(0));
+ vals->config_ant1 = rtwn_bb_read(sc, R92C_CONFIG_ANT(1));
+ }
+
+ rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0, 0x0f000000);
+ rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
+ rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
+ rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(0), 0, 0x04000400);
+ rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(0), 0x400, 0);
+ rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(1), 0x400, 0);
+
+ if (sc->ntxchains > 1) {
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000);
+ }
+
+ rtwn_write_1(sc, R92C_TXPAUSE,
+ R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH);
+ rtwn_write_1(sc, R92C_BCN_CTRL(0),
+ vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN);
+ rtwn_write_1(sc, R92C_BCN_CTRL(1),
+ vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN);
+ rtwn_write_1(sc, R92C_GPIO_MUXCFG,
+ vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT);
+
+ rtwn_bb_write(sc, R92C_CONFIG_ANT(0), 0x00080000);
+ if (sc->ntxchains > 1)
+ rtwn_bb_write(sc, R92C_CONFIG_ANT(1), 0x00080000);
+
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
+ rtwn_bb_write(sc, R92C_TX_IQK, 0x01007c00);
+ rtwn_bb_write(sc, R92C_RX_IQK, 0x01004800);
+
+ for (chain = 0; chain < sc->ntxchains; chain++) {
+ if (chain > 0) {
+ /* Put chain 0 on standby. */
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0);
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0x80800000);
+
+ /* Enable chain 1. */
+ for (i = 0; i < nitems(reg_adda); i++)
+ rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4);
+ }
+
+ /* Run IQ calibration twice. */
+ for (i = 0; i < 2; i++) {
+ int ret;
+
+ ret = r92c_iq_calib_chain(sc, chain,
+ tx[chain], rx[chain]);
+ if (ret == 0) {
+ RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
+ "%s: chain %d: Tx failed.\n",
+ __func__, chain);
+ tx[chain][0] = 0xff;
+ tx[chain][1] = 0xff;
+ rx[chain][0] = 0xff;
+ rx[chain][1] = 0xff;
+ } else if (ret == 1) {
+ RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
+ "%s: chain %d: Rx failed.\n",
+ __func__, chain);
+ rx[chain][0] = 0xff;
+ rx[chain][1] = 0xff;
+ } else if (ret == 3) {
+ RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
+ "%s: chain %d: Both Tx and Rx "
+ "succeeded.\n", __func__, chain);
+ }
+ }
+
+ RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
+ "%s: results for run %d chain %d: tx[0] 0x%x, "
+ "tx[1] 0x%x, rx[0] 0x%x, rx[1] 0x%x\n", __func__, n, chain,
+ tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1]);
+ }
+
+ rtwn_bb_write(sc, R92C_CCK0_AFESETTING, vals->cck0_afesetting);
+ rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, vals->ofdm0_trxpathena);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(0), vals->fpga0_rfifacesw0);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), vals->fpga0_rfifacesw1);
+ rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(0), vals->fpga0_rfifaceoe0);
+ rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(1), vals->fpga0_rfifaceoe1);
+ rtwn_bb_write(sc, R92C_CONFIG_ANT(0), vals->config_ant0);
+ rtwn_bb_write(sc, R92C_CONFIG_ANT(1), vals->config_ant1);
+
+ rtwn_bb_write(sc, R92C_FPGA0_IQK, 0);
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
+ if (sc->ntxchains > 1)
+ rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3);
+
+ if (n != 0) {
+ if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1);
+ rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1);
+ }
+
+ for (i = 0; i < nitems(reg_adda); i++)
+ rtwn_bb_write(sc, reg_adda[i], vals->adda[i]);
+
+ rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause);
+ rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]);
+ rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]);
+ rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg);
+
+ rtwn_bb_write(sc, R92C_TX_IQK_TONE(0), 0x01008c00);
+ rtwn_bb_write(sc, R92C_RX_IQK_TONE(0), 0x01008c00);
+ }
+}
+
+#define RTWN_IQ_CAL_MAX_TOLERANCE 5
+static int
+r92c_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2][2],
+ uint16_t rx1[2][2], uint16_t tx2[2][2], uint16_t rx2[2][2])
+{
+ int chain, i, tx_ok[2], rx_ok[2];
+
+ tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0;
+ for (chain = 0; chain < sc->ntxchains; chain++) {
+ for (i = 0; i < 2; i++) {
+ if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff ||
+ rx1[chain][i] == 0xff || rx2[chain][i] == 0xff)
+ continue;
+
+ tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <=
+ RTWN_IQ_CAL_MAX_TOLERANCE);
+
+ rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <=
+ RTWN_IQ_CAL_MAX_TOLERANCE);
+ }
+ }
+
+ if (sc->ntxchains > 1)
+ return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]);
+ else
+ return (tx_ok[0] && rx_ok[0]);
+}
+#undef RTWN_IQ_CAL_MAX_TOLERANCE
+
+static void
+r92c_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2],
+ uint16_t rx[2], int chain)
+{
+ uint32_t reg, val, x;
+ long y, tx_c;
+
+ if (tx[0] == 0xff || tx[1] == 0xff)
+ return;
+
+ reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain));
+ val = ((reg >> 22) & 0x3ff);
+ x = tx[0];
+ if (x & 0x00000200)
+ x |= 0xfffffc00;
+ reg = (((x * val) >> 8) & 0x3ff);
+ rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x3ff, reg);
+ rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000,
+ ((x * val) & 0x80) << 24);
+
+ y = tx[1];
+ if (y & 0x00000200)
+ y |= 0xfffffc00;
+ tx_c = (y * val) >> 8;
+ rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(chain), 0xf0000000,
+ (tx_c & 0x3c0) << 22);
+ rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x003f0000,
+ (tx_c & 0x3f) << 16);
+ rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000,
+ ((y * val) & 0x80) << 22);
+
+ if (rx[0] == 0xff || rx[1] == 0xff)
+ return;
+
+ rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0x3ff,
+ rx[0] & 0x3ff);
+ rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0xfc00,
+ (rx[1] & 0x3f) << 10);
+
+ if (chain == 0) {
+ rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000,
+ (rx[1] & 0x3c0) << 22);
+ } else {
+ rtwn_bb_setbits(sc, R92C_OFDM0_AGCRSSITABLE, 0xf000,
+ (rx[1] & 0x3c0) << 6);
+ }
+}
+
+#define RTWN_IQ_CAL_NRUN 3
void
r92c_iq_calib(struct rtwn_softc *sc)
{
- /* XXX TODO */
+ struct r92c_iq_cal_reg_vals vals;
+ uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2];
+ int n, valid;
+
+ valid = 0;
+ for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) {
+ r92c_iq_calib_run(sc, n, tx[n], rx[n], &vals);
+
+ if (n == 0)
+ continue;
+
+ /* Valid results remain stable after consecutive runs. */
+ valid = r92c_iq_calib_compare_results(sc, tx[n - 1],
+ rx[n - 1], tx[n], rx[n]);
+ if (valid)
+ break;
+ }
+
+ if (valid) {
+ r92c_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0);
+ if (sc->ntxchains > 1)
+ r92c_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1);
+ }
}
+#undef RTWN_IQ_CAL_NRUN
void
r92c_lc_calib(struct rtwn_softc *sc)
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c
index 199a419f..8cd55fbf 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_init.c
@@ -324,6 +324,7 @@ r92c_init_antsel(struct rtwn_softc *sc)
rtwn_bb_setbits(sc, R92C_FPGA0_RFPARAM(0), 0, 0x2000);
reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0));
sc->sc_ant = MS(reg, R92C_FPGA0_RFIFACEOE0_ANT); /* XXX */
+ rtwn_setbits_1(sc, R92C_LEDCFG2, 0x80, 0);
}
void
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h
index 34a4b80c..c3def33e 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_reg.h
@@ -66,6 +66,7 @@
#define R92C_HSIMR 0x058
#define R92C_HSISR 0x05c
#define R92C_MULTI_FUNC_CTRL 0x068
+#define R92C_AFE_XTAL_CTRL_EXT 0x078
#define R92C_LDO_SWR_CTRL 0x07c
#define R92C_MCUFWDL 0x080
#define R92C_HMEBOX_EXT(idx) (0x088 + (idx) * 2)
@@ -147,6 +148,7 @@
#define R92C_RD_RESP_PKT_TH 0x463
#define R92C_INIRTS_RATE_SEL 0x480
#define R92C_INIDATA_RATE_SEL(macid) (0x484 + (macid))
+#define R92C_POWER_STATUS 0x4a4
#define R92C_QUEUE_CTRL 0x4c6
#define R92C_MAX_AGGR_NUM 0x4ca
#define R92C_BAR_MODE_CTRL 0x4cc
@@ -347,6 +349,7 @@
/* Bits for R92C_GPIO_MUXCFG. */
#define R92C_GPIO_MUXCFG_ENBT 0x0020
+#define R92C_GPIO_MUXCFG_ENSIC 0x1000
/* Bits for R92C_LEDCFG0. */
#define R92C_LEDCFG0_DIS 0x08
@@ -691,6 +694,7 @@
#define R92C_FPGA1_TXINFO 0x90c
#define R92C_CCK0_SYSTEM 0xa00
#define R92C_CCK0_AFESETTING 0xa04
+#define R92C_CONFIG_ANT(chain) (0xb68 + (chain) * 4)
#define R92C_OFDM0_TRXPATHENA 0xc04
#define R92C_OFDM0_TRMUXPAR 0xc08
#define R92C_OFDM0_RXIQIMBALANCE(chain) (0xc14 + (chain) * 8)
@@ -703,6 +707,20 @@
#define R92C_OFDM0_RXIQEXTANTA 0xca0
#define R92C_OFDM0_TXPSEUDONOISEWGT 0xce4
#define R92C_OFDM1_LSTF 0xd00
+#define R92C_FPGA0_IQK 0xe28
+#define R92C_TX_IQK_TONE(chain) (0xe30 + (chain) * 32)
+#define R92C_RX_IQK_TONE(chain) (0xe34 + (chain) * 32)
+#define R92C_TX_IQK_PI(chain) (0xe38 + (chain) * 32)
+#define R92C_RX_IQK_PI(chain) (0xe3c + (chain) * 32)
+#define R92C_TX_IQK 0xe40
+#define R92C_RX_IQK 0xe44
+#define R92C_IQK_AGC_PTS 0xe48
+#define R92C_IQK_AGC_RSP 0xe4c
+#define R92C_IQK_AGC_CONT 0xe60
+#define R92C_TX_POWER_IQK_BEFORE(chain) (0xe94 + (chain) * 32)
+#define R92C_TX_POWER_IQK_AFTER(chain) (0xe9c + (chain) * 32)
+#define R92C_RX_POWER_IQK_BEFORE(chain) (0xea4 + (chain) * 32)
+#define R92C_RX_POWER_IQK_AFTER(chain) (0xeac + (chain) * 32)
/* Bits for R92C_FPGA[01]_RFMOD. */
#define R92C_RFMOD_40MHZ 0x00000001
@@ -828,6 +846,10 @@
#define R92C_OFDM0_AGCCORE1_GAIN_M 0x0000007f
#define R92C_OFDM0_AGCCORE1_GAIN_S 0
+/* Bits for R92C_[RT]X_POWER_IQK*. */
+#define R92C_POWER_IQK_RESULT_S 16
+#define R92C_POWER_IQK_RESULT_M 0x03ff0000
+
/*
* RF (6052) registers.
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c
index 1eb5ca12..bc355e30 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rom.c
@@ -98,7 +98,7 @@ r92c_parse_rom(struct rtwn_softc *sc, uint8_t *buf)
__func__, rs->regulatory);
/* Need to be set before postinit() (but after preinit()). */
- rtwn_r92c_set_name(sc);
+ rtwn_r92c_set_rom_opts(sc, buf);
r92c_set_chains(sc);
for (j = 0; j < R92C_GROUP_2G; j++) {
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c
index c98a0203..cbc8eb56 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_rx.c
@@ -54,6 +54,13 @@ __FBSDID("$FreeBSD$");
#include <dev/rtwn/rtl8192c/r92c_rx_desc.h>
+int
+r92c_classify_intr(struct rtwn_softc *sc, void *buf, int len)
+{
+ /* NB: reports are fetched from C2H_MSG register. */
+ return (RTWN_RX_DATA);
+}
+
int8_t
r92c_get_rssi_cck(struct rtwn_softc *sc, void *physt)
{
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c
index 5c80af90..36450e80 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_tx.c
@@ -105,7 +105,7 @@ r92c_tx_protection(struct rtwn_softc *sc, struct r92c_tx_desc *txd,
rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx);
else
rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]);
- ridx = rate2ridx(rate);
+ ridx = rate2ridx(IEEE80211_RV(rate));
txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, ridx));
/* RTS rate fallback limit (max). */
@@ -213,6 +213,12 @@ r92c_tx_setup_macid(void *buf, int id)
struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf;
txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, id));
+
+ /* XXX does not belong here */
+ /* XXX temporary (I hope) */
+ /* Force CCK1 for RTS / CTS frames (driver bug) */
+ txd->txdw4 &= ~htole32(SM(R92C_TXDW4_RTSRATE, R92C_TXDW4_RTSRATE_M));
+ txd->txdw4 &= ~htole32(R92C_TXDW4_RTS_SHORT);
}
void
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h b/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h
index 79592449..2b35ccea 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h
+++ b/freebsd/sys/dev/rtwn/rtl8192c/r92c_var.h
@@ -58,7 +58,7 @@ struct r92c_softc {
void (*rs_tx_enable_ampdu)(void *, int);
void (*rs_tx_setup_hwseq)(void *);
void (*rs_tx_setup_macid)(void *, int);
- void (*rs_set_name)(struct rtwn_softc *);
+ void (*rs_set_rom_opts)(struct rtwn_softc *, uint8_t *);
int rf_read_delay[3];
uint32_t rf_chnlbw[R92C_MAX_CHAINS];
@@ -77,7 +77,7 @@ struct r92c_softc {
((R92C_SOFTC(_sc)->rs_tx_setup_hwseq)((_buf)))
#define rtwn_r92c_tx_setup_macid(_sc, _buf, _id) \
((R92C_SOFTC(_sc)->rs_tx_setup_macid)((_buf), (_id)))
-#define rtwn_r92c_set_name(_sc) \
- ((R92C_SOFTC(_sc)->rs_set_name)((_sc)))
+#define rtwn_r92c_set_rom_opts(_sc, _buf) \
+ ((R92C_SOFTC(_sc)->rs_set_rom_opts)((_sc), (_buf)))
#endif /* R92C_VAR_H */
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu.h b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu.h
index 2486d7fa..4cc01049 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu.h
+++ b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu.h
@@ -47,7 +47,6 @@ void r92cu_post_init(struct rtwn_softc *);
void r92cu_set_led(struct rtwn_softc *, int, int);
/* r92cu_rx.c */
-int r92cu_classify_intr(struct rtwn_softc *, void *, int);
int r92cu_align_rx(int, int);
/* r92cu_tx.c */
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c
index 4696e8c4..c8270184 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c
@@ -96,7 +96,7 @@ r92cu_postattach(struct rtwn_softc *sc)
}
static void
-r92cu_set_name(struct rtwn_softc *sc)
+r92cu_set_name(struct rtwn_softc *sc, uint8_t *buf)
{
struct r92c_softc *rs = sc->sc_priv;
@@ -126,7 +126,7 @@ r92cu_attach_private(struct rtwn_softc *sc)
rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu;
rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq;
rs->rs_tx_setup_macid = r92c_tx_setup_macid;
- rs->rs_set_name = r92cu_set_name;
+ rs->rs_set_rom_opts = r92cu_set_name;
#ifndef RTWN_WITHOUT_UCODE
rs->rs_c2h_timeout = hz;
@@ -170,7 +170,7 @@ r92cu_attach(struct rtwn_usb_softc *uc)
sc->sc_get_rx_stats = r92c_get_rx_stats;
sc->sc_get_rssi_cck = r92c_get_rssi_cck;
sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm;
- sc->sc_classify_intr = r92cu_classify_intr;
+ sc->sc_classify_intr = r92c_classify_intr;
sc->sc_handle_tx_report = rtwn_nop_softc_uint8_int;
sc->sc_handle_c2h_report = rtwn_nop_softc_uint8_int;
sc->sc_check_frame = rtwn_nop_int_softc_mbuf;
@@ -189,7 +189,7 @@ r92cu_attach(struct rtwn_usb_softc *uc)
sc->sc_llt_init = r92c_llt_init;
sc->sc_set_page_size = r92c_set_page_size;
sc->sc_lc_calib = r92c_lc_calib;
- sc->sc_iq_calib = r92c_iq_calib; /* XXX TODO */
+ sc->sc_iq_calib = r92c_iq_calib;
sc->sc_read_chipid_vendor = r92c_read_chipid_vendor;
sc->sc_adj_devcaps = r92cu_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c
index 61dd1aa0..08259875 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c
@@ -359,6 +359,8 @@ void
r92cu_post_init(struct rtwn_softc *sc)
{
+ rtwn_write_4(sc, R92C_POWER_STATUS, 0x5);
+
/* Perform LO and IQ calibrations. */
r92c_iq_calib(sc);
/* Perform LC calibration. */
diff --git a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c
index 4d040a4e..8d8489c2 100644
--- a/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c
+++ b/freebsd/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c
@@ -52,13 +52,6 @@ __FBSDID("$FreeBSD$");
int
-r92cu_classify_intr(struct rtwn_softc *sc, void *buf, int len)
-{
- /* NB: reports are fetched from C2H_MSG register. */
- return (RTWN_RX_DATA);
-}
-
-int
r92cu_align_rx(int totlen, int len)
{
return (roundup2(totlen, 128));
diff --git a/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c
index ce1e49f4..f906d9fa 100644
--- a/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c
+++ b/freebsd/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c
@@ -137,7 +137,7 @@ r92eu_attach(struct rtwn_usb_softc *uc)
sc->sc_llt_init = r92e_llt_init;
sc->sc_set_page_size = rtwn_nop_int_softc;
sc->sc_lc_calib = r92c_lc_calib;
- sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */
+ sc->sc_iq_calib = rtwn_nop_softc; /* XXX TODO */
sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32;
sc->sc_adj_devcaps = r92eu_adj_devcaps;
sc->sc_vap_preattach = rtwn_nop_softc_vap;
diff --git a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c
index 77e9e423..910a06eb 100644
--- a/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c
+++ b/freebsd/sys/dev/rtwn/rtl8812a/r12a_tx.c
@@ -113,7 +113,7 @@ r12a_tx_protection(struct rtwn_softc *sc, struct r12a_tx_desc *txd,
rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx);
else
rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]);
- ridx = rate2ridx(rate);
+ ridx = rate2ridx(IEEE80211_RV(rate));
txd->txdw4 |= htole32(SM(R12A_TXDW4_RTSRATE, ridx));
/* RTS rate fallback limit (max). */
diff --git a/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h b/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h
index 432d7e97..c757cb79 100644
--- a/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h
+++ b/freebsd/sys/dev/rtwn/usb/rtwn_usb_attach.h
@@ -107,6 +107,7 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = {
{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8192EU) }
RTWN_RTL8192EU_DEV(DLINK, DWA131E1),
RTWN_RTL8192EU_DEV(REALTEK, RTL8192EU),
+ RTWN_RTL8192EU_DEV(TPLINK, WN821NV5),
RTWN_RTL8192EU_DEV(TPLINK, WN822NV4),
RTWN_RTL8192EU_DEV(TPLINK, WN823NV2),
#undef RTWN_RTL8192EU_DEV
@@ -155,7 +156,10 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = {
RTWN_RTL8821AU_DEV(EDIMAX, EW7811UTC_2),
RTWN_RTL8821AU_DEV(HAWKING, HD65U),
RTWN_RTL8821AU_DEV(MELCO, WIU2433DM),
- RTWN_RTL8821AU_DEV(NETGEAR, A6100)
+ RTWN_RTL8821AU_DEV(NETGEAR, A6100),
+ RTWN_RTL8821AU_DEV(REALTEK, RTL8821AU_1),
+ RTWN_RTL8821AU_DEV(REALTEK, RTL8821AU_2),
+ RTWN_RTL8821AU_DEV(TPLINK, T2UNANO)
#undef RTWN_RTL8821AU_DEV
};
diff --git a/freebsd/sys/dev/rtwn/usb/rtwn_usb_reg.c b/freebsd/sys/dev/rtwn/usb/rtwn_usb_reg.c
index 8225282e..c7cb255e 100644
--- a/freebsd/sys/dev/rtwn/usb/rtwn_usb_reg.c
+++ b/freebsd/sys/dev/rtwn/usb/rtwn_usb_reg.c
@@ -174,8 +174,6 @@ rtwn_usb_delay(struct rtwn_softc *sc, int usec)
/* 1ms delay as default is too big. */
if (usec < 1000)
DELAY(usec);
- else {
- usb_pause_mtx(&sc->sc_mtx,
- MAX(msecs_to_ticks(usec / 1000), 1));
- }
+ else
+ usb_pause_mtx(&sc->sc_mtx, msecs_to_ticks(usec / 1000));
}
diff --git a/freebsd/sys/dev/sdhci/fsl_sdhci.c b/freebsd/sys/dev/sdhci/fsl_sdhci.c
index 84665b41..be3d1de3 100644
--- a/freebsd/sys/dev/sdhci/fsl_sdhci.c
+++ b/freebsd/sys/dev/sdhci/fsl_sdhci.c
@@ -1016,7 +1016,7 @@ static driver_t fsl_sdhci_driver = {
DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhci_driver, fsl_sdhci_devclass,
NULL, NULL);
-MODULE_DEPEND(sdhci_fsl, sdhci, 1, 1, 1);
+SDHCI_DEPEND(sdhci_fsl);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_fsl);
diff --git a/freebsd/sys/dev/sdhci/sdhci.c b/freebsd/sys/dev/sdhci/sdhci.c
index 0bb9edc7..cf853360 100644
--- a/freebsd/sys/dev/sdhci/sdhci.c
+++ b/freebsd/sys/dev/sdhci/sdhci.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
+#include <sys/libkern.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
@@ -110,19 +111,20 @@ static void sdhci_retune(void *arg);
static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock);
static void sdhci_set_power(struct sdhci_slot *slot, u_char power);
static void sdhci_set_transfer_mode(struct sdhci_slot *slot,
- struct mmc_data *data);
+ const struct mmc_data *data);
static void sdhci_start(struct sdhci_slot *slot);
static void sdhci_timeout(void *arg);
static void sdhci_start_command(struct sdhci_slot *slot,
struct mmc_command *cmd);
-static void sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data);
+static void sdhci_start_data(struct sdhci_slot *slot,
+ const struct mmc_data *data);
static void sdhci_write_block_pio(struct sdhci_slot *slot);
static void sdhci_transfer_pio(struct sdhci_slot *slot);
#ifdef MMCCAM
/* CAM-related */
static void sdhci_cam_action(struct cam_sim *sim, union ccb *ccb);
-static int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot,
+static int sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot,
int proposed_clock);
static void sdhci_cam_handle_mmcio(struct cam_sim *sim, union ccb *ccb);
static void sdhci_cam_poll(struct cam_sim *sim);
@@ -132,12 +134,14 @@ static int sdhci_cam_update_ios(struct sdhci_slot *slot);
#endif
/* helper routines */
+static int sdhci_dma_alloc(struct sdhci_slot *slot);
+static void sdhci_dma_free(struct sdhci_slot *slot);
static void sdhci_dumpregs(struct sdhci_slot *slot);
static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs,
int error);
-static int slot_printf(struct sdhci_slot *slot, const char * fmt, ...)
+static int slot_printf(const struct sdhci_slot *slot, const char * fmt, ...)
__printflike(2, 3);
-static uint32_t sdhci_tuning_intmask(struct sdhci_slot *slot);
+static uint32_t sdhci_tuning_intmask(const struct sdhci_slot *slot);
#define SDHCI_LOCK(_slot) mtx_lock(&(_slot)->mtx)
#define SDHCI_UNLOCK(_slot) mtx_unlock(&(_slot)->mtx)
@@ -181,17 +185,22 @@ sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
}
static int
-slot_printf(struct sdhci_slot *slot, const char * fmt, ...)
+slot_printf(const struct sdhci_slot *slot, const char * fmt, ...)
{
+ char buf[128];
va_list ap;
int retval;
- retval = printf("%s-slot%d: ",
- device_get_nameunit(slot->bus), slot->num);
-
+ /*
+ * Make sure we print a single line all together rather than in two
+ * halves to avoid console gibberish bingo.
+ */
va_start(ap, fmt);
- retval += vprintf(fmt, ap);
+ retval = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
+
+ retval += printf("%s-slot%d: %s",
+ device_get_nameunit(slot->bus), slot->num, buf);
return (retval);
}
@@ -292,7 +301,7 @@ sdhci_reset(struct sdhci_slot *slot, uint8_t mask)
}
static uint32_t
-sdhci_tuning_intmask(struct sdhci_slot *slot)
+sdhci_tuning_intmask(const struct sdhci_slot *slot)
{
uint32_t intmask;
@@ -474,7 +483,7 @@ sdhci_set_power(struct sdhci_slot *slot, u_char power)
DELAY(100);
}
if (!(RD1(slot, SDHCI_POWER_CONTROL) & SDHCI_POWER_ON))
- slot_printf(slot, "Bus power failed to enable");
+ slot_printf(slot, "Bus power failed to enable\n");
if (slot->quirks & SDHCI_QUIRK_INTEL_POWER_UP_RESET) {
WR1(slot, SDHCI_POWER_CONTROL, pwr | 0x10);
@@ -494,7 +503,13 @@ sdhci_read_block_pio(struct sdhci_slot *slot)
buffer = slot->curcmd->data->data;
buffer += slot->offset;
/* Transfer one block at a time. */
- left = min(512, slot->curcmd->data->len - slot->offset);
+#ifdef MMCCAM
+ if (slot->curcmd->data->flags & MMC_DATA_BLOCK_SIZE)
+ left = min(slot->curcmd->data->block_size,
+ slot->curcmd->data->len - slot->offset);
+ else
+#endif
+ left = min(512, slot->curcmd->data->len - slot->offset);
slot->offset += left;
/* If we are too fast, broken controllers return zeroes. */
@@ -537,7 +552,13 @@ sdhci_write_block_pio(struct sdhci_slot *slot)
buffer = slot->curcmd->data->data;
buffer += slot->offset;
/* Transfer one block at a time. */
- left = min(512, slot->curcmd->data->len - slot->offset);
+#ifdef MMCCAM
+ if (slot->curcmd->data->flags & MMC_DATA_BLOCK_SIZE) {
+ left = min(slot->curcmd->data->block_size,
+ slot->curcmd->data->len - slot->offset);
+ } else
+#endif
+ left = min(512, slot->curcmd->data->len - slot->offset);
slot->offset += left;
/* Handle unaligned and aligned buffer cases. */
@@ -739,55 +760,94 @@ sdhci_card_poll(void *arg)
sdhci_card_poll, slot);
}
-int
-sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
+static int
+sdhci_dma_alloc(struct sdhci_slot *slot)
{
- kobjop_desc_t kobj_desc;
- kobj_method_t *kobj_method;
- uint32_t caps, caps2, freq, host_caps;
int err;
- SDHCI_LOCK_INIT(slot);
-
- slot->num = num;
- slot->bus = dev;
+ if (!(slot->quirks & SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY)) {
+ if (MAXPHYS <= 1024 * 4)
+ slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K;
+ else if (MAXPHYS <= 1024 * 8)
+ slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_8K;
+ else if (MAXPHYS <= 1024 * 16)
+ slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_16K;
+ else if (MAXPHYS <= 1024 * 32)
+ slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_32K;
+ else if (MAXPHYS <= 1024 * 64)
+ slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_64K;
+ else if (MAXPHYS <= 1024 * 128)
+ slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_128K;
+ else if (MAXPHYS <= 1024 * 256)
+ slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_256K;
+ else
+ slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_512K;
+ }
+ slot->sdma_bbufsz = SDHCI_SDMA_BNDRY_TO_BBUFSZ(slot->sdma_boundary);
- /* Allocate DMA tag. */
- err = bus_dma_tag_create(bus_get_dma_tag(dev),
- DMA_BLOCK_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
- BUS_SPACE_MAXADDR, NULL, NULL,
- DMA_BLOCK_SIZE, 1, DMA_BLOCK_SIZE,
- BUS_DMA_ALLOCNOW, NULL, NULL,
- &slot->dmatag);
+ /*
+ * Allocate the DMA tag for an SDMA bounce buffer.
+ * Note that the SDHCI specification doesn't state any alignment
+ * constraint for the SDMA system address. However, controllers
+ * typically ignore the SDMA boundary bits in SDHCI_DMA_ADDRESS when
+ * forming the actual address of data, requiring the SDMA buffer to
+ * be aligned to the SDMA boundary.
+ */
+ err = bus_dma_tag_create(bus_get_dma_tag(slot->bus), slot->sdma_bbufsz,
+ 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ slot->sdma_bbufsz, 1, slot->sdma_bbufsz, BUS_DMA_ALLOCNOW,
+ NULL, NULL, &slot->dmatag);
if (err != 0) {
- device_printf(dev, "Can't create DMA tag\n");
- SDHCI_LOCK_DESTROY(slot);
+ slot_printf(slot, "Can't create DMA tag for SDMA\n");
return (err);
}
- /* Allocate DMA memory. */
+ /* Allocate DMA memory for the SDMA bounce buffer. */
err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem,
BUS_DMA_NOWAIT, &slot->dmamap);
if (err != 0) {
- device_printf(dev, "Can't alloc DMA memory\n");
+ slot_printf(slot, "Can't alloc DMA memory for SDMA\n");
bus_dma_tag_destroy(slot->dmatag);
- SDHCI_LOCK_DESTROY(slot);
return (err);
}
- /* Map the memory. */
+ /* Map the memory of the SDMA bounce buffer. */
err = bus_dmamap_load(slot->dmatag, slot->dmamap,
- (void *)slot->dmamem, DMA_BLOCK_SIZE,
- sdhci_getaddr, &slot->paddr, 0);
+ (void *)slot->dmamem, slot->sdma_bbufsz, sdhci_getaddr,
+ &slot->paddr, 0);
if (err != 0 || slot->paddr == 0) {
- device_printf(dev, "Can't load DMA memory\n");
+ slot_printf(slot, "Can't load DMA memory for SDMA\n");
bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
- SDHCI_LOCK_DESTROY(slot);
if (err)
return (err);
else
return (EFAULT);
}
+ return (0);
+}
+
+static void
+sdhci_dma_free(struct sdhci_slot *slot)
+{
+
+ bus_dmamap_unload(slot->dmatag, slot->dmamap);
+ bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
+ bus_dma_tag_destroy(slot->dmatag);
+}
+
+int
+sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
+{
+ kobjop_desc_t kobj_desc;
+ kobj_method_t *kobj_method;
+ uint32_t caps, caps2, freq, host_caps;
+ int err;
+
+ SDHCI_LOCK_INIT(slot);
+
+ slot->num = num;
+ slot->bus = dev;
+
slot->version = (RD2(slot, SDHCI_HOST_VERSION)
>> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK;
if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) {
@@ -803,12 +863,8 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
if (slot->version >= SDHCI_SPEC_300) {
if ((caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_REMOVABLE &&
(caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_EMBEDDED) {
- device_printf(dev,
+ slot_printf(slot,
"Driver doesn't support shared bus slots\n");
- bus_dmamap_unload(slot->dmatag, slot->dmamap);
- bus_dmamem_free(slot->dmatag, slot->dmamem,
- slot->dmamap);
- bus_dma_tag_destroy(slot->dmatag);
SDHCI_LOCK_DESTROY(slot);
return (ENXIO);
} else if ((caps & SDHCI_SLOTTYPE_MASK) ==
@@ -832,7 +888,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
*/
if (slot->max_clk == 0) {
slot->max_clk = SDHCI_DEFAULT_MAX_FREQ * 1000000;
- device_printf(dev, "Hardware doesn't specify base clock "
+ slot_printf(slot, "Hardware doesn't specify base clock "
"frequency, using %dMHz as default.\n",
SDHCI_DEFAULT_MAX_FREQ);
}
@@ -853,7 +909,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
* max timeout, but still mention it.
*/
if (slot->timeout_clk == 0) {
- device_printf(dev, "Hardware doesn't specify timeout clock "
+ slot_printf(slot, "Hardware doesn't specify timeout clock "
"frequency, setting BROKEN_TIMEOUT quirk.\n");
slot->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
}
@@ -869,7 +925,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
if ((caps & SDHCI_CAN_VDD_180) && (slot->opt & SDHCI_SLOT_EMBEDDED))
slot->host.host_ocr |= MMC_OCR_LOW_VOLTAGE;
if (slot->host.host_ocr == 0) {
- device_printf(dev, "Hardware doesn't report any "
+ slot_printf(slot, "Hardware doesn't report any "
"support voltages.\n");
}
@@ -955,7 +1011,7 @@ no_tuning:
slot->retune_count = (caps2 & SDHCI_RETUNE_CNT_MASK) >>
SDHCI_RETUNE_CNT_SHIFT;
if (slot->retune_count > 0xb) {
- device_printf(dev, "Unknown re-tuning count "
+ slot_printf(slot, "Unknown re-tuning count "
"%x, using 1 sec\n", slot->retune_count);
slot->retune_count = 1;
} else if (slot->retune_count != 0)
@@ -1014,6 +1070,19 @@ no_tuning:
if (slot->opt & SDHCI_PLATFORM_TRANSFER)
slot->opt &= ~SDHCI_HAVE_DMA;
+ if (slot->opt & SDHCI_HAVE_DMA) {
+ err = sdhci_dma_alloc(slot);
+ if (err != 0) {
+ if (slot->opt & SDHCI_TUNING_SUPPORTED) {
+ free(slot->tune_req, M_DEVBUF);
+ free(slot->tune_cmd, M_DEVBUF);
+ free(slot->tune_data, M_DEVBUF);
+ }
+ SDHCI_LOCK_DESTROY(slot);
+ return (err);
+ }
+ }
+
if (bootverbose || sdhci_debug) {
slot_printf(slot,
"%uMHz%s %s VDD:%s%s%s VCCQ: 3.3V%s%s DRV: B%s%s%s %s %s\n",
@@ -1061,7 +1130,7 @@ no_tuning:
slot->timeout = 10;
SYSCTL_ADD_INT(device_get_sysctl_ctx(slot->bus),
SYSCTL_CHILDREN(device_get_sysctl_tree(slot->bus)), OID_AUTO,
- "timeout", CTLFLAG_RW, &slot->timeout, 0,
+ "timeout", CTLFLAG_RWTUN, &slot->timeout, 0,
"Maximum timeout for SDHCI transfers (in secs)");
TASK_INIT(&slot->card_task, 0, sdhci_card_task, slot);
TIMEOUT_TASK_INIT(taskqueue_swi_giant, &slot->card_delayed_task, 0,
@@ -1111,9 +1180,8 @@ sdhci_cleanup_slot(struct sdhci_slot *slot)
SDHCI_LOCK(slot);
sdhci_reset(slot, SDHCI_RESET_ALL);
SDHCI_UNLOCK(slot);
- bus_dmamap_unload(slot->dmatag, slot->dmamap);
- bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
- bus_dma_tag_destroy(slot->dmatag);
+ if (slot->opt & SDHCI_HAVE_DMA)
+ sdhci_dma_free(slot);
if (slot->opt & SDHCI_TUNING_SUPPORTED) {
free(slot->tune_req, M_DEVBUF);
free(slot->tune_cmd, M_DEVBUF);
@@ -1177,7 +1245,7 @@ sdhci_generic_get_card_present(device_t brdev __unused, struct sdhci_slot *slot)
void
sdhci_generic_set_uhs_timing(device_t brdev __unused, struct sdhci_slot *slot)
{
- struct mmc_ios *ios;
+ const struct mmc_ios *ios;
uint16_t hostctrl2;
if (slot->version < SDHCI_SPEC_300)
@@ -1310,7 +1378,7 @@ int
sdhci_generic_tune(device_t brdev __unused, device_t reqdev, bool hs400)
{
struct sdhci_slot *slot = device_get_ivars(reqdev);
- struct mmc_ios *ios = &slot->host.ios;
+ const struct mmc_ios *ios = &slot->host.ios;
struct mmc_command *tune_cmd;
struct mmc_data *tune_data;
uint32_t opcode;
@@ -1513,23 +1581,23 @@ sdhci_retune(void *arg)
static void
sdhci_req_done(struct sdhci_slot *slot)
{
- union ccb *ccb;
+ union ccb *ccb;
if (__predict_false(sdhci_debug > 1))
slot_printf(slot, "%s\n", __func__);
if (slot->ccb != NULL && slot->curcmd != NULL) {
callout_stop(&slot->timeout_callout);
- ccb = slot->ccb;
- slot->ccb = NULL;
+ ccb = slot->ccb;
+ slot->ccb = NULL;
slot->curcmd = NULL;
- /* Tell CAM the request is finished */
- struct ccb_mmcio *mmcio;
- mmcio = &ccb->mmcio;
+ /* Tell CAM the request is finished */
+ struct ccb_mmcio *mmcio;
+ mmcio = &ccb->mmcio;
- ccb->ccb_h.status =
- (mmcio->cmd.error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR);
- xpt_done(ccb);
+ ccb->ccb_h.status =
+ (mmcio->cmd.error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR);
+ xpt_done(ccb);
}
}
#else
@@ -1579,7 +1647,7 @@ sdhci_timeout(void *arg)
}
static void
-sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data)
+sdhci_set_transfer_mode(struct sdhci_slot *slot, const struct mmc_data *data)
{
uint16_t mode;
@@ -1587,9 +1655,9 @@ sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data)
return;
mode = SDHCI_TRNS_BLK_CNT_EN;
- if (data->len > 512) {
+ if (data->len > 512 || data->block_count > 1) {
mode |= SDHCI_TRNS_MULTI;
- if (__predict_true(
+ if (data->block_count == 0 && __predict_true(
#ifdef MMCCAM
slot->ccb->mmcio.stop.opcode == MMC_STOP_TRANSMISSION &&
#else
@@ -1714,7 +1782,9 @@ sdhci_start_command(struct sdhci_slot *slot, struct mmc_command *cmd)
/* Set data transfer mode. */
sdhci_set_transfer_mode(slot, cmd->data);
if (__predict_false(sdhci_debug > 1))
- slot_printf(slot, "Starting command!\n");
+ slot_printf(slot, "Starting command opcode %#04x flags %#04x\n",
+ cmd->opcode, flags);
+
/* Start command. */
WR2(slot, SDHCI_COMMAND_FLAGS, (cmd->opcode << 8) | (flags & 0xff));
/* Start timeout callout. */
@@ -1730,7 +1800,7 @@ sdhci_finish_command(struct sdhci_slot *slot)
uint8_t extra;
if (__predict_false(sdhci_debug > 1))
- slot_printf(slot, "%s: called, err %d flags %d\n",
+ slot_printf(slot, "%s: called, err %d flags %#04x\n",
__func__, slot->curcmd->error, slot->curcmd->flags);
slot->cmd_done = 1;
/*
@@ -1771,7 +1841,7 @@ sdhci_finish_command(struct sdhci_slot *slot)
slot->curcmd->resp[0] = RD4(slot, SDHCI_RESPONSE);
}
if (__predict_false(sdhci_debug > 1))
- printf("Resp: %02x %02x %02x %02x\n",
+ slot_printf(slot, "Resp: %#04x %#04x %#04x %#04x\n",
slot->curcmd->resp[0], slot->curcmd->resp[1],
slot->curcmd->resp[2], slot->curcmd->resp[3]);
@@ -1781,9 +1851,9 @@ sdhci_finish_command(struct sdhci_slot *slot)
}
static void
-sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
+sdhci_start_data(struct sdhci_slot *slot, const struct mmc_data *data)
{
- uint32_t target_timeout, current_timeout;
+ uint32_t blkcnt, blksz, current_timeout, sdma_bbufsz, target_timeout;
uint8_t div;
if (data == NULL && (slot->curcmd->flags & MMC_RSP_BUSY) == 0) {
@@ -1819,7 +1889,7 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
/* Use DMA if possible. */
if ((slot->opt & SDHCI_HAVE_DMA))
slot->flags |= SDHCI_USE_DMA;
- /* If data is small, broken DMA may return zeroes instead of data, */
+ /* If data is small, broken DMA may return zeroes instead of data. */
if ((slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) &&
(data->len <= 512))
slot->flags &= ~SDHCI_USE_DMA;
@@ -1829,20 +1899,22 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
slot->flags &= ~SDHCI_USE_DMA;
/* Load DMA buffer. */
if (slot->flags & SDHCI_USE_DMA) {
+ sdma_bbufsz = slot->sdma_bbufsz;
if (data->flags & MMC_DATA_READ)
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREREAD);
else {
- memcpy(slot->dmamem, data->data,
- (data->len < DMA_BLOCK_SIZE) ?
- data->len : DMA_BLOCK_SIZE);
+ memcpy(slot->dmamem, data->data, ulmin(data->len,
+ sdma_bbufsz));
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREWRITE);
}
WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr);
- /* Interrupt aggregation: Mask border interrupt
- * for the last page and unmask else. */
- if (data->len == DMA_BLOCK_SIZE)
+ /*
+ * Interrupt aggregation: Mask border interrupt for the last
+ * bounce buffer and unmask otherwise.
+ */
+ if (data->len == sdma_bbufsz)
slot->intmask &= ~SDHCI_INT_DMA_END;
else
slot->intmask |= SDHCI_INT_DMA_END;
@@ -1850,16 +1922,27 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
}
/* Current data offset for both PIO and DMA. */
slot->offset = 0;
- /* Set block size and request IRQ on 4K border. */
- WR2(slot, SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(DMA_BOUNDARY,
- (data->len < 512) ? data->len : 512));
- /* Set block count. */
- WR2(slot, SDHCI_BLOCK_COUNT, (data->len + 511) / 512);
+#ifdef MMCCAM
+ if (data->flags & MMC_DATA_BLOCK_SIZE) {
+ /* Set block size and request border interrupts on the SDMA boundary. */
+ blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, data->block_size);
+ blkcnt = data->block_count;
+ if (__predict_false(sdhci_debug > 0))
+ slot_printf(slot, "SDIO Custom block params: blksz: "
+ "%#10x, blk cnt: %#10x\n", blksz, blkcnt);
+ } else
+#endif
+ {
+ /* Set block size and request border interrupts on the SDMA boundary. */
+ blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, ulmin(data->len, 512));
+ blkcnt = howmany(data->len, 512);
+ }
+ WR2(slot, SDHCI_BLOCK_SIZE, blksz);
+ WR2(slot, SDHCI_BLOCK_COUNT, blkcnt);
if (__predict_false(sdhci_debug > 1))
- slot_printf(slot, "Block size: %02x, count %lu\n",
- (unsigned int)SDHCI_MAKE_BLKSZ(DMA_BOUNDARY, (data->len < 512) ? data->len : 512),
- (unsigned long)(data->len + 511) / 512);
+ slot_printf(slot, "Blk size: 0x%08x | Blk cnt: 0x%08x\n",
+ blksz, blkcnt);
}
void
@@ -1883,7 +1966,7 @@ sdhci_finish_data(struct sdhci_slot *slot)
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTREAD);
memcpy((u_char*)data->data + slot->offset, slot->dmamem,
- (left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE);
+ ulmin(left, slot->sdma_bbufsz));
} else
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTWRITE);
@@ -1907,15 +1990,14 @@ sdhci_finish_data(struct sdhci_slot *slot)
static void
sdhci_start(struct sdhci_slot *slot)
{
- union ccb *ccb;
+ union ccb *ccb;
+ struct ccb_mmcio *mmcio;
ccb = slot->ccb;
if (ccb == NULL)
return;
- struct ccb_mmcio *mmcio;
mmcio = &ccb->mmcio;
-
if (!(slot->flags & CMD_STARTED)) {
slot->flags |= CMD_STARTED;
sdhci_start_command(slot, &mmcio->cmd);
@@ -1947,7 +2029,7 @@ sdhci_start(struct sdhci_slot *slot)
static void
sdhci_start(struct sdhci_slot *slot)
{
- struct mmc_request *req;
+ const struct mmc_request *req;
req = slot->req;
if (req == NULL)
@@ -2076,6 +2158,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
{
struct mmc_data *data;
size_t left;
+ uint32_t sdma_bbufsz;
if (!slot->curcmd) {
slot_printf(slot, "Got data interrupt 0x%08x, but "
@@ -2130,6 +2213,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
/* Handle DMA border. */
if (intmask & SDHCI_INT_DMA_END) {
data = slot->curcmd->data;
+ sdma_bbufsz = slot->sdma_bbufsz;
/* Unload DMA buffer ... */
left = data->len - slot->offset;
@@ -2137,26 +2221,28 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTREAD);
memcpy((u_char*)data->data + slot->offset, slot->dmamem,
- (left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE);
+ ulmin(left, sdma_bbufsz));
} else {
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTWRITE);
}
/* ... and reload it again. */
- slot->offset += DMA_BLOCK_SIZE;
+ slot->offset += sdma_bbufsz;
left = data->len - slot->offset;
if (data->flags & MMC_DATA_READ) {
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREREAD);
} else {
memcpy(slot->dmamem, (u_char*)data->data + slot->offset,
- (left < DMA_BLOCK_SIZE)? left : DMA_BLOCK_SIZE);
+ ulmin(left, sdma_bbufsz));
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREWRITE);
}
- /* Interrupt aggregation: Mask border interrupt
- * for the last page. */
- if (left == DMA_BLOCK_SIZE) {
+ /*
+ * Interrupt aggregation: Mask border interrupt for the last
+ * bounce buffer.
+ */
+ if (left == sdma_bbufsz) {
slot->intmask &= ~SDHCI_INT_DMA_END;
WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask);
}
@@ -2279,7 +2365,7 @@ int
sdhci_generic_read_ivar(device_t bus, device_t child, int which,
uintptr_t *result)
{
- struct sdhci_slot *slot = device_get_ivars(child);
+ const struct sdhci_slot *slot = device_get_ivars(child);
switch (which) {
default:
@@ -2442,47 +2528,46 @@ sdhci_generic_write_ivar(device_t bus, device_t child, int which,
void
sdhci_start_slot(struct sdhci_slot *slot)
{
- if ((slot->devq = cam_simq_alloc(1)) == NULL) {
- goto fail;
- }
-
- mtx_init(&slot->sim_mtx, "sdhcisim", NULL, MTX_DEF);
- slot->sim = cam_sim_alloc(sdhci_cam_action, sdhci_cam_poll,
- "sdhci_slot", slot, device_get_unit(slot->bus),
- &slot->sim_mtx, 1, 1, slot->devq);
-
- if (slot->sim == NULL) {
- cam_simq_free(slot->devq);
- slot_printf(slot, "cannot allocate CAM SIM\n");
- goto fail;
- }
-
- mtx_lock(&slot->sim_mtx);
- if (xpt_bus_register(slot->sim, slot->bus, 0) != 0) {
- slot_printf(slot,
- "cannot register SCSI pass-through bus\n");
- cam_sim_free(slot->sim, FALSE);
- cam_simq_free(slot->devq);
- mtx_unlock(&slot->sim_mtx);
- goto fail;
- }
-
- mtx_unlock(&slot->sim_mtx);
- /* End CAM-specific init */
+
+ if ((slot->devq = cam_simq_alloc(1)) == NULL)
+ goto fail;
+
+ mtx_init(&slot->sim_mtx, "sdhcisim", NULL, MTX_DEF);
+ slot->sim = cam_sim_alloc_dev(sdhci_cam_action, sdhci_cam_poll,
+ "sdhci_slot", slot, slot->bus,
+ &slot->sim_mtx, 1, 1, slot->devq);
+
+ if (slot->sim == NULL) {
+ cam_simq_free(slot->devq);
+ slot_printf(slot, "cannot allocate CAM SIM\n");
+ goto fail;
+ }
+
+ mtx_lock(&slot->sim_mtx);
+ if (xpt_bus_register(slot->sim, slot->bus, 0) != 0) {
+ slot_printf(slot, "cannot register SCSI pass-through bus\n");
+ cam_sim_free(slot->sim, FALSE);
+ cam_simq_free(slot->devq);
+ mtx_unlock(&slot->sim_mtx);
+ goto fail;
+ }
+ mtx_unlock(&slot->sim_mtx);
+
+ /* End CAM-specific init */
slot->card_present = 0;
sdhci_card_task(slot, 0);
- return;
+ return;
fail:
- if (slot->sim != NULL) {
- mtx_lock(&slot->sim_mtx);
- xpt_bus_deregister(cam_sim_path(slot->sim));
- cam_sim_free(slot->sim, FALSE);
- mtx_unlock(&slot->sim_mtx);
- }
-
- if (slot->devq != NULL)
- cam_simq_free(slot->devq);
+ if (slot->sim != NULL) {
+ mtx_lock(&slot->sim_mtx);
+ xpt_bus_deregister(cam_sim_path(slot->sim));
+ cam_sim_free(slot->sim, FALSE);
+ mtx_unlock(&slot->sim_mtx);
+ }
+
+ if (slot->devq != NULL)
+ cam_simq_free(slot->devq);
}
static void
@@ -2541,6 +2626,7 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb)
case XPT_GET_TRAN_SETTINGS:
{
struct ccb_trans_settings *cts = &ccb->cts;
+ uint32_t max_data;
if (sdhci_debug > 1)
slot_printf(slot, "Got XPT_GET_TRAN_SETTINGS\n");
@@ -2554,6 +2640,19 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb)
cts->proto_specific.mmc.host_f_min = slot->host.f_min;
cts->proto_specific.mmc.host_f_max = slot->host.f_max;
cts->proto_specific.mmc.host_caps = slot->host.caps;
+ /*
+ * Re-tuning modes 1 and 2 restrict the maximum data length
+ * per read/write command to 4 MiB.
+ */
+ if (slot->opt & SDHCI_TUNING_ENABLED &&
+ (slot->retune_mode == SDHCI_RETUNE_MODE_1 ||
+ slot->retune_mode == SDHCI_RETUNE_MODE_2)) {
+ max_data = 4 * 1024 * 1024 / MMC_SECTOR_SIZE;
+ } else {
+ max_data = 65535;
+ }
+ cts->proto_specific.mmc.host_max_data = max_data;
+
memcpy(&cts->proto_specific.mmc.ios, &slot->host.ios, sizeof(struct mmc_ios));
ccb->ccb_h.status = CAM_REQ_CMP;
break;
@@ -2601,7 +2700,8 @@ sdhci_cam_poll(struct cam_sim *sim)
}
static int
-sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock)
+sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot,
+ int proposed_clock)
{
int max_clock, clock, i;
@@ -2611,15 +2711,13 @@ sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock)
clock = max_clock;
if (slot->version < SDHCI_SPEC_300) {
- for (i = 0; i < SDHCI_200_MAX_DIVIDER;
- i <<= 1) {
+ for (i = 0; i < SDHCI_200_MAX_DIVIDER; i <<= 1) {
if (clock <= proposed_clock)
break;
clock >>= 1;
}
} else {
- for (i = 0; i < SDHCI_300_MAX_DIVIDER;
- i += 2) {
+ for (i = 0; i < SDHCI_300_MAX_DIVIDER; i += 2) {
if (clock <= proposed_clock)
break;
clock = max_clock / (i + 2);
@@ -2628,15 +2726,14 @@ sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock)
return clock;
}
-int
+static int
sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb)
{
struct mmc_ios *ios;
- struct mmc_ios *new_ios;
- struct ccb_trans_settings_mmc *cts;
+ const struct mmc_ios *new_ios;
+ const struct ccb_trans_settings_mmc *cts;
ios = &slot->host.ios;
-
cts = &ccb->cts.proto_specific.mmc;
new_ios = &cts->ios;
@@ -2670,11 +2767,11 @@ sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb)
slot_printf(slot, "Bus mode => %d\n", ios->bus_mode);
}
- /* XXX Provide a way to call a chip-specific IOS update, required for TI */
+ /* XXX Provide a way to call a chip-specific IOS update, required for TI */
return (sdhci_cam_update_ios(slot));
}
-int
+static int
sdhci_cam_update_ios(struct sdhci_slot *slot)
{
struct mmc_ios *ios = &slot->host.ios;
@@ -2716,10 +2813,10 @@ sdhci_cam_update_ios(struct sdhci_slot *slot)
return (0);
}
-int
+static int
sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb)
{
- struct ccb_mmcio *mmcio;
+ const struct ccb_mmcio *mmcio;
mmcio = &ccb->mmcio;
@@ -2730,15 +2827,18 @@ sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb)
}
*/
if (__predict_false(sdhci_debug > 1)) {
- slot_printf(slot, "CMD%u arg %#x flags %#x dlen %u dflags %#x\n",
- mmcio->cmd.opcode, mmcio->cmd.arg, mmcio->cmd.flags,
- mmcio->cmd.data != NULL ? (unsigned int) mmcio->cmd.data->len : 0,
- mmcio->cmd.data != NULL ? mmcio->cmd.data->flags: 0);
+ slot_printf(slot, "CMD%u arg %#x flags %#x dlen %u dflags %#x "
+ "blksz=%zu blkcnt=%zu\n",
+ mmcio->cmd.opcode, mmcio->cmd.arg, mmcio->cmd.flags,
+ mmcio->cmd.data != NULL ? (unsigned int) mmcio->cmd.data->len : 0,
+ mmcio->cmd.data != NULL ? mmcio->cmd.data->flags : 0,
+ mmcio->cmd.data != NULL ? mmcio->cmd.data->block_size : 0,
+ mmcio->cmd.data != NULL ? mmcio->cmd.data->block_count : 0);
}
if (mmcio->cmd.data != NULL) {
if (mmcio->cmd.data->len == 0 || mmcio->cmd.data->flags == 0)
panic("data->len = %d, data->flags = %d -- something is b0rked",
- (int)mmcio->cmd.data->len, mmcio->cmd.data->flags);
+ (int)mmcio->cmd.data->len, mmcio->cmd.data->flags);
}
slot->ccb = ccb;
slot->flags = 0;
@@ -2754,4 +2854,4 @@ sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb)
}
#endif /* MMCCAM */
-MODULE_VERSION(sdhci, 1);
+MODULE_VERSION(sdhci, SDHCI_VERSION);
diff --git a/freebsd/sys/dev/sdhci/sdhci.h b/freebsd/sys/dev/sdhci/sdhci.h
index a22e0235..38c5e1b9 100644
--- a/freebsd/sys/dev/sdhci/sdhci.h
+++ b/freebsd/sys/dev/sdhci/sdhci.h
@@ -32,8 +32,8 @@
#include <rtems/bsd/local/opt_mmccam.h>
-#define DMA_BLOCK_SIZE 4096
-#define DMA_BOUNDARY 0 /* DMA reload every 4K */
+/* Macro for sizing the SDMA bounce buffer on the SDMA buffer boundary. */
+#define SDHCI_SDMA_BNDRY_TO_BBUFSZ(bndry) (4096 * (1 << bndry))
/* Controller doesn't honor resets unless we touch the clock register */
#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1 << 0)
@@ -95,6 +95,8 @@
#define SDHCI_QUIRK_BROKEN_AUTO_STOP (1 << 28)
/* Controller supports eMMC HS400 mode if SDHCI_CAN_SDR104 is set. */
#define SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 (1 << 29)
+/* SDMA boundary in SDHCI_BLOCK_SIZE broken - use front-end supplied value. */
+#define SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY (1 << 30)
/*
* Controller registers
@@ -102,6 +104,14 @@
#define SDHCI_DMA_ADDRESS 0x00
#define SDHCI_BLOCK_SIZE 0x04
+#define SDHCI_BLKSZ_SDMA_BNDRY_4K 0x00
+#define SDHCI_BLKSZ_SDMA_BNDRY_8K 0x01
+#define SDHCI_BLKSZ_SDMA_BNDRY_16K 0x02
+#define SDHCI_BLKSZ_SDMA_BNDRY_32K 0x03
+#define SDHCI_BLKSZ_SDMA_BNDRY_64K 0x04
+#define SDHCI_BLKSZ_SDMA_BNDRY_128K 0x05
+#define SDHCI_BLKSZ_SDMA_BNDRY_256K 0x06
+#define SDHCI_BLKSZ_SDMA_BNDRY_512K 0x07
#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
#define SDHCI_BLOCK_COUNT 0x06
@@ -362,6 +372,8 @@ struct sdhci_slot {
bus_dmamap_t dmamap;
u_char *dmamem;
bus_addr_t paddr; /* DMA buffer address */
+ uint32_t sdma_bbufsz; /* SDMA bounce buffer size */
+ uint8_t sdma_boundary; /* SDMA boundary */
struct task card_task; /* Card presence check task */
struct timeout_task
card_delayed_task;/* Card insert delayed task */
@@ -401,10 +413,10 @@ struct sdhci_slot {
#ifdef MMCCAM
/* CAM stuff */
union ccb *ccb;
- struct cam_devq *devq;
- struct cam_sim *sim;
- struct mtx sim_mtx;
- u_char card_present; /* XXX Maybe derive this from elsewhere? */
+ struct cam_devq *devq;
+ struct cam_sim *sim;
+ struct mtx sim_mtx;
+ u_char card_present; /* XXX Maybe derive this from elsewhere? */
#endif
};
@@ -434,4 +446,9 @@ bool sdhci_generic_get_card_present(device_t brdev, struct sdhci_slot *slot);
void sdhci_generic_set_uhs_timing(device_t brdev, struct sdhci_slot *slot);
void sdhci_handle_card_present(struct sdhci_slot *slot, bool is_present);
+#define SDHCI_VERSION 2
+
+#define SDHCI_DEPEND(name) \
+ MODULE_DEPEND(name, sdhci, SDHCI_VERSION, SDHCI_VERSION, SDHCI_VERSION);
+
#endif /* __SDHCI_H__ */
diff --git a/freebsd/sys/dev/usb/net/if_aue.c b/freebsd/sys/dev/usb/net/if_aue.c
index 5454e2aa..d33176d9 100644
--- a/freebsd/sys/dev/usb/net/if_aue.c
+++ b/freebsd/sys/dev/usb/net/if_aue.c
@@ -94,6 +94,10 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -107,6 +111,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/net/usb_ethernet.h>
#include <dev/usb/net/if_auereg.h>
+#include <rtems/bsd/local/miibus_if.h>
+
#ifdef USB_DEBUG
static int aue_debug = 0;
diff --git a/freebsd/sys/dev/usb/net/if_axe.c b/freebsd/sys/dev/usb/net/if_axe.c
index cf54e96e..643b46ce 100644
--- a/freebsd/sys/dev/usb/net/if_axe.c
+++ b/freebsd/sys/dev/usb/net/if_axe.c
@@ -118,6 +118,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/net/usb_ethernet.h>
#include <dev/usb/net/if_axereg.h>
+#include <rtems/bsd/local/miibus_if.h>
+
/*
* AXE_178_MAX_FRAME_BURST
* max frame burst size for Ax88178 and Ax88772
@@ -1149,7 +1151,7 @@ axe_rxeof(struct usb_ether *ue, struct usb_page_cache *pc, unsigned int offset,
}
}
- _IF_ENQUEUE(&ue->ue_rxq, m);
+ (void)mbufq_enqueue(&ue->ue_rxq, m);
return (0);
}
diff --git a/freebsd/sys/dev/usb/net/if_axge.c b/freebsd/sys/dev/usb/net/if_axge.c
index f8ed34ae..564d5221 100644
--- a/freebsd/sys/dev/usb/net/if_axge.c
+++ b/freebsd/sys/dev/usb/net/if_axge.c
@@ -50,6 +50,10 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -63,6 +67,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/net/usb_ethernet.h>
#include <dev/usb/net/if_axgereg.h>
+#include <rtems/bsd/local/miibus_if.h>
+
/*
* Various supported device vendors/products.
*/
@@ -1037,7 +1043,7 @@ axge_rxeof(struct usb_ether *ue, struct usb_page_cache *pc, unsigned int offset,
}
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
- _IF_ENQUEUE(&ue->ue_rxq, m);
+ (void)mbufq_enqueue(&ue->ue_rxq, m);
}
static void
diff --git a/freebsd/sys/dev/usb/net/if_cdce.c b/freebsd/sys/dev/usb/net/if_cdce.c
index 9a15da69..6abe6653 100644
--- a/freebsd/sys/dev/usb/net/if_cdce.c
+++ b/freebsd/sys/dev/usb/net/if_cdce.c
@@ -52,11 +52,11 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/gsb_crc32.h>
+#include <sys/eventhandler.h>
#include <sys/stdint.h>
#include <sys/stddef.h>
-#include <sys/param.h>
#include <sys/queue.h>
-#include <sys/types.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/kernel.h>
@@ -278,6 +278,7 @@ static const STRUCT_USB_HOST_ID cdce_host_devs[] = {
{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
+ {USB_VPI(USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8156, 0)},
{USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR),
USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x16),
diff --git a/freebsd/sys/dev/usb/net/if_mos.c b/freebsd/sys/dev/usb/net/if_mos.c
index 3dd0e5ef..3ab0e62e 100644
--- a/freebsd/sys/dev/usb/net/if_mos.c
+++ b/freebsd/sys/dev/usb/net/if_mos.c
@@ -122,6 +122,10 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -134,6 +138,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/net/usb_ethernet.h>
+#include <rtems/bsd/local/miibus_if.h>
+
//#include <dev/usb/net/if_mosreg.h>
#include "if_mosreg.h"
diff --git a/freebsd/sys/dev/usb/net/if_rue.c b/freebsd/sys/dev/usb/net/if_rue.c
index 810a98c8..8d095c86 100644
--- a/freebsd/sys/dev/usb/net/if_rue.c
+++ b/freebsd/sys/dev/usb/net/if_rue.c
@@ -91,6 +91,10 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -104,6 +108,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/net/usb_ethernet.h>
#include <dev/usb/net/if_ruereg.h>
+#include <rtems/bsd/local/miibus_if.h>
+
#ifdef USB_DEBUG
static int rue_debug = 0;
diff --git a/freebsd/sys/dev/usb/net/if_smsc.c b/freebsd/sys/dev/usb/net/if_smsc.c
index 87e181d8..bbf28ad8 100644
--- a/freebsd/sys/dev/usb/net/if_smsc.c
+++ b/freebsd/sys/dev/usb/net/if_smsc.c
@@ -89,6 +89,10 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include <netinet/in.h>
#include <netinet/ip.h>
@@ -99,6 +103,7 @@ __FBSDID("$FreeBSD$");
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/usb/usb_fdt_support.h>
#endif
#include <dev/usb/usb.h>
@@ -114,6 +119,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/net/if_smscreg.h>
+#include <rtems/bsd/local/miibus_if.h>
+
#ifdef USB_DEBUG
static int smsc_debug = 0;
@@ -1561,147 +1568,6 @@ smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
return (rc);
}
-#ifdef FDT
-/*
- * This is FreeBSD-specific compatibility strings for RPi/RPi2
- */
-static phandle_t
-smsc_fdt_find_eth_node(phandle_t start)
-{
- phandle_t child, node;
-
- /* Traverse through entire tree to find usb ethernet nodes. */
- for (node = OF_child(start); node != 0; node = OF_peer(node)) {
- if ((ofw_bus_node_is_compatible(node, "net,ethernet") &&
- ofw_bus_node_is_compatible(node, "usb,device")) ||
- ofw_bus_node_is_compatible(node, "usb424,ec00"))
- return (node);
- child = smsc_fdt_find_eth_node(node);
- if (child != -1)
- return (child);
- }
-
- return (-1);
-}
-
-/*
- * Check if node's path is <*>/usb/hub/ethernet
- */
-static int
-smsc_fdt_is_usb_eth(phandle_t node)
-{
- char name[16];
- int len;
-
- memset(name, 0, sizeof(name));
- len = OF_getprop(node, "name", name, sizeof(name));
- if (len <= 0)
- return (0);
-
- if (strcmp(name, "ethernet"))
- return (0);
-
- node = OF_parent(node);
- if (node == -1)
- return (0);
- len = OF_getprop(node, "name", name, sizeof(name));
- if (len <= 0)
- return (0);
-
- if (strcmp(name, "hub"))
- return (0);
-
- node = OF_parent(node);
- if (node == -1)
- return (0);
- len = OF_getprop(node, "name", name, sizeof(name));
- if (len <= 0)
- return (0);
-
- if (strcmp(name, "usb"))
- return (0);
-
- return (1);
-}
-
-static phandle_t
-smsc_fdt_find_eth_node_by_path(phandle_t start)
-{
- phandle_t child, node;
-
- /* Traverse through entire tree to find usb ethernet nodes. */
- for (node = OF_child(start); node != 0; node = OF_peer(node)) {
- if (smsc_fdt_is_usb_eth(node))
- return (node);
- child = smsc_fdt_find_eth_node_by_path(node);
- if (child != -1)
- return (child);
- }
-
- return (-1);
-}
-
-/*
- * Look through known names that can contain mac address
- * return 0 if valid MAC address has been found
- */
-static int
-smsc_fdt_read_mac_property(phandle_t node, unsigned char *mac)
-{
- int len;
-
- /* Check if there is property */
- if ((len = OF_getproplen(node, "local-mac-address")) > 0) {
- if (len != ETHER_ADDR_LEN)
- return (EINVAL);
-
- OF_getprop(node, "local-mac-address", mac,
- ETHER_ADDR_LEN);
- return (0);
- }
-
- if ((len = OF_getproplen(node, "mac-address")) > 0) {
- if (len != ETHER_ADDR_LEN)
- return (EINVAL);
-
- OF_getprop(node, "mac-address", mac,
- ETHER_ADDR_LEN);
- return (0);
- }
-
- return (ENXIO);
-}
-
-/**
- * Get MAC address from FDT blob. Firmware or loader should fill
- * mac-address or local-mac-address property. Returns 0 if MAC address
- * obtained, error code otherwise.
- */
-static int
-smsc_fdt_find_mac(unsigned char *mac)
-{
- phandle_t node, root;
-
- root = OF_finddevice("/");
- node = smsc_fdt_find_eth_node(root);
- if (node != -1) {
- if (smsc_fdt_read_mac_property(node, mac) == 0)
- return (0);
- }
-
- /*
- * If it's not FreeBSD FDT blob for RPi, try more
- * generic .../usb/hub/ethernet
- */
- node = smsc_fdt_find_eth_node_by_path(root);
-
- if (node != -1)
- return smsc_fdt_read_mac_property(node, mac);
-
- return (ENXIO);
-}
-#endif
-
/**
* smsc_attach_post - Called after the driver attached to the USB interface
* @ue: the USB ethernet device
@@ -1750,7 +1616,7 @@ smsc_attach_post(struct usb_ether *ue)
err = smsc_eeprom_read(sc, 0x01, sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
#ifdef FDT
if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr)))
- err = smsc_fdt_find_mac(sc->sc_ue.ue_eaddr);
+ err = usb_fdt_get_mac_addr(sc->sc_ue.ue_dev, &sc->sc_ue);
#endif
if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr))) {
read_random(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
diff --git a/freebsd/sys/dev/usb/net/if_udav.c b/freebsd/sys/dev/usb/net/if_udav.c
index a4e683ac..8a2ad81f 100644
--- a/freebsd/sys/dev/usb/net/if_udav.c
+++ b/freebsd/sys/dev/usb/net/if_udav.c
@@ -72,12 +72,18 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <rtems/bsd/local/usbdevs.h>
+#include <rtems/bsd/local/miibus_if.h>
+
#define USB_DEBUG_VAR udav_debug
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_process.h>
diff --git a/freebsd/sys/dev/usb/net/if_ure.c b/freebsd/sys/dev/usb/net/if_ure.c
index 136b61f9..0130a7bb 100644
--- a/freebsd/sys/dev/usb/net/if_ure.c
+++ b/freebsd/sys/dev/usb/net/if_ure.c
@@ -43,6 +43,10 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -56,6 +60,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/net/usb_ethernet.h>
#include <dev/usb/net/if_urereg.h>
+#include <rtems/bsd/local/miibus_if.h>
+
#ifdef USB_DEBUG
static int ure_debug = 0;
@@ -64,6 +70,9 @@ SYSCTL_INT(_hw_usb_ure, OID_AUTO, debug, CTLFLAG_RWTUN, &ure_debug, 0,
"Debug level");
#endif
+#define ETHER_IS_ZERO(addr) \
+ (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]))
+
/*
* Various supported device vendors/products.
*/
@@ -71,6 +80,7 @@ static const STRUCT_USB_HOST_ID ure_devs[] = {
#define URE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
URE_DEV(LENOVO, RTL8153, 0),
URE_DEV(LENOVO, TBT3LAN, 0),
+ URE_DEV(LENOVO, ONELINK, 0),
URE_DEV(LENOVO, USBCLAN, 0),
URE_DEV(NVIDIA, RTL8153, 0),
URE_DEV(REALTEK, RTL8152, URE_FLAG_8152),
@@ -674,12 +684,20 @@ ure_attach_post(struct usb_ether *ue)
else
ure_rtl8153_init(sc);
- if (sc->sc_chip & URE_CHIP_VER_4C00)
+ if ((sc->sc_chip & URE_CHIP_VER_4C00) ||
+ (sc->sc_chip & URE_CHIP_VER_4C10))
ure_read_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA,
ue->ue_eaddr, 8);
else
ure_read_mem(sc, URE_PLA_BACKUP, URE_MCU_TYPE_PLA,
ue->ue_eaddr, 8);
+
+ if (ETHER_IS_ZERO(sc->sc_ue.ue_eaddr)) {
+ device_printf(sc->sc_ue.ue_dev, "MAC assigned randomly\n");
+ arc4rand(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN, 0);
+ sc->sc_ue.ue_eaddr[0] &= ~0x01; /* unicast */
+ sc->sc_ue.ue_eaddr[0] |= 0x02; /* locally administered */
+ }
}
static int
@@ -725,8 +743,10 @@ ure_init(struct usb_ether *ue)
ure_reset(sc);
/* Set MAC address. */
+ ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_CONFIG);
ure_write_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA | URE_BYTE_EN_SIX_BYTES,
IF_LLADDR(ifp), 8);
+ ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_NORAML);
/* Reset the packet filter. */
ure_write_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA,
diff --git a/freebsd/sys/dev/usb/net/if_urereg.h b/freebsd/sys/dev/usb/net/if_urereg.h
index 8eff1c25..cc70093f 100644
--- a/freebsd/sys/dev/usb/net/if_urereg.h
+++ b/freebsd/sys/dev/usb/net/if_urereg.h
@@ -176,7 +176,7 @@
#define URE_EEEP_CR_EEEP_TX 0x0002
/* PLA_WDT6_CTRL */
-#define URE_WDT6_SET_MODE 0x001
+#define URE_WDT6_SET_MODE 0x0010
/* PLA_TCR0 */
#define URE_TCR0_TX_EMPTY 0x0800
diff --git a/freebsd/sys/dev/usb/net/usb_ethernet.c b/freebsd/sys/dev/usb/net/usb_ethernet.c
index 9ce60eff..2bbcdedc 100644
--- a/freebsd/sys/dev/usb/net/usb_ethernet.c
+++ b/freebsd/sys/dev/usb/net/usb_ethernet.c
@@ -221,6 +221,7 @@ ue_attach_post_task(struct usb_proc_msg *_task)
ue->ue_unit = alloc_unr(ueunit);
usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_mtx, 0);
sysctl_ctx_init(&ue->ue_sysctl_ctx);
+ mbufq_init(&ue->ue_rxq, 0 /* unlimited length */);
error = 0;
CURVNET_SET_QUIET(vnet0);
@@ -286,6 +287,11 @@ ue_attach_post_task(struct usb_proc_msg *_task)
fail:
CURVNET_RESTORE();
+
+ /* drain mbuf queue */
+ mbufq_drain(&ue->ue_rxq);
+
+ /* free unit */
free_unr(ueunit, ue->ue_unit);
if (ue->ue_ifp != NULL) {
if_free(ue->ue_ifp);
@@ -332,6 +338,9 @@ uether_ifdetach(struct usb_ether *ue)
/* free sysctl */
sysctl_ctx_free(&ue->ue_sysctl_ctx);
+ /* drain mbuf queue */
+ mbufq_drain(&ue->ue_rxq);
+
/* free unit */
free_unr(ueunit, ue->ue_unit);
}
@@ -600,7 +609,7 @@ uether_rxmbuf(struct usb_ether *ue, struct mbuf *m,
m->m_pkthdr.len = m->m_len = len;
/* enqueue for later when the lock can be released */
- _IF_ENQUEUE(&ue->ue_rxq, m);
+ (void)mbufq_enqueue(&ue->ue_rxq, m);
return (0);
}
@@ -630,7 +639,7 @@ uether_rxbuf(struct usb_ether *ue, struct usb_page_cache *pc,
m->m_pkthdr.len = m->m_len = len;
/* enqueue for later when the lock can be released */
- _IF_ENQUEUE(&ue->ue_rxq, m);
+ (void)mbufq_enqueue(&ue->ue_rxq, m);
return (0);
}
@@ -643,7 +652,7 @@ uether_rxflush(struct usb_ether *ue)
UE_LOCK_ASSERT(ue, MA_OWNED);
for (;;) {
- _IF_DEQUEUE(&ue->ue_rxq, m);
+ m = mbufq_dequeue(&ue->ue_rxq);
if (m == NULL)
break;
diff --git a/freebsd/sys/dev/usb/net/usb_ethernet.h b/freebsd/sys/dev/usb/net/usb_ethernet.h
index 9839db16..87886559 100644
--- a/freebsd/sys/dev/usb/net/usb_ethernet.h
+++ b/freebsd/sys/dev/usb/net/usb_ethernet.h
@@ -48,11 +48,7 @@
#include <net/bpf.h>
#include <net/ethernet.h>
-#include <rtems/bsd/local/miibus_if.h>
-
-#include <dev/mii/mii.h>
-#include <dev/mii/miivar.h>
-
+struct mii_data;
struct usb_ether;
struct usb_device_request;
@@ -91,7 +87,7 @@ struct usb_ether {
struct usb_process ue_tq;
struct sysctl_ctx_list ue_sysctl_ctx;
- struct ifqueue ue_rxq;
+ struct mbufq ue_rxq;
struct usb_callout ue_watchdog;
struct usb_ether_cfg_task ue_sync_task[2];
struct usb_ether_cfg_task ue_media_task[2];
diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c
index 2aea57c8..6c1589e9 100644
--- a/freebsd/sys/dev/usb/quirk/usb_quirk.c
+++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c
@@ -98,10 +98,12 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(TELEX, MIC1, 0x009, 0x009, UQ_AU_NO_FRAC),
USB_QUIRK(SILICONPORTALS, YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC),
USB_QUIRK(LOGITECH, UN53B, 0x0000, 0xffff, UQ_NO_STRINGS),
+ USB_QUIRK(LOGITECH, G510S, 0x0000, 0xFFFF, UQ_KBD_BOOTPROTO),
USB_QUIRK(REALTEK, RTL8196EU, 0x0000, 0xffff, UQ_CFG_INDEX_1),
USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
USB_QUIRK(PLANEX2, MZKUE150N, 0x0000, 0xffff, UQ_CFG_INDEX_1),
USB_QUIRK(CISCOLINKSYS, USB3GIGV1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
+ USB_QUIRK(REALTEK, RTL8156, 0x0000, 0xffff, UQ_CFG_INDEX_2),
/* Quirks for printer devices */
USB_QUIRK(HP, 895C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
USB_QUIRK(HP, 880C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
@@ -112,8 +114,19 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(XEROX, WCM15, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
/* Devices which should be ignored by uhid */
USB_QUIRK(APC, UPS, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(BELKIN, F6H375USB, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(BELKIN, F6C550AVR, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(BELKIN, F6C1250TWRK, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(BELKIN, F6C1500TWRK, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(BELKIN, F6C900UNV, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(BELKIN, F6C100UNV, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(BELKIN, F6C120UNV, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(BELKIN, F6C800UNV, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(BELKIN, F6C1100UNV, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(CYBERPOWER, BC900D, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(CYBERPOWER, 1500CAVRLCD, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(CYBERPOWER, OR2200LCDRM2U, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(DELL2, VARIOUS_UPS, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(CYPRESS, SILVERSHIELD, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(DELORME, EARTHMATE, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(DREAMLINK, DL100B, 0x0000, 0xffff, UQ_HID_IGNORE),
@@ -121,8 +134,26 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(ITUNERNET, USBLCD4X20, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(LIEBERT, POWERSURE_PXT, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(LIEBERT2, PSI1000, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(LIEBERT2, POWERSURE_PSA, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(MGE, UPS1, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(MGE, UPS2, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(POWERCOM, IMPERIAL_SERIES, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(POWERCOM, SMART_KING_PRO, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(POWERCOM, WOW, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(POWERCOM, VANGUARD, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(POWERCOM, BLACK_KNIGHT_PRO, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, AVR550U, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, AVR750U, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, ECO550UPS, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, T750_INTL, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, RT_2200_INTL, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, OMNI1000LCD, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, OMNI900LCD, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, SMART_2200RMXL2U, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, UPS_3014, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, SU1500RTXL2UA, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, SU6000RT4U, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(TRIPPLITE2, SU1500RTXL2UA_2, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(APPLE, IPHONE, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(APPLE, IPHONE_3G, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(MEGATEC, UPS, 0x0000, 0xffff, UQ_HID_IGNORE),
@@ -137,12 +168,15 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, 0x0000, 0xffff, UQ_MS_LEADING_BYTE),
/* Quirk for Corsair Vengeance K60 keyboard */
USB_QUIRK(CORSAIR, K60, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
+ /* Quirk for Corsair Gaming K68 keyboard */
+ USB_QUIRK(CORSAIR, K68, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
/* Quirk for Corsair Vengeance K70 keyboard */
USB_QUIRK(CORSAIR, K70, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
/* Quirk for Corsair K70 RGB keyboard */
USB_QUIRK(CORSAIR, K70_RGB, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
/* Quirk for Corsair STRAFE Gaming keyboard */
USB_QUIRK(CORSAIR, STRAFE, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
+ USB_QUIRK(CORSAIR, STRAFE2, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
/* umodem(4) device quirks */
USB_QUIRK(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
USB_QUIRK(SANYO, SCP4900, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
@@ -188,6 +222,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(CENTURY, EX35QUAT, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
+ USB_QUIRK(CREATIVE, NOMAD, 0x0001, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
+ UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1),
USB_QUIRK(CYPRESS, XX6830XX, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(DESKNOTE, UCR_61S2B, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -240,7 +276,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_RBC),
USB_QUIRK(INSYSTEM, STORAGE_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
UQ_MSC_FORCE_PROTO_RBC),
- USB_QUIRK(INTENSO, MEMORY_BOX, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY),
+ USB_QUIRK(VIALABS, VL701, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY),
USB_QUIRK(IODATA, IU_CD2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(IODATA, DVR_UEH8, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -248,6 +284,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(IOMEGA, ZIP100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */
+ USB_QUIRK(JMICRON, JMS566, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(JMICRON, JMS567, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI,
@@ -362,6 +399,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
USB_QUIRK(SANDISK, SDCZ4_256, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
+ USB_QUIRK(SANDISK, SDCZ48_32, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE,
+ UQ_MSC_NO_TEST_UNIT_READY),
USB_QUIRK(SANDISK, SDDR31, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1),
USB_QUIRK(SANDISK, IMAGEMATE_SDDR289, 0x0000, 0xffff,
@@ -498,6 +537,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(VIALABS, USB30SATABRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(QUALCOMMINC, ZTE_MF730M, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
UQ_MSC_NO_INQUIRY, UQ_CFG_INDEX_0),
+ USB_QUIRK(SMART2, G2MEMKEY, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY),
/* Non-standard USB MIDI devices */
USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(ROLAND, SC8850, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
@@ -528,6 +568,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(MAUDIO, FASTTRACKULTRA8R, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(CMEDIA, CM6206, 0x0000, 0xffff, UQ_AU_SET_SPDIF_CM6206),
+ USB_QUIRK(PLOYTEC, SPL_CRIMSON_1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
+ USB_QUIRK(ROLAND, UA25EX_AD, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
/*
* Quirks for manufacturers which USB devices does not respond
diff --git a/freebsd/sys/dev/usb/serial/u3g.c b/freebsd/sys/dev/usb/serial/u3g.c
index 8d72ef49..dd82a2b2 100644
--- a/freebsd/sys/dev/usb/serial/u3g.c
+++ b/freebsd/sys/dev/usb/serial/u3g.c
@@ -33,11 +33,11 @@
*/
+#include <sys/param.h>
+#include <sys/eventhandler.h>
#include <sys/stdint.h>
#include <sys/stddef.h>
-#include <sys/param.h>
#include <sys/queue.h>
-#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
diff --git a/freebsd/sys/dev/usb/serial/ugensa.c b/freebsd/sys/dev/usb/serial/ugensa.c
index 2737227c..10a3ea33 100644
--- a/freebsd/sys/dev/usb/serial/ugensa.c
+++ b/freebsd/sys/dev/usb/serial/ugensa.c
@@ -72,6 +72,7 @@
#define UGENSA_CONFIG_INDEX 0
#define UGENSA_IFACE_INDEX 0
#define UGENSA_IFACE_MAX 8 /* exclusivly */
+#define UGENSA_PORT_MAX 8 /* exclusivly */
enum {
UGENSA_BULK_DT_WR,
@@ -86,11 +87,11 @@ struct ugensa_sub_softc {
struct ugensa_softc {
struct ucom_super_softc sc_super_ucom;
- struct ucom_softc sc_ucom[UGENSA_IFACE_MAX];
- struct ugensa_sub_softc sc_sub[UGENSA_IFACE_MAX];
+ struct ucom_softc sc_ucom[UGENSA_PORT_MAX];
+ struct ugensa_sub_softc sc_sub[UGENSA_PORT_MAX];
struct mtx sc_mtx;
- uint8_t sc_niface;
+ uint8_t sc_nports;
};
/* prototypes */
@@ -156,12 +157,13 @@ static driver_t ugensa_driver = {
.size = sizeof(struct ugensa_softc),
};
+/* Driver-info is max number of serial ports per interface */
static const STRUCT_USB_HOST_ID ugensa_devs[] = {
- {USB_VPI(USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220, 0)},
- {USB_VPI(USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CDMA_MODEM1, 0)},
- {USB_VPI(USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_CDMA_MSM_K, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_49GPLUS, 0)},
- {USB_VPI(USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_FLEXPACKGPS, 0)},
+ {USB_VPI(USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220, 1)},
+ {USB_VPI(USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CDMA_MODEM1, 1)},
+ {USB_VPI(USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_CDMA_MSM_K, 1)},
+ {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_49GPLUS, 1)},
+ {USB_VPI(USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_FLEXPACKGPS, 3)},
};
DRIVER_MODULE(ugensa, uhub, ugensa_driver, ugensa_devclass, NULL, 0);
@@ -194,65 +196,68 @@ ugensa_attach(device_t dev)
struct ugensa_softc *sc = device_get_softc(dev);
struct ugensa_sub_softc *ssc;
struct usb_interface *iface;
+ struct usb_config xfer_config[UGENSA_N_TRANSFER];
int32_t error;
uint8_t iface_index;
- int x, cnt;
+ int x, maxports;
+ maxports = USB_GET_DRIVER_INFO(uaa);
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "ugensa", NULL, MTX_DEF);
ucom_ref(&sc->sc_super_ucom);
- /* Figure out how many interfaces this device has got */
- for (cnt = 0; cnt < UGENSA_IFACE_MAX; cnt++) {
- if ((usbd_get_endpoint(uaa->device, cnt, ugensa_xfer_config + 0) == NULL) ||
- (usbd_get_endpoint(uaa->device, cnt, ugensa_xfer_config + 1) == NULL)) {
- /* we have reached the end */
- break;
- }
- }
+ for (iface_index = UGENSA_IFACE_INDEX; iface_index < UGENSA_IFACE_MAX; iface_index++) {
- if (cnt == 0) {
- device_printf(dev, "No interfaces\n");
- goto detach;
- }
- for (x = 0; x < cnt; x++) {
- iface = usbd_get_iface(uaa->device, x);
- if (iface->idesc->bInterfaceClass != UICLASS_VENDOR)
+ iface = usbd_get_iface(uaa->device, iface_index);
+ if (iface == NULL || iface->idesc->bInterfaceClass != UICLASS_VENDOR)
/* Not a serial port, most likely a SD reader */
continue;
- ssc = sc->sc_sub + sc->sc_niface;
- ssc->sc_ucom_ptr = sc->sc_ucom + sc->sc_niface;
-
- iface_index = (UGENSA_IFACE_INDEX + x);
- error = usbd_transfer_setup(uaa->device,
- &iface_index, ssc->sc_xfer, ugensa_xfer_config,
- UGENSA_N_TRANSFER, ssc, &sc->sc_mtx);
-
- if (error) {
- device_printf(dev, "allocating USB "
- "transfers failed\n");
- goto detach;
+ /* Loop over all endpoints pairwise */
+ for (x = 0; x < maxports && sc->sc_nports < UGENSA_PORT_MAX; x++) {
+
+ ssc = sc->sc_sub + sc->sc_nports;
+ ssc->sc_ucom_ptr = sc->sc_ucom + sc->sc_nports;
+
+ memcpy(xfer_config, ugensa_xfer_config, sizeof ugensa_xfer_config);
+ xfer_config[UGENSA_BULK_DT_RD].ep_index = x;
+ xfer_config[UGENSA_BULK_DT_WR].ep_index = x;
+
+ error = usbd_transfer_setup(uaa->device,
+ &iface_index, ssc->sc_xfer, xfer_config,
+ UGENSA_N_TRANSFER, ssc, &sc->sc_mtx);
+
+ if (error) {
+ if (x == 0) {
+ device_printf(dev, "allocating USB "
+ "transfers failed (%d)\n", error);
+ goto detach;
+ }
+ break;
+ }
+
+ /* clear stall at first run */
+ mtx_lock(&sc->sc_mtx);
+ usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_WR]);
+ usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_RD]);
+ mtx_unlock(&sc->sc_mtx);
+
+ /* initialize port number */
+ ssc->sc_ucom_ptr->sc_portno = sc->sc_nports;
+ if (iface_index != uaa->info.bIfaceIndex) {
+ usbd_set_parent_iface(uaa->device, iface_index,
+ uaa->info.bIfaceIndex);
+ }
+ sc->sc_nports++;
}
- /* clear stall at first run */
- mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_WR]);
- usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_RD]);
- mtx_unlock(&sc->sc_mtx);
-
- /* initialize port number */
- ssc->sc_ucom_ptr->sc_portno = sc->sc_niface;
- sc->sc_niface++;
- if (x != uaa->info.bIfaceIndex)
- usbd_set_parent_iface(uaa->device, x,
- uaa->info.bIfaceIndex);
}
- device_printf(dev, "Found %d interfaces.\n", sc->sc_niface);
+ device_printf(dev, "Found %d serial ports.\n", sc->sc_nports);
- error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_niface, sc,
+ error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_nports, sc,
&ugensa_callback, &sc->sc_mtx);
+
if (error) {
- DPRINTF("attach failed\n");
+ DPRINTF("ucom attach failed\n");
goto detach;
}
ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
@@ -272,7 +277,7 @@ ugensa_detach(device_t dev)
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom);
- for (x = 0; x < sc->sc_niface; x++) {
+ for (x = 0; x < sc->sc_nports; x++) {
usbd_transfer_unsetup(sc->sc_sub[x].sc_xfer, UGENSA_N_TRANSFER);
}
diff --git a/freebsd/sys/dev/usb/serial/umcs.c b/freebsd/sys/dev/usb/serial/umcs.c
index 8f083ce3..3a5fc70f 100644
--- a/freebsd/sys/dev/usb/serial/umcs.c
+++ b/freebsd/sys/dev/usb/serial/umcs.c
@@ -501,7 +501,9 @@ umcs7840_cfg_open(struct ucom_softc *ucom)
* Enable DTR/RTS on modem control, enable modem interrupts --
* documented
*/
- sc->sc_ports[pn].sc_mcr = MCS7840_UART_MCR_DTR | MCS7840_UART_MCR_RTS | MCS7840_UART_MCR_IE;
+ sc->sc_ports[pn].sc_mcr = MCS7840_UART_MCR_IE;
+ if (ucom->sc_tty == NULL || (ucom->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0)
+ sc->sc_ports[pn].sc_mcr |= MCS7840_UART_MCR_DTR | MCS7840_UART_MCR_RTS;
if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr))
return;
diff --git a/freebsd/sys/dev/usb/serial/usb_serial.c b/freebsd/sys/dev/usb/serial/usb_serial.c
index a3f9b5de..c649056a 100644
--- a/freebsd/sys/dev/usb/serial/usb_serial.c
+++ b/freebsd/sys/dev/usb/serial/usb_serial.c
@@ -810,7 +810,8 @@ ucom_open(struct tty *tp)
&sc->sc_start_task[0].hdr,
&sc->sc_start_task[1].hdr);
- ucom_modem(tp, SER_DTR | SER_RTS, 0);
+ if (sc->sc_tty == NULL || (sc->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0)
+ ucom_modem(tp, SER_DTR | SER_RTS, 0);
ucom_ring(sc, 0);
diff --git a/freebsd/sys/dev/usb/usb.h b/freebsd/sys/dev/usb/usb.h
index ff33cf00..0075d429 100644
--- a/freebsd/sys/dev/usb/usb.h
+++ b/freebsd/sys/dev/usb/usb.h
@@ -444,6 +444,7 @@ typedef struct usb_interface_assoc_descriptor usb_interface_assoc_descriptor_t;
#define UIPROTO_CDC_NONE 0
#define UIPROTO_CDC_AT 1
+#define UIPROTO_CDC_EEM 7
#define UICLASS_HID 0x03
#define UISUBCLASS_BOOT 1
diff --git a/freebsd/sys/dev/usb/usb_bus.h b/freebsd/sys/dev/usb/usb_bus.h
index 710436c1..9f8586e6 100644
--- a/freebsd/sys/dev/usb/usb_bus.h
+++ b/freebsd/sys/dev/usb/usb_bus.h
@@ -131,6 +131,7 @@ struct usb_bus {
uint8_t do_probe; /* set if USB should be re-probed */
uint8_t no_explore; /* don't explore USB ports */
uint8_t dma_bits; /* number of DMA address lines */
+ uint8_t control_ep_quirk; /* need 64kByte buffer for data stage */
};
#endif /* _USB_BUS_H_ */
diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c
index 5d6b9d0f..ee240949 100644
--- a/freebsd/sys/dev/usb/usb_device.c
+++ b/freebsd/sys/dev/usb/usb_device.c
@@ -34,8 +34,8 @@
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
+#include <sys/eventhandler.h>
#include <sys/queue.h>
-#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
diff --git a/freebsd/sys/dev/usb/usb_fdt_support.h b/freebsd/sys/dev/usb/usb_fdt_support.h
new file mode 100644
index 00000000..e4249e85
--- /dev/null
+++ b/freebsd/sys/dev/usb/usb_fdt_support.h
@@ -0,0 +1,48 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Ian Lepore <ian@FreeBSD.org>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _USB_FDT_SUPPORT_H_
+#define _USB_FDT_SUPPORT_H_
+
+struct usb_device;
+struct usb_ether;
+
+/*
+ * Get the device's MAC address from the FDT data. Fills in ue->ue_eaddr and
+ * returns 0 on success, otherwise leaves ue_eaddr untouched and returns
+ * non-zero. This first attempts to get the address from the "mac-address"
+ * property, and if that's not valid it tries the "local-mac-address" property;
+ * this matches the linux interpretation of the precedence of those properties.
+ */
+int usb_fdt_get_mac_addr(device_t dev, struct usb_ether* ue);
+
+/* Get the FDT node for dev. Returns -1 if dev is not in the FDT data. */
+phandle_t usb_fdt_get_node(device_t dev, struct usb_device* udev);
+
+#endif
diff --git a/freebsd/sys/dev/usb/usb_generic.c b/freebsd/sys/dev/usb/usb_generic.c
index 29a27d53..6d359226 100644
--- a/freebsd/sys/dev/usb/usb_generic.c
+++ b/freebsd/sys/dev/usb/usb_generic.c
@@ -185,7 +185,8 @@ ugen_open(struct usb_fifo *f, int fflags)
struct usb_endpoint_descriptor *ed = ep->edesc;
uint8_t type;
- DPRINTFN(6, "flag=0x%x\n", fflags);
+ DPRINTFN(1, "flag=0x%x pid=%d name=%s\n", fflags,
+ curthread->td_proc->p_pid, curthread->td_proc->p_comm);
mtx_lock(f->priv_mtx);
switch (usbd_get_speed(f->udev)) {
@@ -215,7 +216,9 @@ ugen_open(struct usb_fifo *f, int fflags)
static void
ugen_close(struct usb_fifo *f, int fflags)
{
- DPRINTFN(6, "flag=0x%x\n", fflags);
+
+ DPRINTFN(1, "flag=0x%x pid=%d name=%s\n", fflags,
+ curthread->td_proc->p_pid, curthread->td_proc->p_comm);
/* cleanup */
@@ -1218,6 +1221,40 @@ complete:
}
static int
+ugen_fs_copy_out_cancelled(struct usb_fs_endpoint *fs_ep_uptr)
+{
+ struct usb_fs_endpoint fs_ep;
+ int error;
+
+ error = copyin(fs_ep_uptr, &fs_ep, sizeof(fs_ep));
+ if (error)
+ return (error);
+
+ fs_ep.status = USB_ERR_CANCELLED;
+ fs_ep.aFrames = 0;
+ fs_ep.isoc_time_complete = 0;
+
+ /* update "aFrames" */
+ error = copyout(&fs_ep.aFrames, &fs_ep_uptr->aFrames,
+ sizeof(fs_ep.aFrames));
+ if (error)
+ goto done;
+
+ /* update "isoc_time_complete" */
+ error = copyout(&fs_ep.isoc_time_complete,
+ &fs_ep_uptr->isoc_time_complete,
+ sizeof(fs_ep.isoc_time_complete));
+ if (error)
+ goto done;
+
+ /* update "status" */
+ error = copyout(&fs_ep.status, &fs_ep_uptr->status,
+ sizeof(fs_ep.status));
+done:
+ return (error);
+}
+
+static int
ugen_fs_copy_out(struct usb_fifo *f, uint8_t ep_index)
{
struct usb_device_request *req;
@@ -1242,7 +1279,12 @@ ugen_fs_copy_out(struct usb_fifo *f, uint8_t ep_index)
return (EINVAL);
mtx_lock(f->priv_mtx);
- if (usbd_transfer_pending(xfer)) {
+ if (!xfer->flags_int.transferring &&
+ !xfer->flags_int.started) {
+ mtx_unlock(f->priv_mtx);
+ DPRINTF("Returning fake cancel event\n");
+ return (ugen_fs_copy_out_cancelled(f->fs_ep_ptr + ep_index));
+ } else if (usbd_transfer_pending(xfer)) {
mtx_unlock(f->priv_mtx);
return (EBUSY); /* should not happen */
}
@@ -1363,6 +1405,7 @@ complete:
sizeof(fs_ep.isoc_time_complete));
if (error)
goto done;
+
/* update "status" */
error = copyout(&fs_ep.status, &fs_ep_uptr->status,
sizeof(fs_ep.status));
@@ -1451,12 +1494,15 @@ ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
xfer = f->fs_xfer[u.pstart->ep_index];
if (usbd_transfer_pending(xfer)) {
usbd_transfer_stop(xfer);
+
/*
* Check if the USB transfer was stopped
- * before it was even started. Else a cancel
- * callback will be pending.
+ * before it was even started and fake a
+ * cancel event.
*/
- if (!xfer->flags_int.transferring) {
+ if (!xfer->flags_int.transferring &&
+ !xfer->flags_int.started) {
+ DPRINTF("Issuing fake completion event\n");
ugen_fs_set_complete(xfer->priv_sc,
USB_P2U(xfer->priv_fifo));
}
diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c
index 7ae052b7..21289f0d 100644
--- a/freebsd/sys/dev/usb/usb_hid.c
+++ b/freebsd/sys/dev/usb/usb_hid.c
@@ -76,7 +76,7 @@ static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize);
#define MAXUSAGE 64
#define MAXPUSH 4
#define MAXID 16
-#define MAXLOCCNT 1024
+#define MAXLOCCNT 2048
struct hid_pos_data {
int32_t rid;
diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c
index a0ad462f..b3543a8f 100644
--- a/freebsd/sys/dev/usb/usb_hub.c
+++ b/freebsd/sys/dev/usb/usb_hub.c
@@ -77,14 +77,9 @@
#include <dev/usb/usb_bus.h>
#endif /* USB_GLOBAL_INCLUDE_FILE */
-#define UHUB_INTR_INTERVAL 250 /* ms */
-enum {
- UHUB_INTR_TRANSFER,
-#if USB_HAVE_TT_SUPPORT
- UHUB_RESET_TT_TRANSFER,
-#endif
- UHUB_N_TRANSFER,
-};
+
+#include <dev/usb/usb_hub_private.h>
+
#ifdef USB_DEBUG
static int uhub_debug = 0;
@@ -113,27 +108,6 @@ SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN,
&usb_disable_port_power, 0, "Set to disable all USB port power.");
#endif
-struct uhub_current_state {
- uint16_t port_change;
- uint16_t port_status;
-};
-
-struct uhub_softc {
- struct uhub_current_state sc_st;/* current state */
-#if (USB_HAVE_FIXED_PORT != 0)
- struct usb_hub sc_hub;
-#endif
- device_t sc_dev; /* base device */
- struct mtx sc_mtx; /* our mutex */
- struct usb_device *sc_udev; /* USB device */
- struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */
-#if USB_HAVE_DISABLE_ENUM
- int sc_disable_enumeration;
- int sc_disable_port_power;
-#endif
- uint8_t sc_flags;
-#define UHUB_FLAG_DID_EXPLORE 0x01
-};
#define UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol)
#define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB)
@@ -143,14 +117,10 @@ struct uhub_softc {
/* prototypes for type checking: */
-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;
static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
static usb_callback_t uhub_intr_callback;
@@ -207,7 +177,7 @@ static device_method_t uhub_methods[] = {
DEVMETHOD_END
};
-static driver_t uhub_driver = {
+driver_t uhub_driver = {
.name = "uhub",
.methods = uhub_methods,
.size = sizeof(struct uhub_softc)
@@ -589,13 +559,25 @@ uhub_read_port_status(struct uhub_softc *sc, uint8_t portno)
struct usb_port_status ps;
usb_error_t err;
+ if (sc->sc_usb_port_errors >= UHUB_USB_PORT_ERRORS_MAX) {
+ DPRINTFN(4, "port %d, HUB looks dead, too many errors\n", portno);
+ sc->sc_st.port_status = 0;
+ sc->sc_st.port_change = 0;
+ return (USB_ERR_TIMEOUT);
+ }
+
err = usbd_req_get_port_status(
sc->sc_udev, NULL, &ps, portno);
- /* update status regardless of error */
-
- sc->sc_st.port_status = UGETW(ps.wPortStatus);
- sc->sc_st.port_change = UGETW(ps.wPortChange);
+ if (err == 0) {
+ sc->sc_st.port_status = UGETW(ps.wPortStatus);
+ sc->sc_st.port_change = UGETW(ps.wPortChange);
+ sc->sc_usb_port_errors = 0;
+ } else {
+ sc->sc_st.port_status = 0;
+ sc->sc_st.port_change = 0;
+ sc->sc_usb_port_errors++;
+ }
/* debugging print */
@@ -1126,7 +1108,7 @@ uhub_explore(struct usb_device *udev)
return (USB_ERR_NORMAL_COMPLETION);
}
-static int
+int
uhub_probe(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
@@ -1140,7 +1122,7 @@ uhub_probe(device_t dev)
*/
if (uaa->info.bConfigIndex == 0 &&
uaa->info.bDeviceClass == UDCLASS_HUB)
- return (0);
+ return (BUS_PROBE_DEFAULT);
return (ENXIO);
}
@@ -1206,7 +1188,7 @@ uhub_query_info(struct usb_device *udev, uint8_t *pnports, uint8_t *ptt)
return (err);
}
-static int
+int
uhub_attach(device_t dev)
{
struct uhub_softc *sc = device_get_softc(dev);
@@ -1552,7 +1534,7 @@ error:
* Called from process context when the hub is gone.
* Detach all devices on active ports.
*/
-static int
+int
uhub_detach(device_t dev)
{
struct uhub_softc *sc = device_get_softc(dev);
@@ -1622,13 +1604,7 @@ uhub_driver_added(device_t dev, driver_t *driver)
usb_needs_explore_all();
}
-struct hub_result {
- struct usb_device *udev;
- uint8_t portno;
- uint8_t iface_index;
-};
-
-static void
+void
uhub_find_iface_index(struct usb_hub *hub, device_t child,
struct hub_result *res)
{
@@ -1661,7 +1637,7 @@ uhub_find_iface_index(struct usb_hub *hub, device_t child,
res->portno = 0;
}
-static int
+int
uhub_child_location_string(device_t parent, device_t child,
char *buf, size_t buflen)
{
diff --git a/freebsd/sys/dev/usb/usb_hub_private.h b/freebsd/sys/dev/usb/usb_hub_private.h
new file mode 100644
index 00000000..1151ed7d
--- /dev/null
+++ b/freebsd/sys/dev/usb/usb_hub_private.h
@@ -0,0 +1,86 @@
+/* $FreeBSD$ */
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-NetBSD
+ *
+ * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
+ * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
+ * Copyright (c) 2008-2010 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * USB spec: http://www.usb.org/developers/docs/usbspec.zip
+ */
+
+#ifndef USB_HUB_PRIVATE_H_
+#define USB_HUB_PRIVATE_H_
+#define UHUB_INTR_INTERVAL 250 /* ms */
+
+enum {
+ UHUB_INTR_TRANSFER,
+#if USB_HAVE_TT_SUPPORT
+ UHUB_RESET_TT_TRANSFER,
+#endif
+ UHUB_N_TRANSFER,
+};
+
+
+struct uhub_current_state {
+ uint16_t port_change;
+ uint16_t port_status;
+};
+
+struct uhub_softc {
+ struct uhub_current_state sc_st; /* current state */
+#if (USB_HAVE_FIXED_PORT != 0)
+ struct usb_hub sc_hub;
+#endif
+ device_t sc_dev; /* base device */
+ struct mtx sc_mtx; /* our mutex */
+ struct usb_device *sc_udev; /* USB device */
+ struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */
+#if USB_HAVE_DISABLE_ENUM
+ int sc_disable_enumeration;
+ int sc_disable_port_power;
+#endif
+ uint8_t sc_usb_port_errors; /* error counter */
+#define UHUB_USB_PORT_ERRORS_MAX 4
+ uint8_t sc_flags;
+#define UHUB_FLAG_DID_EXPLORE 0x01
+};
+struct hub_result {
+ struct usb_device *udev;
+ uint8_t portno;
+ uint8_t iface_index;
+};
+
+void
+uhub_find_iface_index(struct usb_hub *hub, device_t child,
+ struct hub_result *res);
+
+device_probe_t uhub_probe;
+device_attach_t uhub_attach;
+device_detach_t uhub_detach;
+bus_child_location_str_t uhub_child_location_string;
+
+#endif
diff --git a/freebsd/sys/dev/usb/usb_ioctl.h b/freebsd/sys/dev/usb/usb_ioctl.h
index fcd31e31..c4023cab 100644
--- a/freebsd/sys/dev/usb/usb_ioctl.h
+++ b/freebsd/sys/dev/usb/usb_ioctl.h
@@ -70,6 +70,7 @@ enum {
USB_TEMP_SERIALNET, /* USB CDC Ethernet and Modem */
USB_TEMP_MIDI, /* USB MIDI */
USB_TEMP_MULTI, /* USB Ethernet, serial, and storage */
+ USB_TEMP_CDCEEM, /* USB Ethernet Emulation Model */
USB_TEMP_MAX,
};
@@ -223,7 +224,7 @@ struct usb_fs_uninit {
} USB_IOCTL_STRUCT_ALIGN(1);
struct usb_fs_open {
-#define USB_FS_MAX_BUFSIZE (1 << 18)
+#define USB_FS_MAX_BUFSIZE (1 << 25) /* 32 MBytes */
uint32_t max_bufsize;
#define USB_FS_MAX_FRAMES (1U << 12)
#define USB_FS_MAX_FRAMES_PRE_SCALE (1U << 31) /* for ISOCHRONOUS transfers */
diff --git a/freebsd/sys/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c
index d2a15f3c..f288378e 100644
--- a/freebsd/sys/dev/usb/usb_request.c
+++ b/freebsd/sys/dev/usb/usb_request.c
@@ -1603,8 +1603,9 @@ usbd_req_get_port_status(struct usb_device *udev, struct mtx *mtx,
USETW(req.wValue, 0);
req.wIndex[0] = port;
req.wIndex[1] = 0;
- USETW(req.wLength, sizeof *ps);
- return (usbd_do_request(udev, mtx, &req, ps));
+ USETW(req.wLength, sizeof(*ps));
+
+ return (usbd_do_request_flags(udev, mtx, &req, ps, 0, NULL, 1000));
}
/*------------------------------------------------------------------------*
diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c
index 7ea25337..3b67c20c 100644
--- a/freebsd/sys/dev/usb/usb_transfer.c
+++ b/freebsd/sys/dev/usb/usb_transfer.c
@@ -111,6 +111,33 @@ static const struct usb_config usb_control_ep_cfg[USB_CTRL_XFER_MAX] = {
},
};
+static const struct usb_config usb_control_ep_quirk_cfg[USB_CTRL_XFER_MAX] = {
+
+ /* This transfer is used for generic control endpoint transfers */
+
+ [0] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control endpoint */
+ .direction = UE_DIR_ANY,
+ .bufsize = 65535, /* bytes */
+ .callback = &usb_request_callback,
+ .usb_mode = USB_MODE_DUAL, /* both modes */
+ },
+
+ /* This transfer is used for generic clear stall only */
+
+ [1] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = UE_DIR_ANY,
+ .bufsize = sizeof(struct usb_device_request),
+ .callback = &usb_do_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
+ .usb_mode = USB_MODE_HOST,
+ },
+};
+
/* function prototypes */
static void usbd_update_max_frame_size(struct usb_xfer *);
@@ -1051,7 +1078,8 @@ usbd_transfer_setup(struct usb_device *udev,
* context, else there is a chance of
* deadlock!
*/
- if (setup_start == usb_control_ep_cfg)
+ if (setup_start == usb_control_ep_cfg ||
+ setup_start == usb_control_ep_quirk_cfg)
info->done_p =
USB_BUS_CONTROL_XFER_PROC(udev->bus);
else if (xfer_mtx == &Giant)
@@ -3179,7 +3207,8 @@ repeat:
*/
iface_index = 0;
if (usbd_transfer_setup(udev, &iface_index,
- udev->ctrl_xfer, usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL,
+ udev->ctrl_xfer, udev->bus->control_ep_quirk ?
+ usb_control_ep_quirk_cfg : usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL,
&udev->device_mtx)) {
DPRINTFN(0, "could not setup default "
"USB transfer\n");
diff --git a/freebsd/sys/dev/usb/usbdi.h b/freebsd/sys/dev/usb/usbdi.h
index d5648c03..0a393844 100644
--- a/freebsd/sys/dev/usb/usbdi.h
+++ b/freebsd/sys/dev/usb/usbdi.h
@@ -105,7 +105,7 @@ typedef void (usb_fifo_filter_t)(struct usb_fifo *fifo, struct usb_mbuf *m);
/* USB events */
#ifndef USB_GLOBAL_INCLUDE_FILE
-#include <sys/eventhandler.h>
+#include <sys/_eventhandler.h>
#endif
typedef void (*usb_dev_configured_t)(void *, struct usb_device *,
struct usb_attach_arg *);
diff --git a/freebsd/sys/dev/usb/wlan/if_rsu.c b/freebsd/sys/dev/usb/wlan/if_rsu.c
index b730ce59..112b8675 100644
--- a/freebsd/sys/dev/usb/wlan/if_rsu.c
+++ b/freebsd/sys/dev/usb/wlan/if_rsu.c
@@ -44,13 +44,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/bus.h>
-#include <sys/rman.h>
#include <sys/firmware.h>
#include <sys/module.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -291,9 +287,6 @@ MODULE_DEPEND(rsu, firmware, 1, 1, 1);
MODULE_VERSION(rsu, 1);
USB_PNP_HOST_INFO(rsu_devs);
-static const uint8_t rsu_chan_2ghz[] =
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
-
static uint8_t rsu_wme_ac_xfer_map[4] = {
[WME_AC_BE] = RSU_BULK_TX_BE_BK,
[WME_AC_BK] = RSU_BULK_TX_BE_BK,
@@ -789,9 +782,8 @@ rsu_getradiocaps(struct ieee80211com *ic,
setbit(bands, IEEE80211_MODE_11G);
if (sc->sc_ht)
setbit(bands, IEEE80211_MODE_11NG);
- ieee80211_add_channel_list_2ghz(chans, maxchans, nchans,
- rsu_chan_2ghz, nitems(rsu_chan_2ghz), bands,
- (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) != 0);
+ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans,
+ bands, (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) != 0);
}
static void
@@ -2460,8 +2452,6 @@ rsu_rx_frame(struct rsu_softc *sc, struct mbuf *m)
tap->wr_rate = rxs.c_rate;
tap->wr_dbm_antsignal = rssi;
- tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
};
(void) ieee80211_add_rx_params(m, &rxs);
@@ -2762,15 +2752,16 @@ static int
rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, struct rsu_data *data)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ const struct ieee80211_txparam *tp = ni->ni_txparms;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ieee80211_key *k = NULL;
struct r92s_tx_desc *txd;
- uint8_t type, cipher;
+ uint8_t rate, ridx, type, cipher, qos;
int prio = 0;
uint8_t which;
int hasqos;
+ int ismcast;
int xferlen;
int qid;
@@ -2778,10 +2769,26 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
wh = mtod(m0, struct ieee80211_frame *);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+ ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
RSU_DPRINTF(sc, RSU_DEBUG_TX, "%s: data=%p, m=%p\n",
__func__, data, m0);
+ /* Choose a TX rate index. */
+ if (type == IEEE80211_FC0_TYPE_MGT ||
+ type == IEEE80211_FC0_TYPE_CTL ||
+ (m0->m_flags & M_EAPOL) != 0)
+ rate = tp->mgmtrate;
+ else if (ismcast)
+ rate = tp->mcastrate;
+ else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
+ rate = tp->ucastrate;
+ else
+ rate = 0;
+
+ if (rate != 0)
+ ridx = rate2ridx(rate);
+
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
k = ieee80211_crypto_encap(ni, m0);
if (k == NULL) {
@@ -2799,12 +2806,14 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
prio = M_WME_GETAC(m0);
which = rsu_wme_ac_xfer_map[prio];
hasqos = 1;
+ qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0];
} else {
/* Non-QoS TID */
/* XXX TODO: tid=0 for non-qos TID? */
which = rsu_wme_ac_xfer_map[WME_AC_BE];
hasqos = 0;
prio = 0;
+ qos = 0;
}
qid = rsu_ac2qid[prio];
@@ -2860,8 +2869,23 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
}
/* XXX todo: set AGGEN bit if appropriate? */
txd->txdw2 |= htole32(R92S_TXDW2_BK);
- if (IEEE80211_IS_MULTICAST(wh->i_addr1))
+ if (ismcast)
txd->txdw2 |= htole32(R92S_TXDW2_BMCAST);
+
+ if (!ismcast && (!qos || (qos & IEEE80211_QOS_ACKPOLICY) !=
+ IEEE80211_QOS_ACKPOLICY_NOACK)) {
+ txd->txdw2 |= htole32(R92S_TXDW2_RTY_LMT_ENA);
+ txd->txdw2 |= htole32(SM(R92S_TXDW2_RTY_LMT, tp->maxretry));
+ }
+
+ /* Force mgmt / mcast / ucast rate if needed. */
+ if (rate != 0) {
+ /* Data rate fallback limit (max). */
+ txd->txdw5 |= htole32(SM(R92S_TXDW5_DATARATE_FB_LMT, 0x1f));
+ txd->txdw5 |= htole32(SM(R92S_TXDW5_DATARATE, ridx));
+ txd->txdw4 |= htole32(R92S_TXDW4_DRVRATE);
+ }
+
/*
* Firmware will use and increment the sequence number for the
* specified priority.
@@ -2872,8 +2896,6 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
struct rsu_tx_radiotap_header *tap = &sc->sc_txtap;
tap->wt_flags = 0;
- tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
ieee80211_radiotap_tx(vap, m0);
}
diff --git a/freebsd/sys/dev/usb/wlan/if_rsureg.h b/freebsd/sys/dev/usb/wlan/if_rsureg.h
index 973280cf..246b06b7 100644
--- a/freebsd/sys/dev/usb/wlan/if_rsureg.h
+++ b/freebsd/sys/dev/usb/wlan/if_rsureg.h
@@ -688,6 +688,9 @@ struct r92s_tx_desc {
#define R92S_TXDW1_HWPC 0x80000000
uint32_t txdw2;
+#define R92S_TXDW2_RTY_LMT_M 0x0000003f
+#define R92S_TXDW2_RTY_LMT_S 0
+#define R92S_TXDW2_RTY_LMT_ENA 0x00000040
#define R92S_TXDW2_BMCAST 0x00000080
#define R92S_TXDW2_AGGEN 0x20000000
#define R92S_TXDW2_BK 0x40000000
@@ -700,9 +703,14 @@ struct r92s_tx_desc {
uint32_t txdw4;
#define R92S_TXDW4_TXBW 0x00040000
+#define R92S_TXDW4_DRVRATE 0x80000000
uint32_t txdw5;
-#define R92S_TXDW5_DISFB 0x00008000
+#define R92S_TXDW5_DATARATE_M 0x00007e00
+#define R92S_TXDW5_DATARATE_S 9
+#define R92S_TXDW5_DISFB 0x00008000
+#define R92S_TXDW5_DATARATE_FB_LMT_M 0x001f0000
+#define R92S_TXDW5_DATARATE_FB_LMT_S 16
uint16_t ipchksum;
uint16_t tcpchksum;
@@ -792,9 +800,10 @@ struct rsu_rx_radiotap_header {
struct rsu_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
+ uint8_t wt_pad;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define RSU_TX_RADIOTAP_PRESENT \
(1 << IEEE80211_RADIOTAP_FLAGS | \
diff --git a/freebsd/sys/dev/usb/wlan/if_rum.c b/freebsd/sys/dev/usb/wlan/if_rum.c
index 5c826cac..c2f68406 100644
--- a/freebsd/sys/dev/usb/wlan/if_rum.c
+++ b/freebsd/sys/dev/usb/wlan/if_rum.c
@@ -46,10 +46,6 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/kdb.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -344,9 +340,6 @@ static const struct {
{ 107, 0x04 }
};
-static const uint8_t rum_chan_2ghz[] =
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
-
static const uint8_t rum_chan_5ghz[] =
{ 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
@@ -3222,8 +3215,7 @@ rum_getradiocaps(struct ieee80211com *ic,
memset(bands, 0, sizeof(bands));
setbit(bands, IEEE80211_MODE_11B);
setbit(bands, IEEE80211_MODE_11G);
- ieee80211_add_channel_list_2ghz(chans, maxchans, nchans,
- rum_chan_2ghz, nitems(rum_chan_2ghz), bands, 0);
+ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_5226) {
setbit(bands, IEEE80211_MODE_11A);
diff --git a/freebsd/sys/dev/usb/wlan/if_rumvar.h b/freebsd/sys/dev/usb/wlan/if_rumvar.h
index 4ff831f4..e19a7088 100644
--- a/freebsd/sys/dev/usb/wlan/if_rumvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_rumvar.h
@@ -49,7 +49,7 @@ struct rum_tx_radiotap_header {
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_antenna;
-} __packed __aligned(8);
+} __packed;
#define RT2573_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_run.c b/freebsd/sys/dev/usb/wlan/if_run.c
index 3bd247e3..9f11a3a3 100644
--- a/freebsd/sys/dev/usb/wlan/if_run.c
+++ b/freebsd/sys/dev/usb/wlan/if_run.c
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/opt_wlan.h>
#include <sys/param.h>
+#include <sys/eventhandler.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/lock.h>
@@ -46,10 +47,6 @@ __FBSDID("$FreeBSD$");
#include <sys/firmware.h>
#include <sys/kdb.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -470,6 +467,7 @@ static void run_usb_timeout_cb(void *);
static void run_reset_livelock(struct run_softc *);
static void run_enable_tsf_sync(struct run_softc *);
static void run_enable_tsf(struct run_softc *);
+static void run_disable_tsf(struct run_softc *);
static void run_get_tsf(struct run_softc *, uint64_t *);
static void run_enable_mrr(struct run_softc *);
static void run_set_txpreamble(struct run_softc *);
@@ -2035,7 +2033,8 @@ run_read_eeprom(struct run_softc *sc)
static struct ieee80211_node *
run_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
{
- return malloc(sizeof (struct run_node), M_DEVBUF, M_NOWAIT | M_ZERO);
+ return malloc(sizeof (struct run_node), M_80211_NODE,
+ M_NOWAIT | M_ZERO);
}
static int
@@ -2095,7 +2094,6 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
struct run_vap *rvp = RUN_VAP(vap);
enum ieee80211_state ostate;
uint32_t sta[3];
- uint32_t tmp;
uint8_t ratectl;
uint8_t restart_ratectl = 0;
uint8_t bid = 1 << rvp->rvp_id;
@@ -2128,12 +2126,8 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
sc->runbmap &= ~bid;
/* abort TSF synchronization if there is no vap running */
- if (--sc->running == 0) {
- run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
- run_write(sc, RT2860_BCN_TIME_CFG,
- tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
- RT2860_TBTT_TIMER_EN));
- }
+ if (--sc->running == 0)
+ run_disable_tsf(sc);
break;
case IEEE80211_S_RUN:
@@ -2826,76 +2820,83 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
uint8_t ant, rssi;
int8_t nf;
- rxwi = mtod(m, struct rt2860_rxwi *);
- len = le16toh(rxwi->len) & 0xfff;
rxwisize = sizeof(struct rt2860_rxwi);
if (sc->mac_ver == 0x5592)
rxwisize += sizeof(uint64_t);
else if (sc->mac_ver == 0x3593)
rxwisize += sizeof(uint32_t);
- if (__predict_false(len > dmalen)) {
- m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
+
+ if (__predict_false(dmalen <
+ rxwisize + sizeof(struct ieee80211_frame_ack))) {
+ RUN_DPRINTF(sc, RUN_DEBUG_RECV,
+ "payload is too short: dma length %u < %zu\n",
+ dmalen, rxwisize + sizeof(struct ieee80211_frame_ack));
+ goto fail;
+ }
+
+ rxwi = mtod(m, struct rt2860_rxwi *);
+ len = le16toh(rxwi->len) & 0xfff;
+
+ if (__predict_false(len > dmalen - rxwisize)) {
RUN_DPRINTF(sc, RUN_DEBUG_RECV,
"bad RXWI length %u > %u\n", len, dmalen);
- return;
+ goto fail;
}
+
/* Rx descriptor is located at the end */
rxd = (struct rt2870_rxd *)(mtod(m, caddr_t) + dmalen);
flags = le32toh(rxd->flags);
if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
- m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
RUN_DPRINTF(sc, RUN_DEBUG_RECV, "%s error.\n",
(flags & RT2860_RX_CRCERR)?"CRC":"ICV");
- return;
+ goto fail;
+ }
+
+ if (flags & RT2860_RX_L2PAD) {
+ RUN_DPRINTF(sc, RUN_DEBUG_RECV,
+ "received RT2860_RX_L2PAD frame\n");
+ len += 2;
}
m->m_data += rxwisize;
- m->m_pkthdr.len = m->m_len -= rxwisize;
+ m->m_pkthdr.len = m->m_len = len;
wh = mtod(m, struct ieee80211_frame *);
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 &&
+ (flags & RT2860_RX_DEC) != 0) {
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
m->m_flags |= M_WEP;
}
- if (flags & RT2860_RX_L2PAD) {
- RUN_DPRINTF(sc, RUN_DEBUG_RECV,
- "received RT2860_RX_L2PAD frame\n");
- len += 2;
- }
-
- ni = ieee80211_find_rxnode(ic,
- mtod(m, struct ieee80211_frame_min *));
+ if (len >= sizeof(struct ieee80211_frame_min)) {
+ ni = ieee80211_find_rxnode(ic,
+ mtod(m, struct ieee80211_frame_min *));
+ } else
+ ni = NULL;
if (__predict_false(flags & RT2860_RX_MICERR)) {
/* report MIC failures to net80211 for TKIP */
if (ni != NULL)
ieee80211_notify_michael_failure(ni->ni_vap, wh,
rxwi->keyidx);
- m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
RUN_DPRINTF(sc, RUN_DEBUG_RECV,
"MIC error. Someone is lying.\n");
- return;
+ goto fail;
}
ant = run_maxrssi_chain(sc, rxwi);
rssi = rxwi->rssi[ant];
nf = run_rssi2dbm(sc, rssi, ant);
- m->m_pkthdr.len = m->m_len = len;
-
if (__predict_false(ieee80211_radiotap_active(ic))) {
struct run_rx_radiotap_header *tap = &sc->sc_rxtap;
uint16_t phy;
tap->wr_flags = 0;
- tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ if (flags & RT2860_RX_L2PAD)
+ tap->wr_flags |= IEEE80211_RADIOTAP_F_DATAPAD;
tap->wr_antsignal = rssi;
tap->wr_antenna = ant;
tap->wr_dbm_antsignal = run_rssi2dbm(sc, rssi, ant);
@@ -2936,6 +2937,12 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
} else {
(void)ieee80211_input_all(ic, m, rssi, nf);
}
+
+ return;
+
+fail:
+ m_freem(m);
+ counter_u64_add(ic->ic_ierrors, 1);
}
static void
@@ -2945,7 +2952,7 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *m = NULL;
struct mbuf *m0;
- uint32_t dmalen;
+ uint32_t dmalen, mbuf_len;
uint16_t rxwisize;
int xferlen;
@@ -3051,6 +3058,14 @@ tr_setup:
break;
}
+ mbuf_len = dmalen + sizeof(struct rt2870_rxd);
+ if (__predict_false(mbuf_len > MCLBYTES)) {
+ RUN_DPRINTF(sc, RUN_DEBUG_RECV_DESC | RUN_DEBUG_USB,
+ "payload is too big: mbuf_len %u\n", mbuf_len);
+ counter_u64_add(ic->ic_ierrors, 1);
+ break;
+ }
+
/* copy aggregated frames to another mbuf */
m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m0 == NULL)) {
@@ -3060,14 +3075,13 @@ tr_setup:
break;
}
m_copydata(m, 4 /* skip 32-bit DMA-len header */,
- dmalen + sizeof(struct rt2870_rxd), mtod(m0, caddr_t));
- m0->m_pkthdr.len = m0->m_len =
- dmalen + sizeof(struct rt2870_rxd);
+ mbuf_len, mtod(m0, caddr_t));
+ m0->m_pkthdr.len = m0->m_len = mbuf_len;
run_rx_frame(sc, m0, dmalen);
/* update data ptr */
- m->m_data += dmalen + 8;
- m->m_pkthdr.len = m->m_len -= dmalen + 8;
+ m->m_data += mbuf_len + 4;
+ m->m_pkthdr.len = m->m_len -= mbuf_len + 4;
}
/* make sure we free the source buffer, if any */
@@ -3149,16 +3163,23 @@ tr_setup:
vap = data->ni->ni_vap;
if (ieee80211_radiotap_active_vap(vap)) {
+ const struct ieee80211_frame *wh;
struct run_tx_radiotap_header *tap = &sc->sc_txtap;
struct rt2860_txwi *txwi =
(struct rt2860_txwi *)(&data->desc + sizeof(struct rt2870_txd));
+ int has_l2pad;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ has_l2pad = IEEE80211_HAS_ADDR4(wh) !=
+ IEEE80211_QOS_HAS_SEQ(wh);
+
tap->wt_flags = 0;
tap->wt_rate = rt2860_rates[data->ridx].rate;
- tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
tap->wt_hwqueue = index;
if (le16toh(txwi->phy) & RT2860_PHY_SHPRE)
tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+ if (has_l2pad)
+ tap->wt_flags |= IEEE80211_RADIOTAP_F_DATAPAD;
ieee80211_radiotap_tx(vap, m);
}
@@ -3350,11 +3371,7 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
if ((hasqos = IEEE80211_QOS_HAS_SEQ(wh))) {
uint8_t *frm;
- if(IEEE80211_HAS_ADDR4(wh))
- frm = ((struct ieee80211_qosframe_addr4 *)wh)->i_qos;
- else
- frm =((struct ieee80211_qosframe *)wh)->i_qos;
-
+ frm = ieee80211_getqos(wh);
qos = le16toh(*(const uint16_t *)frm);
tid = qos & IEEE80211_QOS_TID;
qid = TID_TO_WME_AC(tid);
@@ -4837,8 +4854,7 @@ run_getradiocaps(struct ieee80211com *ic,
memset(bands, 0, sizeof(bands));
setbit(bands, IEEE80211_MODE_11B);
setbit(bands, IEEE80211_MODE_11G);
- ieee80211_add_channel_list_2ghz(chans, maxchans, nchans,
- run_chan_2ghz, nitems(run_chan_2ghz), bands, 0);
+ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 ||
sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 ||
@@ -4853,15 +4869,11 @@ static void
run_scan_start(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_softc;
- uint32_t tmp;
RUN_LOCK(sc);
/* abort TSF synchronization */
- run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
- run_write(sc, RT2860_BCN_TIME_CFG,
- tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
- RT2860_TBTT_TIMER_EN));
+ run_disable_tsf(sc);
run_set_bssid(sc, ieee80211broadcastaddr);
RUN_UNLOCK(sc);
@@ -5148,6 +5160,18 @@ run_enable_tsf(struct run_softc *sc)
}
static void
+run_disable_tsf(struct run_softc *sc)
+{
+ uint32_t tmp;
+
+ if (run_read(sc, RT2860_BCN_TIME_CFG, &tmp) == 0) {
+ tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
+ RT2860_TBTT_TIMER_EN);
+ run_write(sc, RT2860_BCN_TIME_CFG, tmp);
+ }
+}
+
+static void
run_get_tsf(struct run_softc *sc, uint64_t *buf)
{
run_read_region_1(sc, RT2860_TSF_TIMER_DW0, (uint8_t *)buf,
@@ -6098,10 +6122,7 @@ run_init_locked(struct run_softc *sc)
}
/* abort TSF synchronization */
- run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
- tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
- RT2860_TBTT_TIMER_EN);
- run_write(sc, RT2860_BCN_TIME_CFG, tmp);
+ run_disable_tsf(sc);
/* clear RX WCID search table */
run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512);
diff --git a/freebsd/sys/dev/usb/wlan/if_runreg.h b/freebsd/sys/dev/usb/wlan/if_runreg.h
index c09aac8f..8561d2c1 100644
--- a/freebsd/sys/dev/usb/wlan/if_runreg.h
+++ b/freebsd/sys/dev/usb/wlan/if_runreg.h
@@ -1086,9 +1086,6 @@ struct rt2860_rxwi {
/*
* Channel map for run(4) driver; taken from the table below.
*/
-static const uint8_t run_chan_2ghz[] =
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
-
static const uint8_t run_chan_5ghz[] =
{ 36, 38, 40, 44, 46, 48, 52, 54, 56, 60, 62, 64, 100, 102, 104,
108, 110, 112, 116, 118, 120, 124, 126, 128, 132, 134, 136, 140,
diff --git a/freebsd/sys/dev/usb/wlan/if_runvar.h b/freebsd/sys/dev/usb/wlan/if_runvar.h
index 7209bfc7..a17d5b46 100644
--- a/freebsd/sys/dev/usb/wlan/if_runvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_runvar.h
@@ -71,7 +71,7 @@ struct run_tx_radiotap_header {
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_hwqueue;
-} __packed __aligned(8);
+} __packed;
#define IEEE80211_RADIOTAP_HWQUEUE 15
diff --git a/freebsd/sys/dev/usb/wlan/if_uath.c b/freebsd/sys/dev/usb/wlan/if_uath.c
index 2b97060e..9f0c9d5d 100644
--- a/freebsd/sys/dev/usb/wlan/if_uath.c
+++ b/freebsd/sys/dev/usb/wlan/if_uath.c
@@ -87,10 +87,6 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/kdb.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -1282,8 +1278,8 @@ uath_watchdog(void *arg)
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- /*uath_init(sc); XXX needs a process context! */
counter_u64_add(ic->ic_oerrors, 1);
+ ieee80211_restart_all(ic);
return;
}
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
diff --git a/freebsd/sys/dev/usb/wlan/if_uathvar.h b/freebsd/sys/dev/usb/wlan/if_uathvar.h
index a38f54fc..a0ef4eab 100644
--- a/freebsd/sys/dev/usb/wlan/if_uathvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_uathvar.h
@@ -67,9 +67,10 @@ struct uath_rx_radiotap_header {
struct uath_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
+ uint8_t wt_pad;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define UATH_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_upgt.c b/freebsd/sys/dev/usb/wlan/if_upgt.c
index e1923bab..c556d108 100644
--- a/freebsd/sys/dev/usb/wlan/if_upgt.c
+++ b/freebsd/sys/dev/usb/wlan/if_upgt.c
@@ -43,7 +43,6 @@
#include <net/if_types.h>
#include <sys/bus.h>
-#include <machine/bus.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_phy.h>
@@ -1618,7 +1617,7 @@ upgt_fw_load(struct upgt_softc *sc)
data_cmd->buflen = bsize;
upgt_bulk_tx(sc, data_cmd);
- DPRINTF(sc, UPGT_DEBUG_FW, "FW offset=%d, read=%d, sent=%d\n",
+ DPRINTF(sc, UPGT_DEBUG_FW, "FW offset=%zu, read=%d, sent=%d\n",
offset, n, bsize);
bsize = n;
}
@@ -1775,7 +1774,7 @@ upgt_fw_verify(struct upgt_softc *sc)
}
DPRINTF(sc, UPGT_DEBUG_FW,
- "firmware Boot Record Area found at offset %d\n", offset);
+ "firmware Boot Record Area found at offset %zu\n", offset);
/*
* Parse Boot Record Area (BRA) options.
diff --git a/freebsd/sys/dev/usb/wlan/if_upgtvar.h b/freebsd/sys/dev/usb/wlan/if_upgtvar.h
index ce996f6a..9d4c85e6 100644
--- a/freebsd/sys/dev/usb/wlan/if_upgtvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_upgtvar.h
@@ -394,7 +394,7 @@ struct upgt_tx_radiotap_header {
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define UPGT_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_ural.c b/freebsd/sys/dev/usb/wlan/if_ural.c
index 4de0a9c5..8897f148 100644
--- a/freebsd/sys/dev/usb/wlan/if_ural.c
+++ b/freebsd/sys/dev/usb/wlan/if_ural.c
@@ -47,10 +47,6 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/kdb.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -363,9 +359,6 @@ static const struct {
{ 161, 0x08808, 0x0242f, 0x00281 }
};
-static const uint8_t ural_chan_2ghz[] =
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
-
static const uint8_t ural_chan_5ghz[] =
{ 36, 40, 44, 48, 52, 56, 60, 64,
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
@@ -1593,8 +1586,7 @@ ural_getradiocaps(struct ieee80211com *ic,
memset(bands, 0, sizeof(bands));
setbit(bands, IEEE80211_MODE_11B);
setbit(bands, IEEE80211_MODE_11G);
- ieee80211_add_channel_list_2ghz(chans, maxchans, nchans,
- ural_chan_2ghz, nitems(ural_chan_2ghz), bands, 0);
+ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
if (sc->rf_rev == RAL_RF_5222) {
setbit(bands, IEEE80211_MODE_11A);
diff --git a/freebsd/sys/dev/usb/wlan/if_uralvar.h b/freebsd/sys/dev/usb/wlan/if_uralvar.h
index dd863fe0..b59b7911 100644
--- a/freebsd/sys/dev/usb/wlan/if_uralvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_uralvar.h
@@ -51,7 +51,7 @@ struct ural_tx_radiotap_header {
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_antenna;
-} __packed __aligned(8);
+} __packed;
#define RAL_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_urtw.c b/freebsd/sys/dev/usb/wlan/if_urtw.c
index 309375f0..aba334af 100644
--- a/freebsd/sys/dev/usb/wlan/if_urtw.c
+++ b/freebsd/sys/dev/usb/wlan/if_urtw.c
@@ -36,10 +36,6 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/kdb.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
@@ -217,9 +213,6 @@ static uint8_t urtw_8225z2_agc[] = {
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
};
-static const uint8_t urtw_chan_2ghz[] =
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
-
static uint32_t urtw_8225_channel[] = {
0x0000, /* dummy channel 0 */
0x085c, /* 1 */
@@ -679,6 +672,7 @@ static void urtw_scan_end(struct ieee80211com *);
static void urtw_getradiocaps(struct ieee80211com *, int, int *,
struct ieee80211_channel[]);
static void urtw_set_channel(struct ieee80211com *);
+static void urtw_update_promisc(struct ieee80211com *);
static void urtw_update_mcast(struct ieee80211com *);
static int urtw_tx_start(struct urtw_softc *,
struct ieee80211_node *, struct mbuf *,
@@ -760,6 +754,7 @@ static void urtw_free_tx_data_list(struct urtw_softc *);
static void urtw_free_rx_data_list(struct urtw_softc *);
static void urtw_free_data_list(struct urtw_softc *,
struct urtw_data data[], int, int);
+static usb_error_t urtw_set_macaddr(struct urtw_softc *, const uint8_t *);
static usb_error_t urtw_adapter_start(struct urtw_softc *);
static usb_error_t urtw_adapter_start_b(struct urtw_softc *);
static usb_error_t urtw_set_mode(struct urtw_softc *, uint32_t);
@@ -905,6 +900,7 @@ urtw_attach(device_t dev)
ic->ic_updateslot = urtw_updateslot;
ic->ic_vap_create = urtw_vap_create;
ic->ic_vap_delete = urtw_vap_delete;
+ ic->ic_update_promisc = urtw_update_promisc;
ic->ic_update_mcast = urtw_update_mcast;
ic->ic_parent = urtw_parent;
ic->ic_transmit = urtw_transmit;
@@ -1194,9 +1190,23 @@ fail:
}
static usb_error_t
+urtw_set_macaddr(struct urtw_softc *sc, const uint8_t *macaddr)
+{
+ usb_error_t error;
+
+ urtw_write32_m(sc, URTW_MAC0, ((const uint32_t *)macaddr)[0]);
+ urtw_write16_m(sc, URTW_MAC4, ((const uint32_t *)macaddr)[1] & 0xffff);
+
+fail:
+ return (error);
+}
+
+static usb_error_t
urtw_adapter_start(struct urtw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ const uint8_t *macaddr;
usb_error_t error;
error = urtw_reset(sc);
@@ -1216,8 +1226,11 @@ urtw_adapter_start(struct urtw_softc *sc)
if (error)
goto fail;
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
+ macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr;
+ urtw_set_macaddr(sc, macaddr);
+ if (error)
+ goto fail;
+
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
goto fail;
@@ -1587,8 +1600,7 @@ urtw_getradiocaps(struct ieee80211com *ic,
memset(bands, 0, sizeof(bands));
setbit(bands, IEEE80211_MODE_11B);
setbit(bands, IEEE80211_MODE_11G);
- ieee80211_add_channel_list_2ghz(chans, maxchans, nchans,
- urtw_chan_2ghz, nitems(urtw_chan_2ghz), bands, 0);
+ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
}
static void
@@ -1641,6 +1653,17 @@ fail:
}
static void
+urtw_update_promisc(struct ieee80211com *ic)
+{
+ struct urtw_softc *sc = ic->ic_softc;
+
+ URTW_LOCK(sc);
+ if (sc->sc_flags & URTW_RUNNING)
+ urtw_rx_setconf(sc);
+ URTW_UNLOCK(sc);
+}
+
+static void
urtw_update_mcast(struct ieee80211com *ic)
{
@@ -1694,11 +1717,7 @@ urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0,
if (ieee80211_radiotap_active_vap(vap)) {
struct urtw_tx_radiotap_header *tap = &sc->sc_txtap;
- /* XXX Are variables correct? */
tap->wt_flags = 0;
- tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
-
ieee80211_radiotap_tx(vap, m0);
}
@@ -1892,11 +1911,13 @@ static void
urtw_watchdog(void *arg)
{
struct urtw_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
if (sc->sc_txtimer > 0) {
if (--sc->sc_txtimer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ counter_u64_add(ic->ic_oerrors, 1);
+ ieee80211_restart_all(ic);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
@@ -3179,6 +3200,8 @@ static usb_error_t
urtw_8225v2b_rf_init(struct urtw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ const uint8_t *macaddr;
unsigned int i;
uint8_t data8;
usb_error_t error;
@@ -3226,8 +3249,10 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
urtw_write8_m(sc, URTW_CONFIG1, data8);
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
+ macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr;
+ error = urtw_set_macaddr(sc, macaddr);
+ if (error)
+ goto fail;
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
@@ -3887,7 +3912,6 @@ urtw_rx_setconf(struct urtw_softc *sc)
if (sc->sc_flags & URTW_RTL8187B) {
data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA |
URTW_RX_FILTER_MCAST | URTW_RX_FILTER_BCAST |
- URTW_RX_FILTER_NICMAC | URTW_RX_CHECK_BSSID |
URTW_RX_FIFO_THRESHOLD_NONE |
URTW_MAX_RX_DMA_2048 |
URTW_RX_AUTORESETPHY | URTW_RCR_ONLYERLPKT;
@@ -3902,14 +3926,6 @@ urtw_rx_setconf(struct urtw_softc *sc)
if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR)
data = data | URTW_RX_FILTER_CRCERR;
- if (ic->ic_opmode == IEEE80211_M_MONITOR ||
- ic->ic_promisc > 0 || ic->ic_allmulti > 0) {
- data = data | URTW_RX_FILTER_ALLMAC;
- } else {
- data = data | URTW_RX_FILTER_NICMAC;
- data = data | URTW_RX_CHECK_BSSID;
- }
-
data = data &~ URTW_RX_FIFO_THRESHOLD_MASK;
data = data | URTW_RX_FIFO_THRESHOLD_NONE |
URTW_RX_AUTORESETPHY;
@@ -3917,6 +3933,16 @@ urtw_rx_setconf(struct urtw_softc *sc)
data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT;
}
+ /* XXX allmulti should not be checked here... */
+ if (ic->ic_opmode == IEEE80211_M_MONITOR ||
+ ic->ic_promisc > 0 || ic->ic_allmulti > 0) {
+ data = data | URTW_RX_FILTER_CTL;
+ data = data | URTW_RX_FILTER_ALLMAC;
+ } else {
+ data = data | URTW_RX_FILTER_NICMAC;
+ data = data | URTW_RX_CHECK_BSSID;
+ }
+
urtw_write32_m(sc, URTW_RX, data);
fail:
return (error);
@@ -3932,50 +3958,56 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
struct urtw_softc *sc = data->sc;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t noise = 0, rate;
+ uint64_t mactime;
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
- if (actlen < (int)URTW_MIN_RXBUFSZ) {
- counter_u64_add(ic->ic_ierrors, 1);
- return (NULL);
- }
-
if (sc->sc_flags & URTW_RTL8187B) {
struct urtw_8187b_rxhdr *rx;
+ if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN)
+ goto fail;
+
rx = (struct urtw_8187b_rxhdr *)(data->buf +
(actlen - (sizeof(struct urtw_8187b_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
- if (flen > actlen) {
- counter_u64_add(ic->ic_ierrors, 1);
- return (NULL);
- }
+ if (flen > actlen - sizeof(*rx))
+ goto fail;
+
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
/* XXX correct? */
rssi = rx->rssi & URTW_RX_RSSI_MASK;
noise = rx->noise;
+
+ if (ieee80211_radiotap_active(ic))
+ mactime = rx->mactime;
} else {
struct urtw_8187l_rxhdr *rx;
+ if (actlen < sizeof(*rx) + IEEE80211_ACK_LEN)
+ goto fail;
+
rx = (struct urtw_8187l_rxhdr *)(data->buf +
(actlen - (sizeof(struct urtw_8187l_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
- if (flen > actlen) {
- counter_u64_add(ic->ic_ierrors, 1);
- return (NULL);
- }
+ if (flen > actlen - sizeof(*rx))
+ goto fail;
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
/* XXX correct? */
rssi = rx->rssi & URTW_RX_8187L_RSSI_MASK;
noise = rx->noise;
+
+ if (ieee80211_radiotap_active(ic))
+ mactime = rx->mactime;
}
+ if (flen < IEEE80211_ACK_LEN)
+ goto fail;
+
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
- if (mnew == NULL) {
- counter_u64_add(ic->ic_ierrors, 1);
- return (NULL);
- }
+ if (mnew == NULL)
+ goto fail;
m = data->m;
data->m = mnew;
@@ -3987,20 +4019,23 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
if (ieee80211_radiotap_active(ic)) {
struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap;
- /* XXX Are variables correct? */
- tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
- tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ tap->wr_tsf = mactime;
+ tap->wr_flags = 0;
tap->wr_dbm_antsignal = (int8_t)rssi;
}
wh = mtod(m, struct ieee80211_frame *);
- if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA)
+ if (IEEE80211_IS_DATA(wh))
sc->sc_currate = (rate > 0) ? rate : sc->sc_currate;
*rssi_p = rssi;
*nf_p = noise; /* XXX correct? */
return (m);
+
+fail:
+ counter_u64_add(ic->ic_ierrors, 1);
+ return (NULL);
}
static void
@@ -4008,7 +4043,6 @@ urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
struct urtw_data *data;
@@ -4046,9 +4080,13 @@ setup:
*/
URTW_UNLOCK(sc);
if (m != NULL) {
- wh = mtod(m, struct ieee80211_frame *);
- ni = ieee80211_find_rxnode(ic,
- (struct ieee80211_frame_min *)wh);
+ if (m->m_pkthdr.len >=
+ sizeof(struct ieee80211_frame_min)) {
+ ni = ieee80211_find_rxnode(ic,
+ mtod(m, struct ieee80211_frame_min *));
+ } else
+ ni = NULL;
+
if (ni != NULL) {
(void) ieee80211_input(ni, m, rssi, nf);
/* node is no longer needed */
diff --git a/freebsd/sys/dev/usb/wlan/if_urtwvar.h b/freebsd/sys/dev/usb/wlan/if_urtwvar.h
index 08ffc8f3..87c24d64 100644
--- a/freebsd/sys/dev/usb/wlan/if_urtwvar.h
+++ b/freebsd/sys/dev/usb/wlan/if_urtwvar.h
@@ -47,10 +47,6 @@ struct urtw_data {
};
typedef STAILQ_HEAD(, urtw_data) urtw_datahead;
-/* XXX not correct.. */
-#define URTW_MIN_RXBUFSZ \
- (sizeof(struct ieee80211_frame_min))
-
#define URTW_RX_DATA_LIST_COUNT 4
#define URTW_TX_DATA_LIST_COUNT 16
#define URTW_RX_MAXSIZE 0x9c4
@@ -59,23 +55,27 @@ typedef STAILQ_HEAD(, urtw_data) urtw_datahead;
struct urtw_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
+ uint64_t wr_tsf;
uint8_t wr_flags;
+ uint8_t wr_pad;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_dbm_antsignal;
} __packed __aligned(8);
#define URTW_RX_RADIOTAP_PRESENT \
- ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL))
struct urtw_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
+ uint8_t wt_pad;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define URTW_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/freebsd/sys/dev/usb/wlan/if_zyd.c b/freebsd/sys/dev/usb/wlan/if_zyd.c
index 1835b58b..bb4a9e40 100644
--- a/freebsd/sys/dev/usb/wlan/if_zyd.c
+++ b/freebsd/sys/dev/usb/wlan/if_zyd.c
@@ -46,10 +46,6 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/kdb.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -2891,8 +2887,7 @@ zyd_getradiocaps(struct ieee80211com *ic,
memset(bands, 0, sizeof(bands));
setbit(bands, IEEE80211_MODE_11B);
setbit(bands, IEEE80211_MODE_11G);
- ieee80211_add_channel_list_2ghz(chans, maxchans, nchans,
- zyd_chan_2ghz, nitems(zyd_chan_2ghz), bands, 0);
+ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
}
static void
diff --git a/freebsd/sys/dev/usb/wlan/if_zydreg.h b/freebsd/sys/dev/usb/wlan/if_zydreg.h
index 724b8c57..a4523199 100644
--- a/freebsd/sys/dev/usb/wlan/if_zydreg.h
+++ b/freebsd/sys/dev/usb/wlan/if_zydreg.h
@@ -421,10 +421,6 @@
#define ZYD_CR254 0x93f8
#define ZYD_CR255 0x93fc
-/* nitems(ZYD_*_CHANTABLE) */
-static const uint8_t zyd_chan_2ghz[] =
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
-
/* copied nearly verbatim from the Linux driver rewrite */
#define ZYD_DEF_PHY \
{ \
@@ -1204,7 +1200,7 @@ struct zyd_tx_radiotap_header {
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed __aligned(8);
+} __packed;
#define ZYD_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \