From 99fe2010dfe70b7c352dfdad118e2776a53819c5 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 31 Dec 2008 22:20:17 +0800 Subject: [PATCH 01/16] Add ale(4) for Atheros AR8121/AR8113/AR8114 PCIe ethernet controller. Obtained-from: FreeBSD (yongari@freebsd.org) --- share/man/man4/Makefile | 1 + share/man/man4/ale.4 | 143 ++ sys/dev/netif/Makefile | 2 +- sys/dev/netif/ale/Makefile | 6 + sys/dev/netif/ale/if_ale.c | 2754 +++++++++++++++++++++++++++++++++ sys/dev/netif/ale/if_alereg.h | 765 +++++++++ sys/dev/netif/ale/if_alevar.h | 248 +++ 7 files changed, 3918 insertions(+), 1 deletion(-) create mode 100644 share/man/man4/ale.4 create mode 100644 sys/dev/netif/ale/Makefile create mode 100644 sys/dev/netif/ale/if_ale.c create mode 100644 sys/dev/netif/ale/if_alereg.h create mode 100644 sys/dev/netif/ale/if_alevar.h diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 5e2421a648..906c91bf30 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -16,6 +16,7 @@ MAN= aac.4 \ ahb.4 \ ahc.4 \ ahd.4 \ + ale.4 \ altq.4 \ amd.4 \ amr.4 \ diff --git a/share/man/man4/ale.4 b/share/man/man4/ale.4 new file mode 100644 index 0000000000..ed4415c5c4 --- /dev/null +++ b/share/man/man4/ale.4 @@ -0,0 +1,143 @@ +.\" Copyright (c) 2008 Pyun YongHyeon +.\" 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. +.\" +.\" $FreeBSD: src/share/man/man4/ale.4,v 1.2 2008/11/29 18:09:50 brueffer Exp $ +.\" +.Dd December 31, 2008 +.Dt ALE 4 +.Os +.Sh NAME +.Nm ale +.Nd Atheros AR8121/AR8113/AR8114 Gigabit/Fast Ethernet driver +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device miibus" +.Cd "device ale" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +if_ale_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +device driver provides support for Atheros AR8121 PCI Express +Gigabit Ethernet controllers and Atheros AR8113/AR8114 PCI +Express Fast Ethernet controllers. +.Pp +All LOMs supported by the +.Nm +driver have TCP/UDP/IP checksum offload for both receive and transmit, +hardware VLAN tag stripping/insertion features and +an interrupt coalescing/moderation +mechanism as well as a 64-bit multicast hash filter. +.Pp +The AR8121 also supports Jumbo Frames (up to 8132 bytes), +which can be configured via the interface MTU setting. +Selecting an MTU larger than 1500 bytes with the +.Xr ifconfig 8 +utility configures the adapter to receive and transmit Jumbo Frames. +.Pp +The +.Nm +driver supports the following media types: +.Bl -tag -width ".Cm 10baseT/UTP" +.It Cm autoselect +Enable autoselection of the media type and options. +The user can manually override +the autoselected mode by adding media options to +.Xr rc.conf 5 . +.It Cm 10baseT/UTP +Set 10Mbps operation. +.It Cm 100baseTX +Set 100Mbps (Fast Ethernet) operation. +.It Cm 1000baseT +Set 1000baseT operation over twisted pair. +.El +.Pp +The +.Nm +driver supports the following media options: +.Bl -tag -width ".Cm full-duplex" +.It Cm full-duplex +Force full duplex operation. +.It Cm half-duplex +Force half duplex operation. +.El +.Pp +For more information on configuring this device, see +.Xr ifconfig 8 . +.Sh HARDWARE +The +.Nm +device driver provides support for the following Ethernet controllers: +.Pp +.Bl -bullet -compact +.It +Atheros AR8113 PCI Express Fast Ethernet controller +.It +Atheros AR8114 PCI Express Fast Ethernet controller +.It +Atheros AR8121 PCI Express Gigabit Ethernet controller +.El +.Sh SYSCTL VARIABLES +The following variables are available as both +.Xr sysctl 8 +variables and +.Xr loader 8 +tunables: +.Bl -tag -width "xxxxxx" +.It Va dev.ale%d.int_rx_mod +Maximum amount of time to delay receive interrupt processing in +units of 1us. +The accepted range is 0 to 130000, the default is 30(30us). +Value 0 completely disables the interrupt moderation. +.It Va dev.ale%d.int_tx_mod +Maximum amount of time to delay transmit interrupt processing in +units of 1us. +The accepted range is 0 to 130000, the default is 1000(1ms). +Value 0 completely disables the interrupt moderation. +.El +.Sh SEE ALSO +.Xr altq 4 , +.Xr arp 4 , +.Xr miibus 4 , +.Xr netintro 4 , +.Xr ng_ether 4 , +.Xr vlan 4 , +.Xr ifconfig 8 +.Sh HISTORY +The +.Nm +driver was written by +.An Pyun YongHyeon +.Aq yongari@FreeBSD.org . +It first appeared in +.Fx 7.1 . diff --git a/sys/dev/netif/Makefile b/sys/dev/netif/Makefile index cfc85a0ccd..f41d02ae26 100644 --- a/sys/dev/netif/Makefile +++ b/sys/dev/netif/Makefile @@ -1,7 +1,7 @@ # $DragonFly: src/sys/dev/netif/Makefile,v 1.34 2008/07/26 14:26:30 sephe Exp $ # -SUBDIR= an acx ar ath aue axe bce bfe bge bwi cue dc ed em ep et fwe fxp \ +SUBDIR= an acx ale ar ath aue axe bce bfe bge bwi cue dc ed em ep et fwe fxp \ iwi iwl jme kue lge lnc mii_layer my msk nfe nge pcn ral re rl rtw \ rue rum sbni sbsh sf sis sk sln sr ste stge \ ti tl tx txp ural vge vr vx wb wi xe xl diff --git a/sys/dev/netif/ale/Makefile b/sys/dev/netif/ale/Makefile new file mode 100644 index 0000000000..e2fa09f504 --- /dev/null +++ b/sys/dev/netif/ale/Makefile @@ -0,0 +1,6 @@ +KMOD= if_ale +SRCS= if_ale.c +SRCS+= miibus_if.h device_if.h bus_if.h pci_if.h +KMODDEPS= miibus + +.include diff --git a/sys/dev/netif/ale/if_ale.c b/sys/dev/netif/ale/if_ale.c new file mode 100644 index 0000000000..d735ddbbff --- /dev/null +++ b/sys/dev/netif/ale/if_ale.c @@ -0,0 +1,2754 @@ +/*- + * Copyright (c) 2008, Pyun YongHyeon + * 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 unmodified, 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: src/sys/dev/ale/if_ale.c,v 1.3 2008/12/03 09:01:12 yongari Exp $ + */ + +/* Driver for Atheros AR8121/AR8113/AR8114 PCIe Ethernet. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +/* "device miibus" required. See GENERIC if you get errors here. */ +#include "miibus_if.h" + +/* For more information about Tx checksum offload issues see ale_encap(). */ +#define ALE_CSUM_FEATURES (CSUM_TCP | CSUM_UDP) + +struct ale_dmamap_ctx { + int nsegs; + bus_dma_segment_t *segs; +}; + +static int ale_probe(device_t); +static int ale_attach(device_t); +static int ale_detach(device_t); +static int ale_shutdown(device_t); +static int ale_suspend(device_t); +static int ale_resume(device_t); + +static int ale_miibus_readreg(device_t, int, int); +static int ale_miibus_writereg(device_t, int, int, int); +static void ale_miibus_statchg(device_t); + +static void ale_init(void *); +static void ale_start(struct ifnet *); +static int ale_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); +static void ale_watchdog(struct ifnet *); +static int ale_mediachange(struct ifnet *); +static void ale_mediastatus(struct ifnet *, struct ifmediareq *); + +static void ale_intr(void *); +static int ale_rxeof(struct ale_softc *sc); +static void ale_rx_update_page(struct ale_softc *, struct ale_rx_page **, + uint32_t, uint32_t *); +static void ale_rxcsum(struct ale_softc *, struct mbuf *, uint32_t); +static void ale_txeof(struct ale_softc *); + +static int ale_dma_alloc(struct ale_softc *); +static void ale_dma_free(struct ale_softc *); +static int ale_check_boundary(struct ale_softc *); +static void ale_dmamap_cb(void *, bus_dma_segment_t *, int, int); +static void ale_dmamap_buf_cb(void *, bus_dma_segment_t *, int, + bus_size_t, int); +static int ale_encap(struct ale_softc *, struct mbuf **); +static void ale_init_rx_pages(struct ale_softc *); +static void ale_init_tx_ring(struct ale_softc *); + +static void ale_stop(struct ale_softc *); +static void ale_tick(void *); +static void ale_get_macaddr(struct ale_softc *); +static void ale_mac_config(struct ale_softc *); +static void ale_phy_reset(struct ale_softc *); +static void ale_reset(struct ale_softc *); +static void ale_rxfilter(struct ale_softc *); +static void ale_rxvlan(struct ale_softc *); +static void ale_stats_clear(struct ale_softc *); +static void ale_stats_update(struct ale_softc *); +static void ale_stop_mac(struct ale_softc *); +#ifdef notyet +static void ale_setlinkspeed(struct ale_softc *); +static void ale_setwol(struct ale_softc *); +#endif + +static void ale_sysctl_node(struct ale_softc *); +static int sysctl_hw_ale_int_mod(SYSCTL_HANDLER_ARGS); + +/* + * Devices supported by this driver. + */ +static struct ale_dev { + uint16_t ale_vendorid; + uint16_t ale_deviceid; + const char *ale_name; +} ale_devs[] = { + { VENDORID_ATHEROS, DEVICEID_ATHEROS_AR81XX, + "Atheros AR8121/AR8113/AR8114 PCIe Ethernet" }, +}; + +static device_method_t ale_methods[] = { + /* Device interface. */ + DEVMETHOD(device_probe, ale_probe), + DEVMETHOD(device_attach, ale_attach), + DEVMETHOD(device_detach, ale_detach), + DEVMETHOD(device_shutdown, ale_shutdown), + DEVMETHOD(device_suspend, ale_suspend), + DEVMETHOD(device_resume, ale_resume), + + /* Bus interface. */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + /* MII interface. */ + DEVMETHOD(miibus_readreg, ale_miibus_readreg), + DEVMETHOD(miibus_writereg, ale_miibus_writereg), + DEVMETHOD(miibus_statchg, ale_miibus_statchg), + + { NULL, NULL } +}; + +static driver_t ale_driver = { + "ale", + ale_methods, + sizeof(struct ale_softc) +}; + +static devclass_t ale_devclass; + +DECLARE_DUMMY_MODULE(if_ale); +MODULE_DEPEND(if_ale, miibus, 1, 1, 1); +DRIVER_MODULE(if_ale, pci, ale_driver, ale_devclass, 0, 0); +DRIVER_MODULE(miibus, ale, miibus_driver, miibus_devclass, 0, 0); + +static int +ale_miibus_readreg(device_t dev, int phy, int reg) +{ + struct ale_softc *sc; + uint32_t v; + int i; + + sc = device_get_softc(dev); + + if (phy != sc->ale_phyaddr) + return (0); + + CSR_WRITE_4(sc, ALE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ | + MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg)); + for (i = ALE_PHY_TIMEOUT; i > 0; i--) { + DELAY(5); + v = CSR_READ_4(sc, ALE_MDIO); + if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0) + break; + } + + if (i == 0) { + device_printf(sc->ale_dev, "phy read timeout : %d\n", reg); + return (0); + } + + return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT); +} + +static int +ale_miibus_writereg(device_t dev, int phy, int reg, int val) +{ + struct ale_softc *sc; + uint32_t v; + int i; + + sc = device_get_softc(dev); + + if (phy != sc->ale_phyaddr) + return (0); + + CSR_WRITE_4(sc, ALE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE | + (val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT | + MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg)); + for (i = ALE_PHY_TIMEOUT; i > 0; i--) { + DELAY(5); + v = CSR_READ_4(sc, ALE_MDIO); + if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0) + break; + } + + if (i == 0) + device_printf(sc->ale_dev, "phy write timeout : %d\n", reg); + + return (0); +} + +static void +ale_miibus_statchg(device_t dev) +{ + struct ale_softc *sc = device_get_softc(dev); + struct ifnet *ifp = &sc->arpcom.ac_if; + struct mii_data *mii; + uint32_t reg; + + ASSERT_SERIALIZED(ifp->if_serializer); + + if ((ifp->if_flags & IFF_RUNNING) == 0) + return; + + mii = device_get_softc(sc->ale_miibus); + + sc->ale_flags &= ~ALE_FLAG_LINK; + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_10_T: + case IFM_100_TX: + sc->ale_flags |= ALE_FLAG_LINK; + break; + + case IFM_1000_T: + if ((sc->ale_flags & ALE_FLAG_FASTETHER) == 0) + sc->ale_flags |= ALE_FLAG_LINK; + break; + + default: + break; + } + } + + /* Stop Rx/Tx MACs. */ + ale_stop_mac(sc); + + /* Program MACs with resolved speed/duplex/flow-control. */ + if ((sc->ale_flags & ALE_FLAG_LINK) != 0) { + ale_mac_config(sc); + /* Reenable Tx/Rx MACs. */ + reg = CSR_READ_4(sc, ALE_MAC_CFG); + reg |= MAC_CFG_TX_ENB | MAC_CFG_RX_ENB; + CSR_WRITE_4(sc, ALE_MAC_CFG, reg); + } +} + +static void +ale_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + struct ale_softc *sc = ifp->if_softc; + struct mii_data *mii = device_get_softc(sc->ale_miibus); + + ASSERT_SERIALIZED(ifp->if_serializer); + + mii_pollstat(mii); + ifmr->ifm_status = mii->mii_media_status; + ifmr->ifm_active = mii->mii_media_active; +} + +static int +ale_mediachange(struct ifnet *ifp) +{ + struct ale_softc *sc = ifp->if_softc; + struct mii_data *mii = device_get_softc(sc->ale_miibus); + int error; + + ASSERT_SERIALIZED(ifp->if_serializer); + + if (mii->mii_instance != 0) { + struct mii_softc *miisc; + + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) + mii_phy_reset(miisc); + } + error = mii_mediachg(mii); + + return (error); +} + +static int +ale_probe(device_t dev) +{ + struct ale_dev *sp; + int i; + uint16_t vendor, devid; + + vendor = pci_get_vendor(dev); + devid = pci_get_device(dev); + sp = ale_devs; + for (i = 0; i < sizeof(ale_devs) / sizeof(ale_devs[0]); i++) { + if (vendor == sp->ale_vendorid && + devid == sp->ale_deviceid) { + device_set_desc(dev, sp->ale_name); + return (0); + } + sp++; + } + + return (ENXIO); +} + +static void +ale_get_macaddr(struct ale_softc *sc) +{ + uint32_t ea[2], reg; + int i, vpdc; + + reg = CSR_READ_4(sc, ALE_SPI_CTRL); + if ((reg & SPI_VPD_ENB) != 0) { + reg &= ~SPI_VPD_ENB; + CSR_WRITE_4(sc, ALE_SPI_CTRL, reg); + } + + vpdc = pci_get_vpdcap_ptr(sc->ale_dev); + if (vpdc) { + /* + * PCI VPD capability found, let TWSI reload EEPROM. + * This will set ethernet address of controller. + */ + CSR_WRITE_4(sc, ALE_TWSI_CTRL, CSR_READ_4(sc, ALE_TWSI_CTRL) | + TWSI_CTRL_SW_LD_START); + for (i = 100; i > 0; i--) { + DELAY(1000); + reg = CSR_READ_4(sc, ALE_TWSI_CTRL); + if ((reg & TWSI_CTRL_SW_LD_START) == 0) + break; + } + if (i == 0) + device_printf(sc->ale_dev, + "reloading EEPROM timeout!\n"); + } else { + if (bootverbose) + device_printf(sc->ale_dev, + "PCI VPD capability not found!\n"); + } + + ea[0] = CSR_READ_4(sc, ALE_PAR0); + ea[1] = CSR_READ_4(sc, ALE_PAR1); + sc->ale_eaddr[0] = (ea[1] >> 8) & 0xFF; + sc->ale_eaddr[1] = (ea[1] >> 0) & 0xFF; + sc->ale_eaddr[2] = (ea[0] >> 24) & 0xFF; + sc->ale_eaddr[3] = (ea[0] >> 16) & 0xFF; + sc->ale_eaddr[4] = (ea[0] >> 8) & 0xFF; + sc->ale_eaddr[5] = (ea[0] >> 0) & 0xFF; +} + +static void +ale_phy_reset(struct ale_softc *sc) +{ + /* Reset magic from Linux. */ + CSR_WRITE_2(sc, ALE_GPHY_CTRL, + GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE | GPHY_CTRL_SEL_ANA_RESET | + GPHY_CTRL_PHY_PLL_ON); + DELAY(1000); + CSR_WRITE_2(sc, ALE_GPHY_CTRL, + GPHY_CTRL_EXT_RESET | GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE | + GPHY_CTRL_SEL_ANA_RESET | GPHY_CTRL_PHY_PLL_ON); + DELAY(1000); + +#define ATPHY_DBG_ADDR 0x1D +#define ATPHY_DBG_DATA 0x1E + + /* Enable hibernation mode. */ + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_ADDR, 0x0B); + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_DATA, 0xBC00); + /* Set Class A/B for all modes. */ + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_ADDR, 0x00); + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_DATA, 0x02EF); + /* Enable 10BT power saving. */ + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_ADDR, 0x12); + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_DATA, 0x4C04); + /* Adjust 1000T power. */ + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_ADDR, 0x04); + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_ADDR, 0x8BBB); + /* 10BT center tap voltage. */ + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_ADDR, 0x05); + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + ATPHY_DBG_ADDR, 0x2C46); + +#undef ATPHY_DBG_ADDR +#undef ATPHY_DBG_DATA + DELAY(1000); +} + +static int +ale_attach(device_t dev) +{ + struct ale_softc *sc = device_get_softc(dev); + struct ifnet *ifp = &sc->arpcom.ac_if; + int error = 0; + uint32_t rxf_len, txf_len; + uint8_t pcie_ptr; + + if_initname(ifp, device_get_name(dev), device_get_unit(dev)); + sc->ale_dev = dev; + + callout_init(&sc->ale_tick_ch); + +#ifndef BURN_BRIDGES + if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { + uint32_t irq, mem; + + irq = pci_read_config(dev, PCIR_INTLINE, 4); + mem = pci_read_config(dev, ALE_PCIR_BAR, 4); + + device_printf(dev, "chip is in D%d power mode " + "-- setting to D0\n", pci_get_powerstate(dev)); + + pci_set_powerstate(dev, PCI_POWERSTATE_D0); + + pci_write_config(dev, PCIR_INTLINE, irq, 4); + pci_write_config(dev, ALE_PCIR_BAR, mem, 4); + } +#endif /* !BURN_BRIDGE */ + + /* Enable bus mastering */ + pci_enable_busmaster(dev); + + /* + * Allocate memory mapped IO + */ + sc->ale_mem_rid = ALE_PCIR_BAR; + sc->ale_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->ale_mem_rid, RF_ACTIVE); + if (sc->ale_mem_res == NULL) { + device_printf(dev, "can't allocate IO memory\n"); + return ENXIO; + } + sc->ale_mem_bt = rman_get_bustag(sc->ale_mem_res); + sc->ale_mem_bh = rman_get_bushandle(sc->ale_mem_res); + + /* + * Allocate IRQ + */ + sc->ale_irq_rid = 0; + sc->ale_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->ale_irq_rid, + RF_SHAREABLE | RF_ACTIVE); + if (sc->ale_irq_res == NULL) { + device_printf(dev, "can't allocate irq\n"); + error = ENXIO; + goto fail; + } + + /* Set PHY address. */ + sc->ale_phyaddr = ALE_PHY_ADDR; + + /* Reset PHY. */ + ale_phy_reset(sc); + + /* Reset the ethernet controller. */ + ale_reset(sc); + + /* Get PCI and chip id/revision. */ + sc->ale_rev = pci_get_revid(dev); + if (sc->ale_rev >= 0xF0) { + /* L2E Rev. B. AR8114 */ + sc->ale_flags |= ALE_FLAG_FASTETHER; + } else { + if ((CSR_READ_4(sc, ALE_PHY_STATUS) & PHY_STATUS_100M) != 0) { + /* L1E AR8121 */ + sc->ale_flags |= ALE_FLAG_JUMBO; + } else { + /* L2E Rev. A. AR8113 */ + sc->ale_flags |= ALE_FLAG_FASTETHER; + } + } + + /* + * All known controllers seems to require 4 bytes alignment + * of Tx buffers to make Tx checksum offload with custom + * checksum generation method work. + */ + sc->ale_flags |= ALE_FLAG_TXCSUM_BUG; + + /* + * All known controllers seems to have issues on Rx checksum + * offload for fragmented IP datagrams. + */ + sc->ale_flags |= ALE_FLAG_RXCSUM_BUG; + + /* + * Don't use Tx CMB. It is known to cause RRS update failure + * under certain circumstances. Typical phenomenon of the + * issue would be unexpected sequence number encountered in + * Rx handler. + */ + sc->ale_flags |= ALE_FLAG_TXCMB_BUG; + sc->ale_chip_rev = CSR_READ_4(sc, ALE_MASTER_CFG) >> + MASTER_CHIP_REV_SHIFT; + if (bootverbose) { + device_printf(dev, "PCI device revision : 0x%04x\n", + sc->ale_rev); + device_printf(dev, "Chip id/revision : 0x%04x\n", + sc->ale_chip_rev); + } + + /* + * Uninitialized hardware returns an invalid chip id/revision + * as well as 0xFFFFFFFF for Tx/Rx fifo length. + */ + txf_len = CSR_READ_4(sc, ALE_SRAM_TX_FIFO_LEN); + rxf_len = CSR_READ_4(sc, ALE_SRAM_RX_FIFO_LEN); + if (sc->ale_chip_rev == 0xFFFF || txf_len == 0xFFFFFFFF || + rxf_len == 0xFFFFFFF) { + device_printf(dev,"chip revision : 0x%04x, %u Tx FIFO " + "%u Rx FIFO -- not initialized?\n", sc->ale_chip_rev, + txf_len, rxf_len); + error = ENXIO; + goto fail; + } + device_printf(dev, "%u Tx FIFO, %u Rx FIFO\n", txf_len, rxf_len); + + /* Get DMA parameters from PCIe device control register. */ + pcie_ptr = pci_get_pciecap_ptr(dev); + if (pcie_ptr) { + uint16_t devctl; + + sc->ale_flags |= ALE_FLAG_PCIE; + devctl = pci_read_config(dev, pcie_ptr + PCIER_DEVCTRL, 2); + /* Max read request size. */ + sc->ale_dma_rd_burst = ((devctl >> 12) & 0x07) << + DMA_CFG_RD_BURST_SHIFT; + /* Max payload size. */ + sc->ale_dma_wr_burst = ((devctl >> 5) & 0x07) << + DMA_CFG_WR_BURST_SHIFT; + if (bootverbose) { + device_printf(dev, "Read request size : %d bytes.\n", + 128 << ((devctl >> 12) & 0x07)); + device_printf(dev, "TLP payload size : %d bytes.\n", + 128 << ((devctl >> 5) & 0x07)); + } + } else { + sc->ale_dma_rd_burst = DMA_CFG_RD_BURST_128; + sc->ale_dma_wr_burst = DMA_CFG_WR_BURST_128; + } + + /* Create device sysctl node. */ + ale_sysctl_node(sc); + + if ((error = ale_dma_alloc(sc) != 0)) + goto fail; + + /* Load station address. */ + ale_get_macaddr(sc); + + ifp->if_softc = sc; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = ale_ioctl; + ifp->if_start = ale_start; + ifp->if_init = ale_init; + ifp->if_watchdog = ale_watchdog; + ifq_set_maxlen(&ifp->if_snd, ALE_TX_RING_CNT - 1); + ifq_set_ready(&ifp->if_snd); + + ifp->if_capabilities = IFCAP_HWCSUM | + IFCAP_VLAN_MTU | + IFCAP_VLAN_HWTAGGING; + ifp->if_hwassist = ALE_CSUM_FEATURES; + ifp->if_capenable = ifp->if_capabilities; + + /* Set up MII bus. */ + if ((error = mii_phy_probe(dev, &sc->ale_miibus, ale_mediachange, + ale_mediastatus)) != 0) { + device_printf(dev, "no PHY found!\n"); + goto fail; + } + + ether_ifattach(ifp, sc->ale_eaddr, NULL); + + /* Tell the upper layer(s) we support long frames. */ + ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); + + error = bus_setup_intr(dev, sc->ale_irq_res, INTR_MPSAFE, ale_intr, sc, + &sc->ale_irq_handle, ifp->if_serializer); + if (error) { + device_printf(dev, "could not set up interrupt handler.\n"); + ether_ifdetach(ifp); + goto fail; + } + + ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->ale_irq_res)); + KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus); + return 0; +fail: + ale_detach(dev); + return (error); +} + +static int +ale_detach(device_t dev) +{ + struct ale_softc *sc = device_get_softc(dev); + + if (device_is_attached(dev)) { + struct ifnet *ifp = &sc->arpcom.ac_if; + + lwkt_serialize_enter(ifp->if_serializer); + sc->ale_flags |= ALE_FLAG_DETACH; + ale_stop(sc); + bus_teardown_intr(dev, sc->ale_irq_res, sc->ale_irq_handle); + lwkt_serialize_exit(ifp->if_serializer); + + ether_ifdetach(ifp); + } + + if (sc->ale_sysctl_tree != NULL) + sysctl_ctx_free(&sc->ale_sysctl_ctx); + + if (sc->ale_miibus != NULL) + device_delete_child(dev, sc->ale_miibus); + bus_generic_detach(dev); + + if (sc->ale_irq_res != NULL) { + bus_release_resource(dev, SYS_RES_IRQ, sc->ale_irq_rid, + sc->ale_irq_res); + } + if (sc->ale_mem_res != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, sc->ale_mem_rid, + sc->ale_mem_res); + } + + ale_dma_free(sc); + + return (0); +} + +#define ALE_SYSCTL_STAT_ADD32(c, h, n, p, d) \ + SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) +#define ALE_SYSCTL_STAT_ADD64(c, h, n, p, d) \ + SYSCTL_ADD_QUAD(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) + +static void +ale_sysctl_node(struct ale_softc *sc) +{ + struct sysctl_ctx_list *ctx; + struct sysctl_oid_list *child, *parent; + struct sysctl_oid *tree; + struct ale_hw_stats *stats; + int error; + + sysctl_ctx_init(&sc->ale_sysctl_ctx); + sc->ale_sysctl_tree = SYSCTL_ADD_NODE(&sc->ale_sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, + device_get_nameunit(sc->ale_dev), + CTLFLAG_RD, 0, ""); + if (sc->ale_sysctl_tree == NULL) { + device_printf(sc->ale_dev, "can't add sysctl node\n"); + return; + } + + stats = &sc->ale_stats; + ctx = &sc->ale_sysctl_ctx; + child = SYSCTL_CHILDREN(sc->ale_sysctl_tree); + + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "int_rx_mod", + CTLTYPE_INT | CTLFLAG_RW, &sc->ale_int_rx_mod, 0, + sysctl_hw_ale_int_mod, "I", "ale Rx interrupt moderation"); + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "int_tx_mod", + CTLTYPE_INT | CTLFLAG_RW, &sc->ale_int_tx_mod, 0, + sysctl_hw_ale_int_mod, "I", "ale Tx interrupt moderation"); + + /* + * Pull in device tunables. + */ + sc->ale_int_rx_mod = ALE_IM_RX_TIMER_DEFAULT; + error = resource_int_value(device_get_name(sc->ale_dev), + device_get_unit(sc->ale_dev), "int_rx_mod", &sc->ale_int_rx_mod); + if (error == 0) { + if (sc->ale_int_rx_mod < ALE_IM_TIMER_MIN || + sc->ale_int_rx_mod > ALE_IM_TIMER_MAX) { + device_printf(sc->ale_dev, "int_rx_mod value out of " + "range; using default: %d\n", + ALE_IM_RX_TIMER_DEFAULT); + sc->ale_int_rx_mod = ALE_IM_RX_TIMER_DEFAULT; + } + } + + sc->ale_int_tx_mod = ALE_IM_TX_TIMER_DEFAULT; + error = resource_int_value(device_get_name(sc->ale_dev), + device_get_unit(sc->ale_dev), "int_tx_mod", &sc->ale_int_tx_mod); + if (error == 0) { + if (sc->ale_int_tx_mod < ALE_IM_TIMER_MIN || + sc->ale_int_tx_mod > ALE_IM_TIMER_MAX) { + device_printf(sc->ale_dev, "int_tx_mod value out of " + "range; using default: %d\n", + ALE_IM_TX_TIMER_DEFAULT); + sc->ale_int_tx_mod = ALE_IM_TX_TIMER_DEFAULT; + } + } + + /* Misc statistics. */ + ALE_SYSCTL_STAT_ADD32(ctx, child, "reset_brk_seq", + &stats->reset_brk_seq, + "Controller resets due to broken Rx sequnce number"); + + tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, + NULL, "ATE statistics"); + parent = SYSCTL_CHILDREN(tree); + + /* Rx statistics. */ + tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx", CTLFLAG_RD, + NULL, "Rx MAC statistics"); + child = SYSCTL_CHILDREN(tree); + ALE_SYSCTL_STAT_ADD32(ctx, child, "good_frames", + &stats->rx_frames, "Good frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "good_bcast_frames", + &stats->rx_bcast_frames, "Good broadcast frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "good_mcast_frames", + &stats->rx_mcast_frames, "Good multicast frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "pause_frames", + &stats->rx_pause_frames, "Pause control frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "control_frames", + &stats->rx_control_frames, "Control frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "crc_errs", + &stats->rx_crcerrs, "CRC errors"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "len_errs", + &stats->rx_lenerrs, "Frames with length mismatched"); + ALE_SYSCTL_STAT_ADD64(ctx, child, "good_octets", + &stats->rx_bytes, "Good octets"); + ALE_SYSCTL_STAT_ADD64(ctx, child, "good_bcast_octets", + &stats->rx_bcast_bytes, "Good broadcast octets"); + ALE_SYSCTL_STAT_ADD64(ctx, child, "good_mcast_octets", + &stats->rx_mcast_bytes, "Good multicast octets"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "runts", + &stats->rx_runts, "Too short frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "fragments", + &stats->rx_fragments, "Fragmented frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_64", + &stats->rx_pkts_64, "64 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_65_127", + &stats->rx_pkts_65_127, "65 to 127 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_128_255", + &stats->rx_pkts_128_255, "128 to 255 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_256_511", + &stats->rx_pkts_256_511, "256 to 511 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_512_1023", + &stats->rx_pkts_512_1023, "512 to 1023 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_1024_1518", + &stats->rx_pkts_1024_1518, "1024 to 1518 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_1519_max", + &stats->rx_pkts_1519_max, "1519 to max frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "trunc_errs", + &stats->rx_pkts_truncated, "Truncated frames due to MTU size"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "fifo_oflows", + &stats->rx_fifo_oflows, "FIFO overflows"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "rrs_errs", + &stats->rx_rrs_errs, "Return status write-back errors"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "align_errs", + &stats->rx_alignerrs, "Alignment errors"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "filtered", + &stats->rx_pkts_filtered, + "Frames dropped due to address filtering"); + + /* Tx statistics. */ + tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD, + NULL, "Tx MAC statistics"); + child = SYSCTL_CHILDREN(tree); + ALE_SYSCTL_STAT_ADD32(ctx, child, "good_frames", + &stats->tx_frames, "Good frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "good_bcast_frames", + &stats->tx_bcast_frames, "Good broadcast frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "good_mcast_frames", + &stats->tx_mcast_frames, "Good multicast frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "pause_frames", + &stats->tx_pause_frames, "Pause control frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "control_frames", + &stats->tx_control_frames, "Control frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "excess_defers", + &stats->tx_excess_defer, "Frames with excessive derferrals"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "defers", + &stats->tx_excess_defer, "Frames with derferrals"); + ALE_SYSCTL_STAT_ADD64(ctx, child, "good_octets", + &stats->tx_bytes, "Good octets"); + ALE_SYSCTL_STAT_ADD64(ctx, child, "good_bcast_octets", + &stats->tx_bcast_bytes, "Good broadcast octets"); + ALE_SYSCTL_STAT_ADD64(ctx, child, "good_mcast_octets", + &stats->tx_mcast_bytes, "Good multicast octets"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_64", + &stats->tx_pkts_64, "64 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_65_127", + &stats->tx_pkts_65_127, "65 to 127 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_128_255", + &stats->tx_pkts_128_255, "128 to 255 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_256_511", + &stats->tx_pkts_256_511, "256 to 511 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_512_1023", + &stats->tx_pkts_512_1023, "512 to 1023 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_1024_1518", + &stats->tx_pkts_1024_1518, "1024 to 1518 bytes frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "frames_1519_max", + &stats->tx_pkts_1519_max, "1519 to max frames"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "single_colls", + &stats->tx_single_colls, "Single collisions"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "multi_colls", + &stats->tx_multi_colls, "Multiple collisions"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "late_colls", + &stats->tx_late_colls, "Late collisions"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "excess_colls", + &stats->tx_excess_colls, "Excessive collisions"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "abort", + &stats->tx_abort, "Aborted frames due to Excessive collisions"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "underruns", + &stats->tx_underrun, "FIFO underruns"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "desc_underruns", + &stats->tx_desc_underrun, "Descriptor write-back errors"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "len_errs", + &stats->tx_lenerrs, "Frames with length mismatched"); + ALE_SYSCTL_STAT_ADD32(ctx, child, "trunc_errs", + &stats->tx_pkts_truncated, "Truncated frames due to MTU size"); +} + +#undef ALE_SYSCTL_STAT_ADD32 +#undef ALE_SYSCTL_STAT_ADD64 + +struct ale_dmamap_arg { + bus_addr_t ale_busaddr; +}; + +static void +ale_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct ale_dmamap_arg *ctx; + + if (error != 0) + return; + + KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); + + ctx = (struct ale_dmamap_arg *)arg; + ctx->ale_busaddr = segs[0].ds_addr; +} + +/* + * Tx descriptors/RXF0/CMB DMA blocks share ALE_DESC_ADDR_HI register + * which specifies high address region of DMA blocks. Therefore these + * blocks should have the same high address of given 4GB address + * space(i.e. crossing 4GB boundary is not allowed). + */ +static int +ale_check_boundary(struct ale_softc *sc) +{ + bus_addr_t rx_cmb_end[ALE_RX_PAGES], tx_cmb_end; + bus_addr_t rx_page_end[ALE_RX_PAGES], tx_ring_end; + + rx_page_end[0] = sc->ale_cdata.ale_rx_page[0].page_paddr + + sc->ale_pagesize; + rx_page_end[1] = sc->ale_cdata.ale_rx_page[1].page_paddr + + sc->ale_pagesize; + tx_ring_end = sc->ale_cdata.ale_tx_ring_paddr + ALE_TX_RING_SZ; + tx_cmb_end = sc->ale_cdata.ale_tx_cmb_paddr + ALE_TX_CMB_SZ; + rx_cmb_end[0] = sc->ale_cdata.ale_rx_page[0].cmb_paddr + ALE_RX_CMB_SZ; + rx_cmb_end[1] = sc->ale_cdata.ale_rx_page[1].cmb_paddr + ALE_RX_CMB_SZ; + + if ((ALE_ADDR_HI(tx_ring_end) != + ALE_ADDR_HI(sc->ale_cdata.ale_tx_ring_paddr)) || + (ALE_ADDR_HI(rx_page_end[0]) != + ALE_ADDR_HI(sc->ale_cdata.ale_rx_page[0].page_paddr)) || + (ALE_ADDR_HI(rx_page_end[1]) != + ALE_ADDR_HI(sc->ale_cdata.ale_rx_page[1].page_paddr)) || + (ALE_ADDR_HI(tx_cmb_end) != + ALE_ADDR_HI(sc->ale_cdata.ale_tx_cmb_paddr)) || + (ALE_ADDR_HI(rx_cmb_end[0]) != + ALE_ADDR_HI(sc->ale_cdata.ale_rx_page[0].cmb_paddr)) || + (ALE_ADDR_HI(rx_cmb_end[1]) != + ALE_ADDR_HI(sc->ale_cdata.ale_rx_page[1].cmb_paddr))) + return (EFBIG); + + if ((ALE_ADDR_HI(tx_ring_end) != ALE_ADDR_HI(rx_page_end[0])) || + (ALE_ADDR_HI(tx_ring_end) != ALE_ADDR_HI(rx_page_end[1])) || + (ALE_ADDR_HI(tx_ring_end) != ALE_ADDR_HI(rx_cmb_end[0])) || + (ALE_ADDR_HI(tx_ring_end) != ALE_ADDR_HI(rx_cmb_end[1])) || + (ALE_ADDR_HI(tx_ring_end) != ALE_ADDR_HI(tx_cmb_end))) + return (EFBIG); + + return (0); +} + +static int +ale_dma_alloc(struct ale_softc *sc) +{ + struct ale_txdesc *txd; + bus_addr_t lowaddr; + struct ale_dmamap_arg ctx; + int error, guard_size, i; + + if ((sc->ale_flags & ALE_FLAG_JUMBO) != 0) + guard_size = ALE_JUMBO_FRAMELEN; + else + guard_size = ALE_MAX_FRAMELEN; + sc->ale_pagesize = roundup(guard_size + ALE_RX_PAGE_SZ, + ALE_RX_PAGE_ALIGN); + lowaddr = BUS_SPACE_MAXADDR; +again: + /* Create parent DMA tag. */ + error = bus_dma_tag_create( + NULL, /* parent */ + 1, 0, /* alignment, boundary */ + lowaddr, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ + 0, /* nsegments */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ + 0, /* flags */ + &sc->ale_cdata.ale_parent_tag); + if (error != 0) { + device_printf(sc->ale_dev, + "could not create parent DMA tag.\n"); + goto fail; + } + + /* Create DMA tag for Tx descriptor ring. */ + error = bus_dma_tag_create( + sc->ale_cdata.ale_parent_tag, /* parent */ + ALE_TX_RING_ALIGN, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + ALE_TX_RING_SZ, /* maxsize */ + 1, /* nsegments */ + ALE_TX_RING_SZ, /* maxsegsize */ + 0, /* flags */ + &sc->ale_cdata.ale_tx_ring_tag); + if (error != 0) { + device_printf(sc->ale_dev, + "could not create Tx ring DMA tag.\n"); + goto fail; + } + + /* Create DMA tag for Rx pages. */ + for (i = 0; i < ALE_RX_PAGES; i++) { + error = bus_dma_tag_create( + sc->ale_cdata.ale_parent_tag, /* parent */ + ALE_RX_PAGE_ALIGN, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sc->ale_pagesize, /* maxsize */ + 1, /* nsegments */ + sc->ale_pagesize, /* maxsegsize */ + 0, /* flags */ + &sc->ale_cdata.ale_rx_page[i].page_tag); + if (error != 0) { + device_printf(sc->ale_dev, + "could not create Rx page %d DMA tag.\n", i); + goto fail; + } + } + + /* Create DMA tag for Tx coalescing message block. */ + error = bus_dma_tag_create( + sc->ale_cdata.ale_parent_tag, /* parent */ + ALE_CMB_ALIGN, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + ALE_TX_CMB_SZ, /* maxsize */ + 1, /* nsegments */ + ALE_TX_CMB_SZ, /* maxsegsize */ + 0, /* flags */ + &sc->ale_cdata.ale_tx_cmb_tag); + if (error != 0) { + device_printf(sc->ale_dev, + "could not create Tx CMB DMA tag.\n"); + goto fail; + } + + /* Create DMA tag for Rx coalescing message block. */ + for (i = 0; i < ALE_RX_PAGES; i++) { + error = bus_dma_tag_create( + sc->ale_cdata.ale_parent_tag, /* parent */ + ALE_CMB_ALIGN, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + ALE_RX_CMB_SZ, /* maxsize */ + 1, /* nsegments */ + ALE_RX_CMB_SZ, /* maxsegsize */ + 0, /* flags */ + &sc->ale_cdata.ale_rx_page[i].cmb_tag); + if (error != 0) { + device_printf(sc->ale_dev, + "could not create Rx page %d CMB DMA tag.\n", i); + goto fail; + } + } + + /* Allocate DMA'able memory and load the DMA map for Tx ring. */ + error = bus_dmamem_alloc(sc->ale_cdata.ale_tx_ring_tag, + (void **)&sc->ale_cdata.ale_tx_ring, + BUS_DMA_WAITOK | BUS_DMA_ZERO, + &sc->ale_cdata.ale_tx_ring_map); + if (error != 0) { + device_printf(sc->ale_dev, + "could not allocate DMA'able memory for Tx ring.\n"); + goto fail; + } + ctx.ale_busaddr = 0; + error = bus_dmamap_load(sc->ale_cdata.ale_tx_ring_tag, + sc->ale_cdata.ale_tx_ring_map, sc->ale_cdata.ale_tx_ring, + ALE_TX_RING_SZ, ale_dmamap_cb, &ctx, 0); + if (error != 0 || ctx.ale_busaddr == 0) { + device_printf(sc->ale_dev, + "could not load DMA'able memory for Tx ring.\n"); + goto fail; + } + sc->ale_cdata.ale_tx_ring_paddr = ctx.ale_busaddr; + + /* Rx pages. */ + for (i = 0; i < ALE_RX_PAGES; i++) { + error = bus_dmamem_alloc(sc->ale_cdata.ale_rx_page[i].page_tag, + (void **)&sc->ale_cdata.ale_rx_page[i].page_addr, + BUS_DMA_WAITOK | BUS_DMA_ZERO, + &sc->ale_cdata.ale_rx_page[i].page_map); + if (error != 0) { + device_printf(sc->ale_dev, + "could not allocate DMA'able memory for " + "Rx page %d.\n", i); + goto fail; + } + ctx.ale_busaddr = 0; + error = bus_dmamap_load(sc->ale_cdata.ale_rx_page[i].page_tag, + sc->ale_cdata.ale_rx_page[i].page_map, + sc->ale_cdata.ale_rx_page[i].page_addr, + sc->ale_pagesize, ale_dmamap_cb, &ctx, 0); + if (error != 0 || ctx.ale_busaddr == 0) { + device_printf(sc->ale_dev, + "could not load DMA'able memory for " + "Rx page %d.\n", i); + goto fail; + } + sc->ale_cdata.ale_rx_page[i].page_paddr = ctx.ale_busaddr; + } + + /* Tx CMB. */ + error = bus_dmamem_alloc(sc->ale_cdata.ale_tx_cmb_tag, + (void **)&sc->ale_cdata.ale_tx_cmb, + BUS_DMA_WAITOK | BUS_DMA_ZERO, + &sc->ale_cdata.ale_tx_cmb_map); + if (error != 0) { + device_printf(sc->ale_dev, + "could not allocate DMA'able memory for Tx CMB.\n"); + goto fail; + } + ctx.ale_busaddr = 0; + error = bus_dmamap_load(sc->ale_cdata.ale_tx_cmb_tag, + sc->ale_cdata.ale_tx_cmb_map, sc->ale_cdata.ale_tx_cmb, + ALE_TX_CMB_SZ, ale_dmamap_cb, &ctx, 0); + if (error != 0 || ctx.ale_busaddr == 0) { + device_printf(sc->ale_dev, + "could not load DMA'able memory for Tx CMB.\n"); + goto fail; + } + sc->ale_cdata.ale_tx_cmb_paddr = ctx.ale_busaddr; + + /* Rx CMB. */ + for (i = 0; i < ALE_RX_PAGES; i++) { + error = bus_dmamem_alloc(sc->ale_cdata.ale_rx_page[i].cmb_tag, + (void **)&sc->ale_cdata.ale_rx_page[i].cmb_addr, + BUS_DMA_WAITOK | BUS_DMA_ZERO, + &sc->ale_cdata.ale_rx_page[i].cmb_map); + if (error != 0) { + device_printf(sc->ale_dev, "could not allocate " + "DMA'able memory for Rx page %d CMB.\n", i); + goto fail; + } + ctx.ale_busaddr = 0; + error = bus_dmamap_load(sc->ale_cdata.ale_rx_page[i].cmb_tag, + sc->ale_cdata.ale_rx_page[i].cmb_map, + sc->ale_cdata.ale_rx_page[i].cmb_addr, + ALE_RX_CMB_SZ, ale_dmamap_cb, &ctx, 0); + if (error != 0 || ctx.ale_busaddr == 0) { + device_printf(sc->ale_dev, "could not load DMA'able " + "memory for Rx page %d CMB.\n", i); + goto fail; + } + sc->ale_cdata.ale_rx_page[i].cmb_paddr = ctx.ale_busaddr; + } + + /* + * Tx descriptors/RXF0/CMB DMA blocks share the same + * high address region of 64bit DMA address space. + */ + if (lowaddr != BUS_SPACE_MAXADDR_32BIT && + (error = ale_check_boundary(sc)) != 0) { + device_printf(sc->ale_dev, "4GB boundary crossed, " + "switching to 32bit DMA addressing mode.\n"); + ale_dma_free(sc); + /* + * Limit max allowable DMA address space to 32bit + * and try again. + */ + lowaddr = BUS_SPACE_MAXADDR_32BIT; + goto again; + } + + /* + * Create Tx buffer parent tag. + * AR81xx allows 64bit DMA addressing of Tx buffers so it + * needs separate parent DMA tag as parent DMA address space + * could be restricted to be within 32bit address space by + * 4GB boundary crossing. + */ + error = bus_dma_tag_create( + NULL, /* parent */ + 1, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ + 0, /* nsegments */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ + 0, /* flags */ + &sc->ale_cdata.ale_buffer_tag); + if (error != 0) { + device_printf(sc->ale_dev, + "could not create parent buffer DMA tag.\n"); + goto fail; + } + + /* Create DMA tag for Tx buffers. */ + error = bus_dma_tag_create( + sc->ale_cdata.ale_buffer_tag, /* parent */ + 1, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + ALE_TSO_MAXSIZE, /* maxsize */ + ALE_MAXTXSEGS, /* nsegments */ + ALE_TSO_MAXSEGSIZE, /* maxsegsize */ + 0, /* flags */ + &sc->ale_cdata.ale_tx_tag); + if (error != 0) { + device_printf(sc->ale_dev, "could not create Tx DMA tag.\n"); + goto fail; + } + + /* Create DMA maps for Tx buffers. */ + for (i = 0; i < ALE_TX_RING_CNT; i++) { + txd = &sc->ale_cdata.ale_txdesc[i]; + txd->tx_m = NULL; + txd->tx_dmamap = NULL; + error = bus_dmamap_create(sc->ale_cdata.ale_tx_tag, 0, + &txd->tx_dmamap); + if (error != 0) { + device_printf(sc->ale_dev, + "could not create Tx dmamap.\n"); + goto fail; + } + } +fail: + return (error); +} + +static void +ale_dma_free(struct ale_softc *sc) +{ + struct ale_txdesc *txd; + int i; + + /* Tx buffers. */ + if (sc->ale_cdata.ale_tx_tag != NULL) { + for (i = 0; i < ALE_TX_RING_CNT; i++) { + txd = &sc->ale_cdata.ale_txdesc[i]; + if (txd->tx_dmamap != NULL) { + bus_dmamap_destroy(sc->ale_cdata.ale_tx_tag, + txd->tx_dmamap); + txd->tx_dmamap = NULL; + } + } + bus_dma_tag_destroy(sc->ale_cdata.ale_tx_tag); + sc->ale_cdata.ale_tx_tag = NULL; + } + /* Tx descriptor ring. */ + if (sc->ale_cdata.ale_tx_ring_tag != NULL) { + if (sc->ale_cdata.ale_tx_ring_map != NULL) + bus_dmamap_unload(sc->ale_cdata.ale_tx_ring_tag, + sc->ale_cdata.ale_tx_ring_map); + if (sc->ale_cdata.ale_tx_ring_map != NULL && + sc->ale_cdata.ale_tx_ring != NULL) + bus_dmamem_free(sc->ale_cdata.ale_tx_ring_tag, + sc->ale_cdata.ale_tx_ring, + sc->ale_cdata.ale_tx_ring_map); + sc->ale_cdata.ale_tx_ring = NULL; + sc->ale_cdata.ale_tx_ring_map = NULL; + bus_dma_tag_destroy(sc->ale_cdata.ale_tx_ring_tag); + sc->ale_cdata.ale_tx_ring_tag = NULL; + } + /* Rx page block. */ + for (i = 0; i < ALE_RX_PAGES; i++) { + if (sc->ale_cdata.ale_rx_page[i].page_tag != NULL) { + if (sc->ale_cdata.ale_rx_page[i].page_map != NULL) + bus_dmamap_unload( + sc->ale_cdata.ale_rx_page[i].page_tag, + sc->ale_cdata.ale_rx_page[i].page_map); + if (sc->ale_cdata.ale_rx_page[i].page_map != NULL && + sc->ale_cdata.ale_rx_page[i].page_addr != NULL) + bus_dmamem_free( + sc->ale_cdata.ale_rx_page[i].page_tag, + sc->ale_cdata.ale_rx_page[i].page_addr, + sc->ale_cdata.ale_rx_page[i].page_map); + sc->ale_cdata.ale_rx_page[i].page_addr = NULL; + sc->ale_cdata.ale_rx_page[i].page_map = NULL; + bus_dma_tag_destroy( + sc->ale_cdata.ale_rx_page[i].page_tag); + sc->ale_cdata.ale_rx_page[i].page_tag = NULL; + } + } + /* Rx CMB. */ + for (i = 0; i < ALE_RX_PAGES; i++) { + if (sc->ale_cdata.ale_rx_page[i].cmb_tag != NULL) { + if (sc->ale_cdata.ale_rx_page[i].cmb_map != NULL) + bus_dmamap_unload( + sc->ale_cdata.ale_rx_page[i].cmb_tag, + sc->ale_cdata.ale_rx_page[i].cmb_map); + if (sc->ale_cdata.ale_rx_page[i].cmb_map != NULL && + sc->ale_cdata.ale_rx_page[i].cmb_addr != NULL) + bus_dmamem_free( + sc->ale_cdata.ale_rx_page[i].cmb_tag, + sc->ale_cdata.ale_rx_page[i].cmb_addr, + sc->ale_cdata.ale_rx_page[i].cmb_map); + sc->ale_cdata.ale_rx_page[i].cmb_addr = NULL; + sc->ale_cdata.ale_rx_page[i].cmb_map = NULL; + bus_dma_tag_destroy( + sc->ale_cdata.ale_rx_page[i].cmb_tag); + sc->ale_cdata.ale_rx_page[i].cmb_tag = NULL; + } + } + /* Tx CMB. */ + if (sc->ale_cdata.ale_tx_cmb_tag != NULL) { + if (sc->ale_cdata.ale_tx_cmb_map != NULL) + bus_dmamap_unload(sc->ale_cdata.ale_tx_cmb_tag, + sc->ale_cdata.ale_tx_cmb_map); + if (sc->ale_cdata.ale_tx_cmb_map != NULL && + sc->ale_cdata.ale_tx_cmb != NULL) + bus_dmamem_free(sc->ale_cdata.ale_tx_cmb_tag, + sc->ale_cdata.ale_tx_cmb, + sc->ale_cdata.ale_tx_cmb_map); + sc->ale_cdata.ale_tx_cmb = NULL; + sc->ale_cdata.ale_tx_cmb_map = NULL; + bus_dma_tag_destroy(sc->ale_cdata.ale_tx_cmb_tag); + sc->ale_cdata.ale_tx_cmb_tag = NULL; + } + if (sc->ale_cdata.ale_buffer_tag != NULL) { + bus_dma_tag_destroy(sc->ale_cdata.ale_buffer_tag); + sc->ale_cdata.ale_buffer_tag = NULL; + } + if (sc->ale_cdata.ale_parent_tag != NULL) { + bus_dma_tag_destroy(sc->ale_cdata.ale_parent_tag); + sc->ale_cdata.ale_parent_tag = NULL; + } +} + +static int +ale_shutdown(device_t dev) +{ + return (ale_suspend(dev)); +} + +#ifdef notyet + +/* + * Note, this driver resets the link speed to 10/100Mbps by + * restarting auto-negotiation in suspend/shutdown phase but we + * don't know whether that auto-negotiation would succeed or not + * as driver has no control after powering off/suspend operation. + * If the renegotiation fail WOL may not work. Running at 1Gbps + * will draw more power than 375mA at 3.3V which is specified in + * PCI specification and that would result in complete + * shutdowning power to ethernet controller. + * + * TODO + * Save current negotiated media speed/duplex/flow-control to + * softc and restore the same link again after resuming. PHY + * handling such as power down/resetting to 100Mbps may be better + * handled in suspend method in phy driver. + */ +static void +ale_setlinkspeed(struct ale_softc *sc) +{ + struct mii_data *mii; + int aneg, i; + + mii = device_get_softc(sc->ale_miibus); + mii_pollstat(mii); + aneg = 0; + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID)) { + switch IFM_SUBTYPE(mii->mii_media_active) { + case IFM_10_T: + case IFM_100_TX: + return; + case IFM_1000_T: + aneg++; + break; + default: + break; + } + } + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, MII_100T2CR, 0); + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + MII_ANAR, ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA); + ale_miibus_writereg(sc->ale_dev, sc->ale_phyaddr, + MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG); + DELAY(1000); + if (aneg != 0) { + /* + * Poll link state until ale(4) get a 10/100Mbps link. + */ + for (i = 0; i < MII_ANEGTICKS_GIGE; i++) { + mii_pollstat(mii); + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) + == (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE( + mii->mii_media_active)) { + case IFM_10_T: + case IFM_100_TX: + ale_mac_config(sc); + return; + default: + break; + } + } + ALE_UNLOCK(sc); + pause("alelnk", hz); + ALE_LOCK(sc); + } + if (i == MII_ANEGTICKS_GIGE) + device_printf(sc->ale_dev, + "establishing a link failed, WOL may not work!"); + } + /* + * No link, force MAC to have 100Mbps, full-duplex link. + * This is the last resort and may/may not work. + */ + mii->mii_media_status = IFM_AVALID | IFM_ACTIVE; + mii->mii_media_active = IFM_ETHER | IFM_100_TX | IFM_FDX; + ale_mac_config(sc); +} + +static void +ale_setwol(struct ale_softc *sc) +{ + struct ifnet *ifp; + uint32_t reg, pmcs; + uint16_t pmstat; + int pmc; + + ALE_LOCK_ASSERT(sc); + + if (pci_find_extcap(sc->ale_dev, PCIY_PMG, &pmc) != 0) { + /* Disable WOL. */ + CSR_WRITE_4(sc, ALE_WOL_CFG, 0); + reg = CSR_READ_4(sc, ALE_PCIE_PHYMISC); + reg |= PCIE_PHYMISC_FORCE_RCV_DET; + CSR_WRITE_4(sc, ALE_PCIE_PHYMISC, reg); + /* Force PHY power down. */ + CSR_WRITE_2(sc, ALE_GPHY_CTRL, + GPHY_CTRL_EXT_RESET | GPHY_CTRL_HIB_EN | + GPHY_CTRL_HIB_PULSE | GPHY_CTRL_PHY_PLL_ON | + GPHY_CTRL_SEL_ANA_RESET | GPHY_CTRL_PHY_IDDQ | + GPHY_CTRL_PCLK_SEL_DIS | GPHY_CTRL_PWDOWN_HW); + return; + } + + ifp = sc->ale_ifp; + if ((ifp->if_capenable & IFCAP_WOL) != 0) { + if ((sc->ale_flags & ALE_FLAG_FASTETHER) == 0) + ale_setlinkspeed(sc); + } + + pmcs = 0; + if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) + pmcs |= WOL_CFG_MAGIC | WOL_CFG_MAGIC_ENB; + CSR_WRITE_4(sc, ALE_WOL_CFG, pmcs); + reg = CSR_READ_4(sc, ALE_MAC_CFG); + reg &= ~(MAC_CFG_DBG | MAC_CFG_PROMISC | MAC_CFG_ALLMULTI | + MAC_CFG_BCAST); + if ((ifp->if_capenable & IFCAP_WOL_MCAST) != 0) + reg |= MAC_CFG_ALLMULTI | MAC_CFG_BCAST; + if ((ifp->if_capenable & IFCAP_WOL) != 0) + reg |= MAC_CFG_RX_ENB; + CSR_WRITE_4(sc, ALE_MAC_CFG, reg); + + if ((ifp->if_capenable & IFCAP_WOL) == 0) { + /* WOL disabled, PHY power down. */ + reg = CSR_READ_4(sc, ALE_PCIE_PHYMISC); + reg |= PCIE_PHYMISC_FORCE_RCV_DET; + CSR_WRITE_4(sc, ALE_PCIE_PHYMISC, reg); + CSR_WRITE_2(sc, ALE_GPHY_CTRL, + GPHY_CTRL_EXT_RESET | GPHY_CTRL_HIB_EN | + GPHY_CTRL_HIB_PULSE | GPHY_CTRL_SEL_ANA_RESET | + GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PCLK_SEL_DIS | + GPHY_CTRL_PWDOWN_HW); + } + /* Request PME. */ + pmstat = pci_read_config(sc->ale_dev, pmc + PCIR_POWER_STATUS, 2); + pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); + if ((ifp->if_capenable & IFCAP_WOL) != 0) + pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; + pci_write_config(sc->ale_dev, pmc + PCIR_POWER_STATUS, pmstat, 2); +} + +#endif /* notyet */ + +static int +ale_suspend(device_t dev) +{ + struct ale_softc *sc = device_get_softc(dev); + struct ifnet *ifp = &sc->arpcom.ac_if; + + lwkt_serialize_enter(ifp->if_serializer); + ale_stop(sc); +#ifdef notyet + ale_setwol(sc); +#endif + lwkt_serialize_exit(ifp->if_serializer); + return (0); +} + +static int +ale_resume(device_t dev) +{ + struct ale_softc *sc = device_get_softc(dev); + struct ifnet *ifp = &sc->arpcom.ac_if; + uint16_t cmd; + + lwkt_serialize_enter(ifp->if_serializer); + + /* + * Clear INTx emulation disable for hardwares that + * is set in resume event. From Linux. + */ + cmd = pci_read_config(sc->ale_dev, PCIR_COMMAND, 2); + if ((cmd & 0x0400) != 0) { + cmd &= ~0x0400; + pci_write_config(sc->ale_dev, PCIR_COMMAND, cmd, 2); + } + +#ifdef notyet + if (pci_find_extcap(sc->ale_dev, PCIY_PMG, &pmc) == 0) { + uint16_t pmstat; + int pmc; + + /* Disable PME and clear PME status. */ + pmstat = pci_read_config(sc->ale_dev, + pmc + PCIR_POWER_STATUS, 2); + if ((pmstat & PCIM_PSTAT_PMEENABLE) != 0) { + pmstat &= ~PCIM_PSTAT_PMEENABLE; + pci_write_config(sc->ale_dev, + pmc + PCIR_POWER_STATUS, pmstat, 2); + } + } +#endif + + /* Reset PHY. */ + ale_phy_reset(sc); + if ((ifp->if_flags & IFF_UP) != 0) + ale_init(sc); + + lwkt_serialize_exit(ifp->if_serializer); + return (0); +} + +static int +ale_encap(struct ale_softc *sc, struct mbuf **m_head) +{ + struct ale_txdesc *txd, *txd_last; + struct tx_desc *desc; + struct mbuf *m; + bus_dma_segment_t txsegs[ALE_MAXTXSEGS]; + struct ale_dmamap_ctx ctx; + bus_dmamap_t map; + uint32_t cflags, poff, vtag; + int error, i, nsegs, prod, si; + + M_ASSERTPKTHDR((*m_head)); + + m = *m_head; + cflags = vtag = 0; + poff = 0; + + si = prod = sc->ale_cdata.ale_tx_prod; + txd = &sc->ale_cdata.ale_txdesc[prod]; + txd_last = txd; + map = txd->tx_dmamap; + + ctx.nsegs = ALE_MAXTXSEGS; + ctx.segs = txsegs; + error = bus_dmamap_load_mbuf(sc->ale_cdata.ale_tx_tag, map, + *m_head, ale_dmamap_buf_cb, &ctx, + BUS_DMA_NOWAIT); + if (error == EFBIG) { + m = m_defrag(*m_head, MB_DONTWAIT); + if (m == NULL) { + m_freem(*m_head); + *m_head = NULL; + return (ENOMEM); + } + *m_head = m; + + ctx.nsegs = ALE_MAXTXSEGS; + ctx.segs = txsegs; + error = bus_dmamap_load_mbuf(sc->ale_cdata.ale_tx_tag, map, + *m_head, ale_dmamap_buf_cb, &ctx, + BUS_DMA_NOWAIT); + if (error != 0) { + m_freem(*m_head); + *m_head = NULL; + return (error); + } + } else if (error != 0) { + return (error); + } + nsegs = ctx.nsegs; + + if (nsegs == 0) { + m_freem(*m_head); + *m_head = NULL; + return (EIO); + } + + /* Check descriptor overrun. */ + if (sc->ale_cdata.ale_tx_cnt + nsegs >= ALE_TX_RING_CNT - 2) { + bus_dmamap_unload(sc->ale_cdata.ale_tx_tag, map); + return (ENOBUFS); + } + bus_dmamap_sync(sc->ale_cdata.ale_tx_tag, map, BUS_DMASYNC_PREWRITE); + + m = *m_head; + /* Configure Tx checksum offload. */ + if ((m->m_pkthdr.csum_flags & ALE_CSUM_FEATURES) != 0) { + /* + * AR81xx supports Tx custom checksum offload feature + * that offloads single 16bit checksum computation. + * So you can choose one among IP, TCP and UDP. + * Normally driver sets checksum start/insertion + * position from the information of TCP/UDP frame as + * TCP/UDP checksum takes more time than that of IP. + * However it seems that custom checksum offload + * requires 4 bytes aligned Tx buffers due to hardware + * bug. + * AR81xx also supports explicit Tx checksum computation + * if it is told that the size of IP header and TCP + * header(for UDP, the header size does not matter + * because it's fixed length). However with this scheme + * TSO does not work so you have to choose one either + * TSO or explicit Tx checksum offload. I chosen TSO + * plus custom checksum offload with work-around which + * will cover most common usage for this consumer + * ethernet controller. The work-around takes a lot of + * CPU cycles if Tx buffer is not aligned on 4 bytes + * boundary, though. + */ + cflags |= ALE_TD_CXSUM; + /* Set checksum start offset. */ + cflags |= (poff << ALE_TD_CSUM_PLOADOFFSET_SHIFT); + /* Set checksum insertion position of TCP/UDP. */ + cflags |= ((poff + m->m_pkthdr.csum_data) << + ALE_TD_CSUM_XSUMOFFSET_SHIFT); + } + + /* Configure VLAN hardware tag insertion. */ + if ((m->m_flags & M_VLANTAG) != 0) { + vtag = ALE_TX_VLAN_TAG(m->m_pkthdr.ether_vlantag); + vtag = ((vtag << ALE_TD_VLAN_SHIFT) & ALE_TD_VLAN_MASK); + cflags |= ALE_TD_INSERT_VLAN_TAG; + } + + desc = NULL; + for (i = 0; i < nsegs; i++) { + desc = &sc->ale_cdata.ale_tx_ring[prod]; + desc->addr = htole64(txsegs[i].ds_addr); + desc->len = htole32(ALE_TX_BYTES(txsegs[i].ds_len) | vtag); + desc->flags = htole32(cflags); + sc->ale_cdata.ale_tx_cnt++; + ALE_DESC_INC(prod, ALE_TX_RING_CNT); + } + /* Update producer index. */ + sc->ale_cdata.ale_tx_prod = prod; + + /* Finally set EOP on the last descriptor. */ + prod = (prod + ALE_TX_RING_CNT - 1) % ALE_TX_RING_CNT; + desc = &sc->ale_cdata.ale_tx_ring[prod]; + desc->flags |= htole32(ALE_TD_EOP); + + /* Swap dmamap of the first and the last. */ + txd = &sc->ale_cdata.ale_txdesc[prod]; + map = txd_last->tx_dmamap; + txd_last->tx_dmamap = txd->tx_dmamap; + txd->tx_dmamap = map; + txd->tx_m = m; + + /* Sync descriptors. */ + bus_dmamap_sync(sc->ale_cdata.ale_tx_ring_tag, + sc->ale_cdata.ale_tx_ring_map, BUS_DMASYNC_PREWRITE); + + return (0); +} + +static void +ale_start(struct ifnet *ifp) +{ + struct ale_softc *sc = ifp->if_softc; + struct mbuf *m_head; + int enq; + + ASSERT_SERIALIZED(ifp->if_serializer); + + if ((sc->ale_flags & ALE_FLAG_LINK) == 0) { + ifq_purge(&ifp->if_snd); + return; + } + + if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) + return; + + /* Reclaim transmitted frames. */ + if (sc->ale_cdata.ale_tx_cnt >= ALE_TX_DESC_HIWAT) + ale_txeof(sc); + + enq = 0; + while (!ifq_is_empty(&ifp->if_snd)) { + m_head = ifq_dequeue(&ifp->if_snd, NULL); + if (m_head == NULL) + break; + + /* + * Pack the data into the transmit ring. If we + * don't have room, set the OACTIVE flag and wait + * for the NIC to drain the ring. + */ + if (ale_encap(sc, &m_head)) { + if (m_head == NULL) + break; + ifq_prepend(&ifp->if_snd, m_head); + ifp->if_flags |= IFF_OACTIVE; + break; + } + enq = 1; + + /* + * If there's a BPF listener, bounce a copy of this frame + * to him. + */ + ETHER_BPF_MTAP(ifp, m_head); + } + + if (enq) { + /* Kick. */ + CSR_WRITE_4(sc, ALE_MBOX_TPD_PROD_IDX, + sc->ale_cdata.ale_tx_prod); + + /* Set a timeout in case the chip goes out to lunch. */ + ifp->if_timer = ALE_TX_TIMEOUT; + } +} + +static void +ale_watchdog(struct ifnet *ifp) +{ + struct ale_softc *sc = ifp->if_softc; + + ASSERT_SERIALIZED(ifp->if_serializer); + + if ((sc->ale_flags & ALE_FLAG_LINK) == 0) { + if_printf(ifp, "watchdog timeout (lost link)\n"); + ifp->if_oerrors++; + ale_init(sc); + return; + } + + if_printf(ifp, "watchdog timeout -- resetting\n"); + ifp->if_oerrors++; + ale_init(sc); + + if (!ifq_is_empty(&ifp->if_snd)) + if_devstart(ifp); +} + +static int +ale_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) +{ + struct ale_softc *sc; + struct ifreq *ifr; + struct mii_data *mii; + int error, mask; + + ASSERT_SERIALIZED(ifp->if_serializer); + + sc = ifp->if_softc; + ifr = (struct ifreq *)data; + error = 0; + + switch (cmd) { + case SIOCSIFMTU: + if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ALE_JUMBO_MTU || + ((sc->ale_flags & ALE_FLAG_JUMBO) == 0 && + ifr->ifr_mtu > ETHERMTU)) + error = EINVAL; + else if (ifp->if_mtu != ifr->ifr_mtu) { + ifp->if_mtu = ifr->ifr_mtu; + if ((ifp->if_flags & IFF_RUNNING) != 0) + ale_init(sc); + } + break; + + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) != 0) { + if ((ifp->if_flags & IFF_RUNNING) != 0) { + if (((ifp->if_flags ^ sc->ale_if_flags) + & (IFF_PROMISC | IFF_ALLMULTI)) != 0) + ale_rxfilter(sc); + } else { + if ((sc->ale_flags & ALE_FLAG_DETACH) == 0) + ale_init(sc); + } + } else { + if ((ifp->if_flags & IFF_RUNNING) != 0) + ale_stop(sc); + } + sc->ale_if_flags = ifp->if_flags; + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + if ((ifp->if_flags & IFF_RUNNING) != 0) + ale_rxfilter(sc); + break; + + case SIOCSIFMEDIA: + case SIOCGIFMEDIA: + mii = device_get_softc(sc->ale_miibus); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); + break; + + case SIOCSIFCAP: + mask = ifr->ifr_reqcap ^ ifp->if_capenable; + if ((mask & IFCAP_TXCSUM) != 0 && + (ifp->if_capabilities & IFCAP_TXCSUM) != 0) { + ifp->if_capenable ^= IFCAP_TXCSUM; + if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) + ifp->if_hwassist |= ALE_CSUM_FEATURES; + else + ifp->if_hwassist &= ~ALE_CSUM_FEATURES; + } + if ((mask & IFCAP_RXCSUM) != 0 && + (ifp->if_capabilities & IFCAP_RXCSUM) != 0) + ifp->if_capenable ^= IFCAP_RXCSUM; + + if ((mask & IFCAP_VLAN_HWTAGGING) != 0 && + (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) { + ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; + ale_rxvlan(sc); + } + break; + + default: + error = ether_ioctl(ifp, cmd, data); + break; + } + return (error); +} + +static void +ale_mac_config(struct ale_softc *sc) +{ + struct mii_data *mii; + uint32_t reg; + + mii = device_get_softc(sc->ale_miibus); + reg = CSR_READ_4(sc, ALE_MAC_CFG); + reg &= ~(MAC_CFG_FULL_DUPLEX | MAC_CFG_TX_FC | MAC_CFG_RX_FC | + MAC_CFG_SPEED_MASK); + /* Reprogram MAC with resolved speed/duplex. */ + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_10_T: + case IFM_100_TX: + reg |= MAC_CFG_SPEED_10_100; + break; + case IFM_1000_T: + reg |= MAC_CFG_SPEED_1000; + break; + } + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) { + reg |= MAC_CFG_FULL_DUPLEX; +#ifdef notyet + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0) + reg |= MAC_CFG_TX_FC; + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0) + reg |= MAC_CFG_RX_FC; +#endif + } + CSR_WRITE_4(sc, ALE_MAC_CFG, reg); +} + +static void +ale_stats_clear(struct ale_softc *sc) +{ + struct smb sb; + uint32_t *reg; + int i; + + for (reg = &sb.rx_frames, i = 0; reg <= &sb.rx_pkts_filtered; reg++) { + CSR_READ_4(sc, ALE_RX_MIB_BASE + i); + i += sizeof(uint32_t); + } + /* Read Tx statistics. */ + for (reg = &sb.tx_frames, i = 0; reg <= &sb.tx_mcast_bytes; reg++) { + CSR_READ_4(sc, ALE_TX_MIB_BASE + i); + i += sizeof(uint32_t); + } +} + +static void +ale_stats_update(struct ale_softc *sc) +{ + struct ale_hw_stats *stat; + struct smb sb, *smb; + struct ifnet *ifp; + uint32_t *reg; + int i; + + ifp = &sc->arpcom.ac_if; + stat = &sc->ale_stats; + smb = &sb; + + /* Read Rx statistics. */ + for (reg = &sb.rx_frames, i = 0; reg <= &sb.rx_pkts_filtered; reg++) { + *reg = CSR_READ_4(sc, ALE_RX_MIB_BASE + i); + i += sizeof(uint32_t); + } + /* Read Tx statistics. */ + for (reg = &sb.tx_frames, i = 0; reg <= &sb.tx_mcast_bytes; reg++) { + *reg = CSR_READ_4(sc, ALE_TX_MIB_BASE + i); + i += sizeof(uint32_t); + } + + /* Rx stats. */ + stat->rx_frames += smb->rx_frames; + stat->rx_bcast_frames += smb->rx_bcast_frames; + stat->rx_mcast_frames += smb->rx_mcast_frames; + stat->rx_pause_frames += smb->rx_pause_frames; + stat->rx_control_frames += smb->rx_control_frames; + stat->rx_crcerrs += smb->rx_crcerrs; + stat->rx_lenerrs += smb->rx_lenerrs; + stat->rx_bytes += smb->rx_bytes; + stat->rx_runts += smb->rx_runts; + stat->rx_fragments += smb->rx_fragments; + stat->rx_pkts_64 += smb->rx_pkts_64; + stat->rx_pkts_65_127 += smb->rx_pkts_65_127; + stat->rx_pkts_128_255 += smb->rx_pkts_128_255; + stat->rx_pkts_256_511 += smb->rx_pkts_256_511; + stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023; + stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518; + stat->rx_pkts_1519_max += smb->rx_pkts_1519_max; + stat->rx_pkts_truncated += smb->rx_pkts_truncated; + stat->rx_fifo_oflows += smb->rx_fifo_oflows; + stat->rx_rrs_errs += smb->rx_rrs_errs; + stat->rx_alignerrs += smb->rx_alignerrs; + stat->rx_bcast_bytes += smb->rx_bcast_bytes; + stat->rx_mcast_bytes += smb->rx_mcast_bytes; + stat->rx_pkts_filtered += smb->rx_pkts_filtered; + + /* Tx stats. */ + stat->tx_frames += smb->tx_frames; + stat->tx_bcast_frames += smb->tx_bcast_frames; + stat->tx_mcast_frames += smb->tx_mcast_frames; + stat->tx_pause_frames += smb->tx_pause_frames; + stat->tx_excess_defer += smb->tx_excess_defer; + stat->tx_control_frames += smb->tx_control_frames; + stat->tx_deferred += smb->tx_deferred; + stat->tx_bytes += smb->tx_bytes; + stat->tx_pkts_64 += smb->tx_pkts_64; + stat->tx_pkts_65_127 += smb->tx_pkts_65_127; + stat->tx_pkts_128_255 += smb->tx_pkts_128_255; + stat->tx_pkts_256_511 += smb->tx_pkts_256_511; + stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023; + stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518; + stat->tx_pkts_1519_max += smb->tx_pkts_1519_max; + stat->tx_single_colls += smb->tx_single_colls; + stat->tx_multi_colls += smb->tx_multi_colls; + stat->tx_late_colls += smb->tx_late_colls; + stat->tx_excess_colls += smb->tx_excess_colls; + stat->tx_abort += smb->tx_abort; + stat->tx_underrun += smb->tx_underrun; + stat->tx_desc_underrun += smb->tx_desc_underrun; + stat->tx_lenerrs += smb->tx_lenerrs; + stat->tx_pkts_truncated += smb->tx_pkts_truncated; + stat->tx_bcast_bytes += smb->tx_bcast_bytes; + stat->tx_mcast_bytes += smb->tx_mcast_bytes; + + /* Update counters in ifnet. */ + ifp->if_opackets += smb->tx_frames; + + ifp->if_collisions += smb->tx_single_colls + + smb->tx_multi_colls * 2 + smb->tx_late_colls + + smb->tx_abort * HDPX_CFG_RETRY_DEFAULT; + + /* + * XXX + * tx_pkts_truncated counter looks suspicious. It constantly + * increments with no sign of Tx errors. This may indicate + * the counter name is not correct one so I've removed the + * counter in output errors. + */ + ifp->if_oerrors += smb->tx_abort + smb->tx_late_colls + + smb->tx_underrun; + + ifp->if_ipackets += smb->rx_frames; + + ifp->if_ierrors += smb->rx_crcerrs + smb->rx_lenerrs + + smb->rx_runts + smb->rx_pkts_truncated + + smb->rx_fifo_oflows + smb->rx_rrs_errs + + smb->rx_alignerrs; +} + +static void +ale_intr(void *xsc) +{ + struct ale_softc *sc = xsc; + struct ifnet *ifp = &sc->arpcom.ac_if; + uint32_t status; + + ASSERT_SERIALIZED(ifp->if_serializer); + + status = CSR_READ_4(sc, ALE_INTR_STATUS); + if ((status & ALE_INTRS) == 0) + return; + + /* Acknowledge and disable interrupts. */ + CSR_WRITE_4(sc, ALE_INTR_STATUS, status | INTR_DIS_INT); + + if ((ifp->if_flags & IFF_RUNNING) != 0) { + int error; + + error = ale_rxeof(sc); + if (error) { + sc->ale_stats.reset_brk_seq++; + ale_init(sc); + return; + } + + if ((status & (INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST)) != 0) { + if ((status & INTR_DMA_RD_TO_RST) != 0) + device_printf(sc->ale_dev, + "DMA read error! -- resetting\n"); + if ((status & INTR_DMA_WR_TO_RST) != 0) + device_printf(sc->ale_dev, + "DMA write error! -- resetting\n"); + ale_init(sc); + return; + } + + ale_txeof(sc); + if (!ifq_is_empty(&ifp->if_snd)) + if_devstart(ifp); + } + + /* Re-enable interrupts. */ + CSR_WRITE_4(sc, ALE_INTR_STATUS, 0x7FFFFFFF); +} + +static void +ale_txeof(struct ale_softc *sc) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + struct ale_txdesc *txd; + uint32_t cons, prod; + int prog; + + if (sc->ale_cdata.ale_tx_cnt == 0) + return; + + bus_dmamap_sync(sc->ale_cdata.ale_tx_ring_tag, + sc->ale_cdata.ale_tx_ring_map, BUS_DMASYNC_POSTREAD); + if ((sc->ale_flags & ALE_FLAG_TXCMB_BUG) == 0) { + bus_dmamap_sync(sc->ale_cdata.ale_tx_cmb_tag, + sc->ale_cdata.ale_tx_cmb_map, BUS_DMASYNC_POSTREAD); + prod = *sc->ale_cdata.ale_tx_cmb & TPD_CNT_MASK; + } else + prod = CSR_READ_2(sc, ALE_TPD_CONS_IDX); + cons = sc->ale_cdata.ale_tx_cons; + /* + * Go through our Tx list and free mbufs for those + * frames which have been transmitted. + */ + for (prog = 0; cons != prod; prog++, + ALE_DESC_INC(cons, ALE_TX_RING_CNT)) { + if (sc->ale_cdata.ale_tx_cnt <= 0) + break; + prog++; + ifp->if_flags &= ~IFF_OACTIVE; + sc->ale_cdata.ale_tx_cnt--; + txd = &sc->ale_cdata.ale_txdesc[cons]; + if (txd->tx_m != NULL) { + /* Reclaim transmitted mbufs. */ + bus_dmamap_unload(sc->ale_cdata.ale_tx_tag, + txd->tx_dmamap); + m_freem(txd->tx_m); + txd->tx_m = NULL; + } + } + + if (prog > 0) { + sc->ale_cdata.ale_tx_cons = cons; + /* + * Unarm watchdog timer only when there is no pending + * Tx descriptors in queue. + */ + if (sc->ale_cdata.ale_tx_cnt == 0) + ifp->if_timer = 0; + } +} + +static void +ale_rx_update_page(struct ale_softc *sc, struct ale_rx_page **page, + uint32_t length, uint32_t *prod) +{ + struct ale_rx_page *rx_page; + + rx_page = *page; + /* Update consumer position. */ + rx_page->cons += roundup(length + sizeof(struct rx_rs), + ALE_RX_PAGE_ALIGN); + if (rx_page->cons >= ALE_RX_PAGE_SZ) { + /* + * End of Rx page reached, let hardware reuse + * this page. + */ + rx_page->cons = 0; + *rx_page->cmb_addr = 0; + bus_dmamap_sync(rx_page->cmb_tag, rx_page->cmb_map, + BUS_DMASYNC_PREWRITE); + CSR_WRITE_1(sc, ALE_RXF0_PAGE0 + sc->ale_cdata.ale_rx_curp, + RXF_VALID); + /* Switch to alternate Rx page. */ + sc->ale_cdata.ale_rx_curp ^= 1; + rx_page = *page = + &sc->ale_cdata.ale_rx_page[sc->ale_cdata.ale_rx_curp]; + /* Page flipped, sync CMB and Rx page. */ + bus_dmamap_sync(rx_page->page_tag, rx_page->page_map, + BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(rx_page->cmb_tag, rx_page->cmb_map, + BUS_DMASYNC_POSTREAD); + /* Sync completed, cache updated producer index. */ + *prod = *rx_page->cmb_addr; + } +} + + +/* + * It seems that AR81xx controller can compute partial checksum. + * The partial checksum value can be used to accelerate checksum + * computation for fragmented TCP/UDP packets. Upper network stack + * already takes advantage of the partial checksum value in IP + * reassembly stage. But I'm not sure the correctness of the + * partial hardware checksum assistance due to lack of data sheet. + * In addition, the Rx feature of controller that requires copying + * for every frames effectively nullifies one of most nice offload + * capability of controller. + */ +static void +ale_rxcsum(struct ale_softc *sc, struct mbuf *m, uint32_t status) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + struct ip *ip; + char *p; + + m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; + if ((status & ALE_RD_IPCSUM_NOK) == 0) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; + + if ((sc->ale_flags & ALE_FLAG_RXCSUM_BUG) == 0) { + if (((status & ALE_RD_IPV4_FRAG) == 0) && + ((status & (ALE_RD_TCP | ALE_RD_UDP)) != 0) && + ((status & ALE_RD_TCP_UDPCSUM_NOK) == 0)) { + m->m_pkthdr.csum_flags |= + CSUM_DATA_VALID | CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + } else { + if ((status & (ALE_RD_TCP | ALE_RD_UDP)) != 0 && + (status & ALE_RD_TCP_UDPCSUM_NOK) == 0) { + p = mtod(m, char *); + p += ETHER_HDR_LEN; + if ((status & ALE_RD_802_3) != 0) + p += LLC_SNAPFRAMELEN; + if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0 && + (status & ALE_RD_VLAN) != 0) + p += EVL_ENCAPLEN; + ip = (struct ip *)p; + if (ip->ip_off != 0 && (status & ALE_RD_IPV4_DF) == 0) + return; + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | + CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + } + /* + * Don't mark bad checksum for TCP/UDP frames + * as fragmented frames may always have set + * bad checksummed bit of frame status. + */ +} + +/* Process received frames. */ +static int +ale_rxeof(struct ale_softc *sc) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + struct ale_rx_page *rx_page; + struct rx_rs *rs; + struct mbuf *m; + uint32_t length, prod, seqno, status, vtags; + int prog; + + rx_page = &sc->ale_cdata.ale_rx_page[sc->ale_cdata.ale_rx_curp]; + bus_dmamap_sync(rx_page->cmb_tag, rx_page->cmb_map, + BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(rx_page->page_tag, rx_page->page_map, + BUS_DMASYNC_POSTREAD); + /* + * Don't directly access producer index as hardware may + * update it while Rx handler is in progress. It would + * be even better if there is a way to let hardware + * know how far driver processed its received frames. + * Alternatively, hardware could provide a way to disable + * CMB updates until driver acknowledges the end of CMB + * access. + */ + prod = *rx_page->cmb_addr; + for (prog = 0; ; prog++) { + if (rx_page->cons >= prod) + break; + rs = (struct rx_rs *)(rx_page->page_addr + rx_page->cons); + seqno = ALE_RX_SEQNO(le32toh(rs->seqno)); + if (sc->ale_cdata.ale_rx_seqno != seqno) { + /* + * Normally I believe this should not happen unless + * severe driver bug or corrupted memory. However + * it seems to happen under certain conditions which + * is triggered by abrupt Rx events such as initiation + * of bulk transfer of remote host. It's not easy to + * reproduce this and I doubt it could be related + * with FIFO overflow of hardware or activity of Tx + * CMB updates. I also remember similar behaviour + * seen on RealTek 8139 which uses resembling Rx + * scheme. + */ + if (bootverbose) + device_printf(sc->ale_dev, + "garbled seq: %u, expected: %u -- " + "resetting!\n", seqno, + sc->ale_cdata.ale_rx_seqno); + return (EIO); + } + /* Frame received. */ + sc->ale_cdata.ale_rx_seqno++; + length = ALE_RX_BYTES(le32toh(rs->length)); + status = le32toh(rs->flags); + if ((status & ALE_RD_ERROR) != 0) { + /* + * We want to pass the following frames to upper + * layer regardless of error status of Rx return + * status. + * + * o IP/TCP/UDP checksum is bad. + * o frame length and protocol specific length + * does not match. + */ + if ((status & (ALE_RD_CRC | ALE_RD_CODE | + ALE_RD_DRIBBLE | ALE_RD_RUNT | ALE_RD_OFLOW | + ALE_RD_TRUNC)) != 0) { + ale_rx_update_page(sc, &rx_page, length, &prod); + continue; + } + } + /* + * m_devget(9) is major bottle-neck of ale(4)(It comes + * from hardware limitation). For jumbo frames we could + * get a slightly better performance if driver use + * m_getjcl(9) with proper buffer size argument. However + * that would make code more complicated and I don't + * think users would expect good Rx performance numbers + * on these low-end consumer ethernet controller. + */ + m = m_devget((char *)(rs + 1), length - ETHER_CRC_LEN, + ETHER_ALIGN, ifp, NULL); + if (m == NULL) { + ifp->if_iqdrops++; + ale_rx_update_page(sc, &rx_page, length, &prod); + continue; + } + if ((ifp->if_capenable & IFCAP_RXCSUM) != 0 && + (status & ALE_RD_IPV4) != 0) + ale_rxcsum(sc, m, status); + if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && + (status & ALE_RD_VLAN) != 0) { + vtags = ALE_RX_VLAN(le32toh(rs->vtags)); + m->m_pkthdr.ether_vlantag = ALE_RX_VLAN_TAG(vtags); + m->m_flags |= M_VLANTAG; + } + + /* Pass it to upper layer. */ + ifp->if_input(ifp, m); + + ale_rx_update_page(sc, &rx_page, length, &prod); + } + return 0; +} + +static void +ale_tick(void *xsc) +{ + struct ale_softc *sc = xsc; + struct ifnet *ifp = &sc->arpcom.ac_if; + struct mii_data *mii; + + lwkt_serialize_enter(ifp->if_serializer); + + mii = device_get_softc(sc->ale_miibus); + mii_tick(mii); + ale_stats_update(sc); + + callout_reset(&sc->ale_tick_ch, hz, ale_tick, sc); + + lwkt_serialize_exit(ifp->if_serializer); +} + +static void +ale_reset(struct ale_softc *sc) +{ + uint32_t reg; + int i; + + /* Initialize PCIe module. From Linux. */ + CSR_WRITE_4(sc, 0x1008, CSR_READ_4(sc, 0x1008) | 0x8000); + + CSR_WRITE_4(sc, ALE_MASTER_CFG, MASTER_RESET); + for (i = ALE_RESET_TIMEOUT; i > 0; i--) { + DELAY(10); + if ((CSR_READ_4(sc, ALE_MASTER_CFG) & MASTER_RESET) == 0) + break; + } + if (i == 0) + device_printf(sc->ale_dev, "master reset timeout!\n"); + + for (i = ALE_RESET_TIMEOUT; i > 0; i--) { + if ((reg = CSR_READ_4(sc, ALE_IDLE_STATUS)) == 0) + break; + DELAY(10); + } + + if (i == 0) + device_printf(sc->ale_dev, "reset timeout(0x%08x)!\n", reg); +} + +static void +ale_init(void *xsc) +{ + struct ale_softc *sc = xsc; + struct ifnet *ifp = &sc->arpcom.ac_if; + struct mii_data *mii; + uint8_t eaddr[ETHER_ADDR_LEN]; + bus_addr_t paddr; + uint32_t reg, rxf_hi, rxf_lo; + + ASSERT_SERIALIZED(ifp->if_serializer); + + mii = device_get_softc(sc->ale_miibus); + + /* + * Cancel any pending I/O. + */ + ale_stop(sc); + + /* + * Reset the chip to a known state. + */ + ale_reset(sc); + + /* Initialize Tx descriptors, DMA memory blocks. */ + ale_init_rx_pages(sc); + ale_init_tx_ring(sc); + + /* Reprogram the station address. */ + bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN); + CSR_WRITE_4(sc, ALE_PAR0, + eaddr[2] << 24 | eaddr[3] << 16 | eaddr[4] << 8 | eaddr[5]); + CSR_WRITE_4(sc, ALE_PAR1, eaddr[0] << 8 | eaddr[1]); + + /* + * Clear WOL status and disable all WOL feature as WOL + * would interfere Rx operation under normal environments. + */ + CSR_READ_4(sc, ALE_WOL_CFG); + CSR_WRITE_4(sc, ALE_WOL_CFG, 0); + + /* + * Set Tx descriptor/RXF0/CMB base addresses. They share + * the same high address part of DMAable region. + */ + paddr = sc->ale_cdata.ale_tx_ring_paddr; + CSR_WRITE_4(sc, ALE_TPD_ADDR_HI, ALE_ADDR_HI(paddr)); + CSR_WRITE_4(sc, ALE_TPD_ADDR_LO, ALE_ADDR_LO(paddr)); + CSR_WRITE_4(sc, ALE_TPD_CNT, + (ALE_TX_RING_CNT << TPD_CNT_SHIFT) & TPD_CNT_MASK); + + /* Set Rx page base address, note we use single queue. */ + paddr = sc->ale_cdata.ale_rx_page[0].page_paddr; + CSR_WRITE_4(sc, ALE_RXF0_PAGE0_ADDR_LO, ALE_ADDR_LO(paddr)); + paddr = sc->ale_cdata.ale_rx_page[1].page_paddr; + CSR_WRITE_4(sc, ALE_RXF0_PAGE1_ADDR_LO, ALE_ADDR_LO(paddr)); + + /* Set Tx/Rx CMB addresses. */ + paddr = sc->ale_cdata.ale_tx_cmb_paddr; + CSR_WRITE_4(sc, ALE_TX_CMB_ADDR_LO, ALE_ADDR_LO(paddr)); + paddr = sc->ale_cdata.ale_rx_page[0].cmb_paddr; + CSR_WRITE_4(sc, ALE_RXF0_CMB0_ADDR_LO, ALE_ADDR_LO(paddr)); + paddr = sc->ale_cdata.ale_rx_page[1].cmb_paddr; + CSR_WRITE_4(sc, ALE_RXF0_CMB1_ADDR_LO, ALE_ADDR_LO(paddr)); + + /* Mark RXF0 is valid. */ + CSR_WRITE_1(sc, ALE_RXF0_PAGE0, RXF_VALID); + CSR_WRITE_1(sc, ALE_RXF0_PAGE1, RXF_VALID); + /* + * No need to initialize RFX1/RXF2/RXF3. We don't use + * multi-queue yet. + */ + + /* Set Rx page size, excluding guard frame size. */ + CSR_WRITE_4(sc, ALE_RXF_PAGE_SIZE, ALE_RX_PAGE_SZ); + + /* Tell hardware that we're ready to load DMA blocks. */ + CSR_WRITE_4(sc, ALE_DMA_BLOCK, DMA_BLOCK_LOAD); + + /* Set Rx/Tx interrupt trigger threshold. */ + CSR_WRITE_4(sc, ALE_INT_TRIG_THRESH, (1 << INT_TRIG_RX_THRESH_SHIFT) | + (4 << INT_TRIG_TX_THRESH_SHIFT)); + /* + * XXX + * Set interrupt trigger timer, its purpose and relation + * with interrupt moderation mechanism is not clear yet. + */ + CSR_WRITE_4(sc, ALE_INT_TRIG_TIMER, + ((ALE_USECS(10) << INT_TRIG_RX_TIMER_SHIFT) | + (ALE_USECS(1000) << INT_TRIG_TX_TIMER_SHIFT))); + + /* Configure interrupt moderation timer. */ + reg = ALE_USECS(sc->ale_int_rx_mod) << IM_TIMER_RX_SHIFT; + reg |= ALE_USECS(sc->ale_int_tx_mod) << IM_TIMER_TX_SHIFT; + CSR_WRITE_4(sc, ALE_IM_TIMER, reg); + reg = CSR_READ_4(sc, ALE_MASTER_CFG); + reg &= ~(MASTER_CHIP_REV_MASK | MASTER_CHIP_ID_MASK); + reg &= ~(MASTER_IM_RX_TIMER_ENB | MASTER_IM_TX_TIMER_ENB); + if (ALE_USECS(sc->ale_int_rx_mod) != 0) + reg |= MASTER_IM_RX_TIMER_ENB; + if (ALE_USECS(sc->ale_int_tx_mod) != 0) + reg |= MASTER_IM_TX_TIMER_ENB; + CSR_WRITE_4(sc, ALE_MASTER_CFG, reg); + CSR_WRITE_2(sc, ALE_INTR_CLR_TIMER, ALE_USECS(1000)); + + /* Set Maximum frame size of controller. */ + if (ifp->if_mtu < ETHERMTU) + sc->ale_max_frame_size = ETHERMTU; + else + sc->ale_max_frame_size = ifp->if_mtu; + sc->ale_max_frame_size += ETHER_HDR_LEN + EVL_ENCAPLEN + ETHER_CRC_LEN; + CSR_WRITE_4(sc, ALE_FRAME_SIZE, sc->ale_max_frame_size); + + /* Configure IPG/IFG parameters. */ + CSR_WRITE_4(sc, ALE_IPG_IFG_CFG, + ((IPG_IFG_IPGT_DEFAULT << IPG_IFG_IPGT_SHIFT) & IPG_IFG_IPGT_MASK) | + ((IPG_IFG_MIFG_DEFAULT << IPG_IFG_MIFG_SHIFT) & IPG_IFG_MIFG_MASK) | + ((IPG_IFG_IPG1_DEFAULT << IPG_IFG_IPG1_SHIFT) & IPG_IFG_IPG1_MASK) | + ((IPG_IFG_IPG2_DEFAULT << IPG_IFG_IPG2_SHIFT) & IPG_IFG_IPG2_MASK)); + + /* Set parameters for half-duplex media. */ + CSR_WRITE_4(sc, ALE_HDPX_CFG, + ((HDPX_CFG_LCOL_DEFAULT << HDPX_CFG_LCOL_SHIFT) & + HDPX_CFG_LCOL_MASK) | + ((HDPX_CFG_RETRY_DEFAULT << HDPX_CFG_RETRY_SHIFT) & + HDPX_CFG_RETRY_MASK) | HDPX_CFG_EXC_DEF_EN | + ((HDPX_CFG_ABEBT_DEFAULT << HDPX_CFG_ABEBT_SHIFT) & + HDPX_CFG_ABEBT_MASK) | + ((HDPX_CFG_JAMIPG_DEFAULT << HDPX_CFG_JAMIPG_SHIFT) & + HDPX_CFG_JAMIPG_MASK)); + + /* Configure Tx jumbo frame parameters. */ + if ((sc->ale_flags & ALE_FLAG_JUMBO) != 0) { + if (ifp->if_mtu < ETHERMTU) + reg = sc->ale_max_frame_size; + else if (ifp->if_mtu < 6 * 1024) + reg = (sc->ale_max_frame_size * 2) / 3; + else + reg = sc->ale_max_frame_size / 2; + CSR_WRITE_4(sc, ALE_TX_JUMBO_THRESH, + roundup(reg, TX_JUMBO_THRESH_UNIT) >> + TX_JUMBO_THRESH_UNIT_SHIFT); + } + + /* Configure TxQ. */ + reg = (128 << (sc->ale_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) + << TXQ_CFG_TX_FIFO_BURST_SHIFT; + reg |= (TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) & + TXQ_CFG_TPD_BURST_MASK; + CSR_WRITE_4(sc, ALE_TXQ_CFG, reg | TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB); + + /* Configure Rx jumbo frame & flow control parameters. */ + if ((sc->ale_flags & ALE_FLAG_JUMBO) != 0) { + reg = roundup(sc->ale_max_frame_size, RX_JUMBO_THRESH_UNIT); + CSR_WRITE_4(sc, ALE_RX_JUMBO_THRESH, + (((reg >> RX_JUMBO_THRESH_UNIT_SHIFT) << + RX_JUMBO_THRESH_MASK_SHIFT) & RX_JUMBO_THRESH_MASK) | + ((RX_JUMBO_LKAH_DEFAULT << RX_JUMBO_LKAH_SHIFT) & + RX_JUMBO_LKAH_MASK)); + reg = CSR_READ_4(sc, ALE_SRAM_RX_FIFO_LEN); + rxf_hi = (reg * 7) / 10; + rxf_lo = (reg * 3)/ 10; + CSR_WRITE_4(sc, ALE_RX_FIFO_PAUSE_THRESH, + ((rxf_lo << RX_FIFO_PAUSE_THRESH_LO_SHIFT) & + RX_FIFO_PAUSE_THRESH_LO_MASK) | + ((rxf_hi << RX_FIFO_PAUSE_THRESH_HI_SHIFT) & + RX_FIFO_PAUSE_THRESH_HI_MASK)); + } + + /* Disable RSS. */ + CSR_WRITE_4(sc, ALE_RSS_IDT_TABLE0, 0); + CSR_WRITE_4(sc, ALE_RSS_CPU, 0); + + /* Configure RxQ. */ + CSR_WRITE_4(sc, ALE_RXQ_CFG, + RXQ_CFG_ALIGN_32 | RXQ_CFG_CUT_THROUGH_ENB | RXQ_CFG_ENB); + + /* Configure DMA parameters. */ + reg = 0; + if ((sc->ale_flags & ALE_FLAG_TXCMB_BUG) == 0) + reg |= DMA_CFG_TXCMB_ENB; + CSR_WRITE_4(sc, ALE_DMA_CFG, + DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 | + sc->ale_dma_rd_burst | reg | + sc->ale_dma_wr_burst | DMA_CFG_RXCMB_ENB | + ((DMA_CFG_RD_DELAY_CNT_DEFAULT << DMA_CFG_RD_DELAY_CNT_SHIFT) & + DMA_CFG_RD_DELAY_CNT_MASK) | + ((DMA_CFG_WR_DELAY_CNT_DEFAULT << DMA_CFG_WR_DELAY_CNT_SHIFT) & + DMA_CFG_WR_DELAY_CNT_MASK)); + + /* + * Hardware can be configured to issue SMB interrupt based + * on programmed interval. Since there is a callout that is + * invoked for every hz in driver we use that instead of + * relying on periodic SMB interrupt. + */ + CSR_WRITE_4(sc, ALE_SMB_STAT_TIMER, ALE_USECS(0)); + + /* Clear MAC statistics. */ + ale_stats_clear(sc); + + /* + * Configure Tx/Rx MACs. + * - Auto-padding for short frames. + * - Enable CRC generation. + * Actual reconfiguration of MAC for resolved speed/duplex + * is followed after detection of link establishment. + * AR81xx always does checksum computation regardless of + * MAC_CFG_RXCSUM_ENB bit. In fact, setting the bit will + * cause Rx handling issue for fragmented IP datagrams due + * to silicon bug. + */ + reg = MAC_CFG_TX_CRC_ENB | MAC_CFG_TX_AUTO_PAD | MAC_CFG_FULL_DUPLEX | + ((MAC_CFG_PREAMBLE_DEFAULT << MAC_CFG_PREAMBLE_SHIFT) & + MAC_CFG_PREAMBLE_MASK); + if ((sc->ale_flags & ALE_FLAG_FASTETHER) != 0) + reg |= MAC_CFG_SPEED_10_100; + else + reg |= MAC_CFG_SPEED_1000; + CSR_WRITE_4(sc, ALE_MAC_CFG, reg); + + /* Set up the receive filter. */ + ale_rxfilter(sc); + ale_rxvlan(sc); + + /* Acknowledge all pending interrupts and clear it. */ + CSR_WRITE_4(sc, ALE_INTR_MASK, ALE_INTRS); + CSR_WRITE_4(sc, ALE_INTR_STATUS, 0xFFFFFFFF); + CSR_WRITE_4(sc, ALE_INTR_STATUS, 0); + + sc->ale_flags &= ~ALE_FLAG_LINK; + + /* Switch to the current media. */ + mii_mediachg(mii); + + callout_reset(&sc->ale_tick_ch, hz, ale_tick, sc); + + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; +} + +static void +ale_stop(struct ale_softc *sc) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + struct ale_txdesc *txd; + uint32_t reg; + int i; + + ASSERT_SERIALIZED(ifp->if_serializer); + + /* + * Mark the interface down and cancel the watchdog timer. + */ + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + ifp->if_timer = 0; + + callout_stop(&sc->ale_tick_ch); + sc->ale_flags &= ~ALE_FLAG_LINK; + + ale_stats_update(sc); + + /* Disable interrupts. */ + CSR_WRITE_4(sc, ALE_INTR_MASK, 0); + CSR_WRITE_4(sc, ALE_INTR_STATUS, 0xFFFFFFFF); + + /* Disable queue processing and DMA. */ + reg = CSR_READ_4(sc, ALE_TXQ_CFG); + reg &= ~TXQ_CFG_ENB; + CSR_WRITE_4(sc, ALE_TXQ_CFG, reg); + reg = CSR_READ_4(sc, ALE_RXQ_CFG); + reg &= ~RXQ_CFG_ENB; + CSR_WRITE_4(sc, ALE_RXQ_CFG, reg); + reg = CSR_READ_4(sc, ALE_DMA_CFG); + reg &= ~(DMA_CFG_TXCMB_ENB | DMA_CFG_RXCMB_ENB); + CSR_WRITE_4(sc, ALE_DMA_CFG, reg); + DELAY(1000); + + /* Stop Rx/Tx MACs. */ + ale_stop_mac(sc); + + /* Disable interrupts again? XXX */ + CSR_WRITE_4(sc, ALE_INTR_STATUS, 0xFFFFFFFF); + + /* + * Free TX mbufs still in the queues. + */ + for (i = 0; i < ALE_TX_RING_CNT; i++) { + txd = &sc->ale_cdata.ale_txdesc[i]; + if (txd->tx_m != NULL) { + bus_dmamap_unload(sc->ale_cdata.ale_tx_tag, + txd->tx_dmamap); + m_freem(txd->tx_m); + txd->tx_m = NULL; + } + } +} + +static void +ale_stop_mac(struct ale_softc *sc) +{ + uint32_t reg; + int i; + + reg = CSR_READ_4(sc, ALE_MAC_CFG); + if ((reg & (MAC_CFG_TX_ENB | MAC_CFG_RX_ENB)) != 0) { + reg &= ~MAC_CFG_TX_ENB | MAC_CFG_RX_ENB; + CSR_WRITE_4(sc, ALE_MAC_CFG, reg); + } + + for (i = ALE_TIMEOUT; i > 0; i--) { + reg = CSR_READ_4(sc, ALE_IDLE_STATUS); + if (reg == 0) + break; + DELAY(10); + } + if (i == 0) + device_printf(sc->ale_dev, + "could not disable Tx/Rx MAC(0x%08x)!\n", reg); +} + +static void +ale_init_tx_ring(struct ale_softc *sc) +{ + struct ale_txdesc *txd; + int i; + + sc->ale_cdata.ale_tx_prod = 0; + sc->ale_cdata.ale_tx_cons = 0; + sc->ale_cdata.ale_tx_cnt = 0; + + bzero(sc->ale_cdata.ale_tx_ring, ALE_TX_RING_SZ); + bzero(sc->ale_cdata.ale_tx_cmb, ALE_TX_CMB_SZ); + for (i = 0; i < ALE_TX_RING_CNT; i++) { + txd = &sc->ale_cdata.ale_txdesc[i]; + txd->tx_m = NULL; + } + *sc->ale_cdata.ale_tx_cmb = 0; + bus_dmamap_sync(sc->ale_cdata.ale_tx_cmb_tag, + sc->ale_cdata.ale_tx_cmb_map, + BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sc->ale_cdata.ale_tx_ring_tag, + sc->ale_cdata.ale_tx_ring_map, + BUS_DMASYNC_PREWRITE); +} + +static void +ale_init_rx_pages(struct ale_softc *sc) +{ + struct ale_rx_page *rx_page; + int i; + + sc->ale_cdata.ale_rx_seqno = 0; + sc->ale_cdata.ale_rx_curp = 0; + + for (i = 0; i < ALE_RX_PAGES; i++) { + rx_page = &sc->ale_cdata.ale_rx_page[i]; + bzero(rx_page->page_addr, sc->ale_pagesize); + bzero(rx_page->cmb_addr, ALE_RX_CMB_SZ); + rx_page->cons = 0; + *rx_page->cmb_addr = 0; + bus_dmamap_sync(rx_page->page_tag, rx_page->page_map, + BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(rx_page->cmb_tag, rx_page->cmb_map, + BUS_DMASYNC_PREWRITE); + } +} + +static void +ale_rxvlan(struct ale_softc *sc) +{ + struct ifnet *ifp; + uint32_t reg; + + ifp = &sc->arpcom.ac_if; + reg = CSR_READ_4(sc, ALE_MAC_CFG); + reg &= ~MAC_CFG_VLAN_TAG_STRIP; + if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) + reg |= MAC_CFG_VLAN_TAG_STRIP; + CSR_WRITE_4(sc, ALE_MAC_CFG, reg); +} + +static void +ale_rxfilter(struct ale_softc *sc) +{ + struct ifnet *ifp; + struct ifmultiaddr *ifma; + uint32_t crc; + uint32_t mchash[2]; + uint32_t rxcfg; + + ifp = &sc->arpcom.ac_if; + + rxcfg = CSR_READ_4(sc, ALE_MAC_CFG); + rxcfg &= ~(MAC_CFG_ALLMULTI | MAC_CFG_BCAST | MAC_CFG_PROMISC); + if ((ifp->if_flags & IFF_BROADCAST) != 0) + rxcfg |= MAC_CFG_BCAST; + if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { + if ((ifp->if_flags & IFF_PROMISC) != 0) + rxcfg |= MAC_CFG_PROMISC; + if ((ifp->if_flags & IFF_ALLMULTI) != 0) + rxcfg |= MAC_CFG_ALLMULTI; + CSR_WRITE_4(sc, ALE_MAR0, 0xFFFFFFFF); + CSR_WRITE_4(sc, ALE_MAR1, 0xFFFFFFFF); + CSR_WRITE_4(sc, ALE_MAC_CFG, rxcfg); + return; + } + + /* Program new filter. */ + bzero(mchash, sizeof(mchash)); + + LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) + ifma->ifma_addr), ETHER_ADDR_LEN); + mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); + } + + CSR_WRITE_4(sc, ALE_MAR0, mchash[0]); + CSR_WRITE_4(sc, ALE_MAR1, mchash[1]); + CSR_WRITE_4(sc, ALE_MAC_CFG, rxcfg); +} + +static int +sysctl_hw_ale_int_mod(SYSCTL_HANDLER_ARGS) +{ + return (sysctl_int_range(oidp, arg1, arg2, req, + ALE_IM_TIMER_MIN, ALE_IM_TIMER_MAX)); +} + +static void +ale_dmamap_buf_cb(void *xctx, bus_dma_segment_t *segs, int nsegs, + bus_size_t mapsz __unused, int error) +{ + struct ale_dmamap_ctx *ctx = xctx; + int i; + + if (error) + return; + + if (nsegs > ctx->nsegs) { + ctx->nsegs = 0; + return; + } + + ctx->nsegs = nsegs; + for (i = 0; i < nsegs; ++i) + ctx->segs[i] = segs[i]; +} diff --git a/sys/dev/netif/ale/if_alereg.h b/sys/dev/netif/ale/if_alereg.h new file mode 100644 index 0000000000..0305b435b5 --- /dev/null +++ b/sys/dev/netif/ale/if_alereg.h @@ -0,0 +1,765 @@ +/*- + * Copyright (c) 2008, Pyun YongHyeon + * 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 unmodified, 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 + * DAMATES (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 DAMATE. + * + * $FreeBSD: src/sys/dev/ale/if_alereg.h,v 1.1 2008/11/12 09:52:06 yongari Exp $ + */ + +#ifndef _IF_ALEREG_H +#define _IF_ALEREG_H + +#define ALE_PCIR_BAR PCIR_BAR(0) + +/* + * Atheros Communucations, Inc. PCI vendor ID + */ +#define VENDORID_ATHEROS 0x1969 + +/* + * Atheros AR8121/AR8113/AR8114 device ID + */ +#define DEVICEID_ATHEROS_AR81XX 0x1026 + +#define ALE_SPI_CTRL 0x200 +#define SPI_VPD_ENB 0x00002000 + +#define ALE_SPI_ADDR 0x204 /* 16bits */ + +#define ALE_SPI_DATA 0x208 + +#define ALE_SPI_CONFIG 0x20C + +#define ALE_SPI_OP_PROGRAM 0x210 /* 8bits */ + +#define ALE_SPI_OP_SC_ERASE 0x211 /* 8bits */ + +#define ALE_SPI_OP_CHIP_ERASE 0x212 /* 8bits */ + +#define ALE_SPI_OP_RDID 0x213 /* 8bits */ + +#define ALE_SPI_OP_WREN 0x214 /* 8bits */ + +#define ALE_SPI_OP_RDSR 0x215 /* 8bits */ + +#define ALE_SPI_OP_WRSR 0x216 /* 8bits */ + +#define ALE_SPI_OP_READ 0x217 /* 8bits */ + +#define ALE_TWSI_CTRL 0x218 +#define TWSI_CTRL_SW_LD_START 0x00000800 +#define TWSI_CTRL_HW_LD_START 0x00001000 +#define TWSI_CTRL_LD_EXIST 0x00400000 + +#define ALE_DEV_MISC_CTRL 0x21C + +#define ALE_PCIE_PHYMISC 0x1000 +#define PCIE_PHYMISC_FORCE_RCV_DET 0x00000004 + +#define ALE_MASTER_CFG 0x1400 +#define MASTER_RESET 0x00000001 +#define MASTER_MTIMER_ENB 0x00000002 +#define MASTER_IM_TX_TIMER_ENB 0x00000004 +#define MASTER_MANUAL_INT_ENB 0x00000008 +#define MASTER_IM_RX_TIMER_ENB 0x00000020 +#define MASTER_INT_RDCLR 0x00000040 +#define MASTER_LED_MODE 0x00000200 +#define MASTER_CHIP_REV_MASK 0x00FF0000 +#define MASTER_CHIP_ID_MASK 0xFF000000 +#define MASTER_CHIP_REV_SHIFT 16 +#define MASTER_CHIP_ID_SHIFT 24 + +/* Number of ticks per usec for AR81xx. */ +#define ALE_TICK_USECS 2 +#define ALE_USECS(x) ((x) / ALE_TICK_USECS) + +#define ALE_MANUAL_TIMER 0x1404 + +#define ALE_IM_TIMER 0x1408 +#define IM_TIMER_TX_MASK 0x0000FFFF +#define IM_TIMER_RX_MASK 0xFFFF0000 +#define IM_TIMER_TX_SHIFT 0 +#define IM_TIMER_RX_SHIFT 16 +#define ALE_IM_TIMER_MIN 0 +#define ALE_IM_TIMER_MAX 130000 /* 130ms */ +#define ALE_IM_RX_TIMER_DEFAULT 30 +#define ALE_IM_TX_TIMER_DEFAULT 1000 + +#define ALE_GPHY_CTRL 0x140C /* 16bits */ +#define GPHY_CTRL_EXT_RESET 0x0001 +#define GPHY_CTRL_PIPE_MOD 0x0002 +#define GPHY_CTRL_BERT_START 0x0010 +#define GPHY_CTRL_GALE_25M_ENB 0x0020 +#define GPHY_CTRL_LPW_EXIT 0x0040 +#define GPHY_CTRL_PHY_IDDQ 0x0080 +#define GPHY_CTRL_PHY_IDDQ_DIS 0x0100 +#define GPHY_CTRL_PCLK_SEL_DIS 0x0200 +#define GPHY_CTRL_HIB_EN 0x0400 +#define GPHY_CTRL_HIB_PULSE 0x0800 +#define GPHY_CTRL_SEL_ANA_RESET 0x1000 +#define GPHY_CTRL_PHY_PLL_ON 0x2000 +#define GPHY_CTRL_PWDOWN_HW 0x4000 + +#define ALE_INTR_CLR_TIMER 0x140E /* 16bits */ + +#define ALE_IDLE_STATUS 0x1410 +#define IDLE_STATUS_RXMAC 0x00000001 +#define IDLE_STATUS_TXMAC 0x00000002 +#define IDLE_STATUS_RXQ 0x00000004 +#define IDLE_STATUS_TXQ 0x00000008 +#define IDLE_STATUS_DMARD 0x00000010 +#define IDLE_STATUS_DMAWR 0x00000020 +#define IDLE_STATUS_SMB 0x00000040 +#define IDLE_STATUS_CMB 0x00000080 + +#define ALE_MDIO 0x1414 +#define MDIO_DATA_MASK 0x0000FFFF +#define MDIO_REG_ADDR_MASK 0x001F0000 +#define MDIO_OP_READ 0x00200000 +#define MDIO_OP_WRITE 0x00000000 +#define MDIO_SUP_PREAMBLE 0x00400000 +#define MDIO_OP_EXECUTE 0x00800000 +#define MDIO_CLK_25_4 0x00000000 +#define MDIO_CLK_25_6 0x02000000 +#define MDIO_CLK_25_8 0x03000000 +#define MDIO_CLK_25_10 0x04000000 +#define MDIO_CLK_25_14 0x05000000 +#define MDIO_CLK_25_20 0x06000000 +#define MDIO_CLK_25_28 0x07000000 +#define MDIO_OP_BUSY 0x08000000 +#define MDIO_DATA_SHIFT 0 +#define MDIO_REG_ADDR_SHIFT 16 + +#define MDIO_REG_ADDR(x) \ + (((x) << MDIO_REG_ADDR_SHIFT) & MDIO_REG_ADDR_MASK) +/* Default PHY address. */ +#define ALE_PHY_ADDR 0 + +#define ALE_PHY_STATUS 0x1418 +#define PHY_STATUS_100M 0x00020000 + +/* Packet memory BIST. */ +#define ALE_BIST0 0x141C +#define BIST0_ENB 0x00000001 +#define BIST0_SRAM_FAIL 0x00000002 +#define BIST0_FUSE_FLAG 0x00000004 + +/* PCIe retry buffer BIST. */ +#define ALE_BIST1 0x1420 +#define BIST1_ENB 0x00000001 +#define BIST1_SRAM_FAIL 0x00000002 +#define BIST1_FUSE_FLAG 0x00000004 + +#define ALE_SERDES_LOCK 0x1424 +#define SERDES_LOCK_DET 0x00000001 +#define SERDES_LOCK_DET_ENB 0x00000002 + +#define ALE_MAC_CFG 0x1480 +#define MAC_CFG_TX_ENB 0x00000001 +#define MAC_CFG_RX_ENB 0x00000002 +#define MAC_CFG_TX_FC 0x00000004 +#define MAC_CFG_RX_FC 0x00000008 +#define MAC_CFG_LOOP 0x00000010 +#define MAC_CFG_FULL_DUPLEX 0x00000020 +#define MAC_CFG_TX_CRC_ENB 0x00000040 +#define MAC_CFG_TX_AUTO_PAD 0x00000080 +#define MAC_CFG_TX_LENCHK 0x00000100 +#define MAC_CFG_RX_JUMBO_ENB 0x00000200 +#define MAC_CFG_PREAMBLE_MASK 0x00003C00 +#define MAC_CFG_VLAN_TAG_STRIP 0x00004000 +#define MAC_CFG_PROMISC 0x00008000 +#define MAC_CFG_TX_PAUSE 0x00010000 +#define MAC_CFG_SCNT 0x00020000 +#define MAC_CFG_SYNC_RST_TX 0x00040000 +#define MAC_CFG_SPEED_MASK 0x00300000 +#define MAC_CFG_SPEED_10_100 0x00100000 +#define MAC_CFG_SPEED_1000 0x00200000 +#define MAC_CFG_DBG_TX_BACKOFF 0x00400000 +#define MAC_CFG_TX_JUMBO_ENB 0x00800000 +#define MAC_CFG_RXCSUM_ENB 0x01000000 +#define MAC_CFG_ALLMULTI 0x02000000 +#define MAC_CFG_BCAST 0x04000000 +#define MAC_CFG_DBG 0x08000000 +#define MAC_CFG_PREAMBLE_SHIFT 10 +#define MAC_CFG_PREAMBLE_DEFAULT 7 + +#define ALE_IPG_IFG_CFG 0x1484 +#define IPG_IFG_IPGT_MASK 0x0000007F +#define IPG_IFG_MIFG_MASK 0x0000FF00 +#define IPG_IFG_IPG1_MASK 0x007F0000 +#define IPG_IFG_IPG2_MASK 0x7F000000 +#define IPG_IFG_IPGT_SHIFT 0 +#define IPG_IFG_IPGT_DEFAULT 0x60 +#define IPG_IFG_MIFG_SHIFT 8 +#define IPG_IFG_MIFG_DEFAULT 0x50 +#define IPG_IFG_IPG1_SHIFT 16 +#define IPG_IFG_IPG1_DEFAULT 0x40 +#define IPG_IFG_IPG2_SHIFT 24 +#define IPG_IFG_IPG2_DEFAULT 0x60 + +/* Station address. */ +#define ALE_PAR0 0x1488 +#define ALE_PAR1 0x148C + +/* 64bit multicast hash register. */ +#define ALE_MAR0 0x1490 +#define ALE_MAR1 0x1494 + +/* half-duplex parameter configuration. */ +#define ALE_HDPX_CFG 0x1498 +#define HDPX_CFG_LCOL_MASK 0x000003FF +#define HDPX_CFG_RETRY_MASK 0x0000F000 +#define HDPX_CFG_EXC_DEF_EN 0x00010000 +#define HDPX_CFG_NO_BACK_C 0x00020000 +#define HDPX_CFG_NO_BACK_P 0x00040000 +#define HDPX_CFG_ABEBE 0x00080000 +#define HDPX_CFG_ABEBT_MASK 0x00F00000 +#define HDPX_CFG_JAMIPG_MASK 0x0F000000 +#define HDPX_CFG_LCOL_SHIFT 0 +#define HDPX_CFG_LCOL_DEFAULT 0x37 +#define HDPX_CFG_RETRY_SHIFT 12 +#define HDPX_CFG_RETRY_DEFAULT 0x0F +#define HDPX_CFG_ABEBT_SHIFT 20 +#define HDPX_CFG_ABEBT_DEFAULT 0x0A +#define HDPX_CFG_JAMIPG_SHIFT 24 +#define HDPX_CFG_JAMIPG_DEFAULT 0x07 + +#define ALE_FRAME_SIZE 0x149C + +#define ALE_WOL_CFG 0x14A0 +#define WOL_CFG_PATTERN 0x00000001 +#define WOL_CFG_PATTERN_ENB 0x00000002 +#define WOL_CFG_MAGIC 0x00000004 +#define WOL_CFG_MAGIC_ENB 0x00000008 +#define WOL_CFG_LINK_CHG 0x00000010 +#define WOL_CFG_LINK_CHG_ENB 0x00000020 +#define WOL_CFG_PATTERN_DET 0x00000100 +#define WOL_CFG_MAGIC_DET 0x00000200 +#define WOL_CFG_LINK_CHG_DET 0x00000400 +#define WOL_CFG_CLK_SWITCH_ENB 0x00008000 +#define WOL_CFG_PATTERN0 0x00010000 +#define WOL_CFG_PATTERN1 0x00020000 +#define WOL_CFG_PATTERN2 0x00040000 +#define WOL_CFG_PATTERN3 0x00080000 +#define WOL_CFG_PATTERN4 0x00100000 +#define WOL_CFG_PATTERN5 0x00200000 +#define WOL_CFG_PATTERN6 0x00400000 + +/* WOL pattern length. */ +#define ALE_PATTERN_CFG0 0x14A4 +#define PATTERN_CFG_0_LEN_MASK 0x0000007F +#define PATTERN_CFG_1_LEN_MASK 0x00007F00 +#define PATTERN_CFG_2_LEN_MASK 0x007F0000 +#define PATTERN_CFG_3_LEN_MASK 0x7F000000 + +#define ALE_PATTERN_CFG1 0x14A8 +#define PATTERN_CFG_4_LEN_MASK 0x0000007F +#define PATTERN_CFG_5_LEN_MASK 0x00007F00 +#define PATTERN_CFG_6_LEN_MASK 0x007F0000 + +/* RSS */ +#define ALE_RSS_KEY0 0x14B0 + +#define ALE_RSS_KEY1 0x14B4 + +#define ALE_RSS_KEY2 0x14B8 + +#define ALE_RSS_KEY3 0x14BC + +#define ALE_RSS_KEY4 0x14C0 + +#define ALE_RSS_KEY5 0x14C4 + +#define ALE_RSS_KEY6 0x14C8 + +#define ALE_RSS_KEY7 0x14CC + +#define ALE_RSS_KEY8 0x14D0 + +#define ALE_RSS_KEY9 0x14D4 + +#define ALE_RSS_IDT_TABLE4 0x14E0 + +#define ALE_RSS_IDT_TABLE5 0x14E4 + +#define ALE_RSS_IDT_TABLE6 0x14E8 + +#define ALE_RSS_IDT_TABLE7 0x14EC + +#define ALE_SRAM_RD_ADDR 0x1500 + +#define ALE_SRAM_RD_LEN 0x1504 + +#define ALE_SRAM_RRD_ADDR 0x1508 + +#define ALE_SRAM_RRD_LEN 0x150C + +#define ALE_SRAM_TPD_ADDR 0x1510 + +#define ALE_SRAM_TPD_LEN 0x1514 + +#define ALE_SRAM_TRD_ADDR 0x1518 + +#define ALE_SRAM_TRD_LEN 0x151C + +#define ALE_SRAM_RX_FIFO_ADDR 0x1520 + +#define ALE_SRAM_RX_FIFO_LEN 0x1524 + +#define ALE_SRAM_TX_FIFO_ADDR 0x1528 + +#define ALE_SRAM_TX_FIFO_LEN 0x152C + +#define ALE_SRAM_TCPH_ADDR 0x1530 +#define SRAM_TCPH_ADDR_MASK 0x00000FFF +#define SRAM_PATH_ADDR_MASK 0x0FFF0000 +#define SRAM_TCPH_ADDR_SHIFT 0 +#define SRAM_PATH_ADDR_SHIFT 16 + +#define ALE_DMA_BLOCK 0x1534 +#define DMA_BLOCK_LOAD 0x00000001 + +#define ALE_RXF3_ADDR_HI 0x153C + +#define ALE_TPD_ADDR_HI 0x1540 + +#define ALE_RXF0_PAGE0_ADDR_LO 0x1544 + +#define ALE_RXF0_PAGE1_ADDR_LO 0x1548 + +#define ALE_TPD_ADDR_LO 0x154C + +#define ALE_RXF1_ADDR_HI 0x1550 + +#define ALE_RXF2_ADDR_HI 0x1554 + +#define ALE_RXF_PAGE_SIZE 0x1558 + +#define ALE_TPD_CNT 0x155C +#define TPD_CNT_MASK 0x00003FF +#define TPD_CNT_SHIFT 0 + +#define ALE_RSS_IDT_TABLE0 0x1560 + +#define ALE_RSS_IDT_TABLE1 0x1564 + +#define ALE_RSS_IDT_TABLE2 0x1568 + +#define ALE_RSS_IDT_TABLE3 0x156C + +#define ALE_RSS_HASH_VALUE 0x1570 + +#define ALE_RSS_HASH_FLAG 0x1574 + +#define ALE_RSS_CPU 0x157C + +#define ALE_TXQ_CFG 0x1580 +#define TXQ_CFG_TPD_BURST_MASK 0x0000000F +#define TXQ_CFG_ENB 0x00000020 +#define TXQ_CFG_ENHANCED_MODE 0x00000040 +#define TXQ_CFG_TX_FIFO_BURST_MASK 0xFFFF0000 +#define TXQ_CFG_TPD_BURST_SHIFT 0 +#define TXQ_CFG_TPD_BURST_DEFAULT 4 +#define TXQ_CFG_TX_FIFO_BURST_SHIFT 16 +#define TXQ_CFG_TX_FIFO_BURST_DEFAULT 256 + +#define ALE_TX_JUMBO_THRESH 0x1584 +#define TX_JUMBO_THRESH_MASK 0x000007FF +#define TX_JUMBO_THRESH_SHIFT 0 +#define TX_JUMBO_THRESH_UNIT 8 +#define TX_JUMBO_THRESH_UNIT_SHIFT 3 + +#define ALE_RXQ_CFG 0x15A0 +#define RXQ_CFG_ALIGN_32 0x00000000 +#define RXQ_CFG_ALIGN_64 0x00000001 +#define RXQ_CFG_ALIGN_128 0x00000002 +#define RXQ_CFG_ALIGN_256 0x00000003 +#define RXQ_CFG_QUEUE1_ENB 0x00000010 +#define RXQ_CFG_QUEUE2_ENB 0x00000020 +#define RXQ_CFG_QUEUE3_ENB 0x00000040 +#define RXQ_CFG_IPV6_CSUM_VERIFY 0x00000080 +#define RXQ_CFG_RSS_HASH_TBL_LEN_MASK 0x0000FF00 +#define RXQ_CFG_RSS_HASH_IPV4 0x00010000 +#define RXQ_CFG_RSS_HASH_IPV4_TCP 0x00020000 +#define RXQ_CFG_RSS_HASH_IPV6 0x00040000 +#define RXQ_CFG_RSS_HASH_IPV6_TCP 0x00080000 +#define RXQ_CFG_RSS_MODE_DIS 0x00000000 +#define RXQ_CFG_RSS_MODE_SQSINT 0x04000000 +#define RXQ_CFG_RSS_MODE_MQUESINT 0x08000000 +#define RXQ_CFG_RSS_MODE_MQUEMINT 0x0C000000 +#define RXQ_CFG_NIP_QUEUE_SEL_TBL 0x10000000 +#define RXQ_CFG_RSS_HASH_ENB 0x20000000 +#define RXQ_CFG_CUT_THROUGH_ENB 0x40000000 +#define RXQ_CFG_ENB 0x80000000 +#define RXQ_CFG_RSS_HASH_TBL_LEN_SHIFT 8 + +#define ALE_RX_JUMBO_THRESH 0x15A4 /* 16bits */ +#define RX_JUMBO_THRESH_MASK 0x07FF +#define RX_JUMBO_LKAH_MASK 0x7800 +#define RX_JUMBO_THRESH_MASK_SHIFT 0 +#define RX_JUMBO_THRESH_UNIT 8 +#define RX_JUMBO_THRESH_UNIT_SHIFT 3 +#define RX_JUMBO_LKAH_SHIFT 11 +#define RX_JUMBO_LKAH_DEFAULT 1 + +#define ALE_RX_FIFO_PAUSE_THRESH 0x15A8 +#define RX_FIFO_PAUSE_THRESH_LO_MASK 0x00000FFF +#define RX_FIFO_PAUSE_THRESH_HI_MASK 0x0FFF0000 +#define RX_FIFO_PAUSE_THRESH_LO_SHIFT 0 +#define RX_FIFO_PAUSE_THRESH_HI_SHIFT 16 + +#define ALE_CMB_RXF1 0x15B4 + +#define ALE_CMB_RXF2 0x15B8 + +#define ALE_CMB_RXF3 0x15BC + +#define ALE_DMA_CFG 0x15C0 +#define DMA_CFG_IN_ORDER 0x00000001 +#define DMA_CFG_ENH_ORDER 0x00000002 +#define DMA_CFG_OUT_ORDER 0x00000004 +#define DMA_CFG_RCB_64 0x00000000 +#define DMA_CFG_RCB_128 0x00000008 +#define DMA_CFG_RD_BURST_128 0x00000000 +#define DMA_CFG_RD_BURST_256 0x00000010 +#define DMA_CFG_RD_BURST_512 0x00000020 +#define DMA_CFG_RD_BURST_1024 0x00000030 +#define DMA_CFG_RD_BURST_2048 0x00000040 +#define DMA_CFG_RD_BURST_4096 0x00000050 +#define DMA_CFG_WR_BURST_128 0x00000000 +#define DMA_CFG_WR_BURST_256 0x00000080 +#define DMA_CFG_WR_BURST_512 0x00000100 +#define DMA_CFG_WR_BURST_1024 0x00000180 +#define DMA_CFG_WR_BURST_2048 0x00000200 +#define DMA_CFG_WR_BURST_4096 0x00000280 +#define DMA_CFG_RD_REQ_PRI 0x00000400 +#define DMA_CFG_RD_DELAY_CNT_MASK 0x0000F800 +#define DMA_CFG_WR_DELAY_CNT_MASK 0x000F0000 +#define DMA_CFG_TXCMB_ENB 0x00100000 +#define DMA_CFG_RXCMB_ENB 0x00200000 +#define DMA_CFG_RD_BURST_MASK 0x07 +#define DMA_CFG_RD_BURST_SHIFT 4 +#define DMA_CFG_WR_BURST_MASK 0x07 +#define DMA_CFG_WR_BURST_SHIFT 7 +#define DMA_CFG_RD_DELAY_CNT_SHIFT 11 +#define DMA_CFG_WR_DELAY_CNT_SHIFT 16 +#define DMA_CFG_RD_DELAY_CNT_DEFAULT 15 +#define DMA_CFG_WR_DELAY_CNT_DEFAULT 4 + +#define ALE_SMB_STAT_TIMER 0x15C4 + +#define ALE_INT_TRIG_THRESH 0x15C8 +#define INT_TRIG_TX_THRESH_MASK 0x0000FFFF +#define INT_TRIG_RX_THRESH_MASK 0xFFFF0000 +#define INT_TRIG_TX_THRESH_SHIFT 0 +#define INT_TRIG_RX_THRESH_SHIFT 16 + +#define ALE_INT_TRIG_TIMER 0x15CC +#define INT_TRIG_TX_TIMER_MASK 0x0000FFFF +#define INT_TRIG_RX_TIMER_MASK 0x0000FFFF +#define INT_TRIG_TX_TIMER_SHIFT 0 +#define INT_TRIG_RX_TIMER_SHIFT 16 + +#define ALE_RXF1_PAGE0_ADDR_LO 0x15D0 + +#define ALE_RXF1_PAGE1_ADDR_LO 0x15D4 + +#define ALE_RXF2_PAGE0_ADDR_LO 0x15D8 + +#define ALE_RXF2_PAGE1_ADDR_LO 0x15DC + +#define ALE_RXF3_PAGE0_ADDR_LO 0x15E0 + +#define ALE_RXF3_PAGE1_ADDR_LO 0x15E4 + +#define ALE_MBOX_TPD_PROD_IDX 0x15F0 + +#define ALE_RXF0_PAGE0 0x15F4 + +#define ALE_RXF0_PAGE1 0x15F5 + +#define ALE_RXF1_PAGE0 0x15F6 + +#define ALE_RXF1_PAGE1 0x15F7 + +#define ALE_RXF2_PAGE0 0x15F8 + +#define ALE_RXF2_PAGE1 0x15F9 + +#define ALE_RXF3_PAGE0 0x15FA + +#define ALE_RXF3_PAGE1 0x15FB + +#define RXF_VALID 0x01 + +#define ALE_INTR_STATUS 0x1600 +#define INTR_SMB 0x00000001 +#define INTR_TIMER 0x00000002 +#define INTR_MANUAL_TIMER 0x00000004 +#define INTR_RX_FIFO_OFLOW 0x00000008 +#define INTR_RXF0_OFLOW 0x00000010 +#define INTR_RXF1_OFLOW 0x00000020 +#define INTR_RXF2_OFLOW 0x00000040 +#define INTR_RXF3_OFLOW 0x00000080 +#define INTR_TX_FIFO_UNDERRUN 0x00000100 +#define INTR_RX0_PAGE_FULL 0x00000200 +#define INTR_DMA_RD_TO_RST 0x00000400 +#define INTR_DMA_WR_TO_RST 0x00000800 +#define INTR_GPHY 0x00001000 +#define INTR_TX_CREDIT 0x00002000 +#define INTR_GPHY_LOW_PW 0x00004000 +#define INTR_RX_PKT 0x00010000 +#define INTR_TX_PKT 0x00020000 +#define INTR_TX_DMA 0x00040000 +#define INTR_RX_PKT1 0x00080000 +#define INTR_RX_PKT2 0x00100000 +#define INTR_RX_PKT3 0x00200000 +#define INTR_MAC_RX 0x00400000 +#define INTR_MAC_TX 0x00800000 +#define INTR_UNDERRUN 0x01000000 +#define INTR_FRAME_ERROR 0x02000000 +#define INTR_FRAME_OK 0x04000000 +#define INTR_CSUM_ERROR 0x08000000 +#define INTR_PHY_LINK_DOWN 0x10000000 +#define INTR_DIS_INT 0x80000000 + +/* Interrupt Mask Register */ +#define ALE_INTR_MASK 0x1604 + +#define ALE_INTRS \ + (INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST | \ + INTR_RX_PKT | INTR_TX_PKT | INTR_RX_FIFO_OFLOW | \ + INTR_TX_FIFO_UNDERRUN) + +/* + * AR81xx requires register access to get MAC statistics + * and the format of statistics seems to be the same of L1 . + */ +#define ALE_RX_MIB_BASE 0x1700 + +#define ALE_TX_MIB_BASE 0x1760 + +/* Statistics counters collected by the MAC. */ +struct smb { + /* Rx stats. */ + uint32_t rx_frames; + uint32_t rx_bcast_frames; + uint32_t rx_mcast_frames; + uint32_t rx_pause_frames; + uint32_t rx_control_frames; + uint32_t rx_crcerrs; + uint32_t rx_lenerrs; + uint32_t rx_bytes; + uint32_t rx_runts; + uint32_t rx_fragments; + uint32_t rx_pkts_64; + uint32_t rx_pkts_65_127; + uint32_t rx_pkts_128_255; + uint32_t rx_pkts_256_511; + uint32_t rx_pkts_512_1023; + uint32_t rx_pkts_1024_1518; + uint32_t rx_pkts_1519_max; + uint32_t rx_pkts_truncated; + uint32_t rx_fifo_oflows; + uint32_t rx_rrs_errs; + uint32_t rx_alignerrs; + uint32_t rx_bcast_bytes; + uint32_t rx_mcast_bytes; + uint32_t rx_pkts_filtered; + /* Tx stats. */ + uint32_t tx_frames; + uint32_t tx_bcast_frames; + uint32_t tx_mcast_frames; + uint32_t tx_pause_frames; + uint32_t tx_excess_defer; + uint32_t tx_control_frames; + uint32_t tx_deferred; + uint32_t tx_bytes; + uint32_t tx_pkts_64; + uint32_t tx_pkts_65_127; + uint32_t tx_pkts_128_255; + uint32_t tx_pkts_256_511; + uint32_t tx_pkts_512_1023; + uint32_t tx_pkts_1024_1518; + uint32_t tx_pkts_1519_max; + uint32_t tx_single_colls; + uint32_t tx_multi_colls; + uint32_t tx_late_colls; + uint32_t tx_excess_colls; + uint32_t tx_abort; + uint32_t tx_underrun; + uint32_t tx_desc_underrun; + uint32_t tx_lenerrs; + uint32_t tx_pkts_truncated; + uint32_t tx_bcast_bytes; + uint32_t tx_mcast_bytes; +} __packed; + +#define ALE_HOST_RXF0_PAGEOFF 0x1800 + +#define ALE_TPD_CONS_IDX 0x1804 + +#define ALE_HOST_RXF1_PAGEOFF 0x1808 + +#define ALE_HOST_RXF2_PAGEOFF 0x180C + +#define ALE_HOST_RXF3_PAGEOFF 0x1810 + +#define ALE_RXF0_CMB0_ADDR_LO 0x1820 + +#define ALE_RXF0_CMB1_ADDR_LO 0x1824 + +#define ALE_RXF1_CMB0_ADDR_LO 0x1828 + +#define ALE_RXF1_CMB1_ADDR_LO 0x182C + +#define ALE_RXF2_CMB0_ADDR_LO 0x1830 + +#define ALE_RXF2_CMB1_ADDR_LO 0x1834 + +#define ALE_RXF3_CMB0_ADDR_LO 0x1838 + +#define ALE_RXF3_CMB1_ADDR_LO 0x183C + +#define ALE_TX_CMB_ADDR_LO 0x1840 + +#define ALE_SMB_ADDR_LO 0x1844 + +/* + * RRS(receive return status) structure. + * + * Note: + * Atheros AR81xx does not support descriptor based DMA on Rx + * instead it just prepends a Rx status structure prior to a + * received frame which also resides on the same Rx buffer. + * This means driver should copy an entire frame from the + * buffer to new mbuf chain which in turn greatly increases CPU + * cycles and effectively nullify the advantage of DMA + * operation of controller. So you should have fast CPU to cope + * with the copy operation. Implementing flow-controls may help + * a lot to minimize Rx FIFO overflows but it's not available + * yet on FreeBSD and hardware doesn't seem to support + * fine-grained Tx/Rx flow controls. + */ +struct rx_rs { + uint32_t seqno; +#define ALE_RD_SEQNO_MASK 0x0000FFFF +#define ALE_RD_HASH_MASK 0xFFFF0000 +#define ALE_RD_SEQNO_SHIFT 0 +#define ALE_RD_HASH_SHIFT 16 +#define ALE_RX_SEQNO(x) \ + (((x) & ALE_RD_SEQNO_MASK) >> ALE_RD_SEQNO_SHIFT) + uint32_t length; +#define ALE_RD_CSUM_MASK 0x0000FFFF +#define ALE_RD_LEN_MASK 0x3FFF0000 +#define ALE_RD_CPU_MASK 0xC0000000 +#define ALE_RD_CSUM_SHIFT 0 +#define ALE_RD_LEN_SHIFT 16 +#define ALE_RD_CPU_SHIFT 30 +#define ALE_RX_CSUM(x) \ + (((x) & ALE_RD_CSUM_MASK) >> ALE_RD_CSUM_SHIFT) +#define ALE_RX_BYTES(x) \ + (((x) & ALE_RD_LEN_MASK) >> ALE_RD_LEN_SHIFT) +#define ALE_RX_CPU(x) \ + (((x) & ALE_RD_CPU_MASK) >> ALE_RD_CPU_SHIFT) + uint32_t flags; +#define ALE_RD_RSS_IPV4 0x00000001 +#define ALE_RD_RSS_IPV4_TCP 0x00000002 +#define ALE_RD_RSS_IPV6 0x00000004 +#define ALE_RD_RSS_IPV6_TCP 0x00000008 +#define ALE_RD_IPV6 0x00000010 +#define ALE_RD_IPV4_FRAG 0x00000020 +#define ALE_RD_IPV4_DF 0x00000040 +#define ALE_RD_802_3 0x00000080 +#define ALE_RD_VLAN 0x00000100 +#define ALE_RD_ERROR 0x00000200 +#define ALE_RD_IPV4 0x00000400 +#define ALE_RD_UDP 0x00000800 +#define ALE_RD_TCP 0x00001000 +#define ALE_RD_BCAST 0x00002000 +#define ALE_RD_MCAST 0x00004000 +#define ALE_RD_PAUSE 0x00008000 +#define ALE_RD_CRC 0x00010000 +#define ALE_RD_CODE 0x00020000 +#define ALE_RD_DRIBBLE 0x00040000 +#define ALE_RD_RUNT 0x00080000 +#define ALE_RD_OFLOW 0x00100000 +#define ALE_RD_TRUNC 0x00200000 +#define ALE_RD_IPCSUM_NOK 0x00400000 +#define ALE_RD_TCP_UDPCSUM_NOK 0x00800000 +#define ALE_RD_LENGTH_NOK 0x01000000 +#define ALE_RD_DES_ADDR_FILTERED 0x02000000 + uint32_t vtags; +#define ALE_RD_HASH_HI_MASK 0x0000FFFF +#define ALE_RD_HASH_HI_SHIFT 0 +#define ALE_RD_VLAN_MASK 0xFFFF0000 +#define ALE_RD_VLAN_SHIFT 16 +#define ALE_RX_VLAN(x) \ + (((x) & ALE_RD_VLAN_MASK) >> ALE_RD_VLAN_SHIFT) +#define ALE_RX_VLAN_TAG(x) \ + (((x) >> 4) | (((x) & 7) << 13) | (((x) & 8) << 9)) +} __packed; + +/* Tx descriptor. */ +struct tx_desc { + uint64_t addr; + uint32_t len; +#define ALE_TD_VLAN_MASK 0xFFFF0000 +#define ALE_TD_PKT_INT 0x00008000 +#define ALE_TD_DMA_INT 0x00004000 +#define ALE_TD_BUFLEN_MASK 0x00003FFF +#define ALE_TD_VLAN_SHIFT 16 +#define ALE_TX_VLAN_TAG(x) \ + (((x) << 4) | ((x) >> 13) | (((x) >> 9) & 8)) +#define ALE_TD_BUFLEN_SHIFT 0 +#define ALE_TX_BYTES(x) \ + (((x) << ALE_TD_BUFLEN_SHIFT) & ALE_TD_BUFLEN_MASK) + uint32_t flags; +#define ALE_TD_MSS 0xFFF80000 +#define ALE_TD_TSO_HDR 0x00040000 +#define ALE_TD_TCPHDR_LEN 0x0003C000 +#define ALE_TD_IPHDR_LEN 0x00003C00 +#define ALE_TD_IPV6HDR_LEN2 0x00003C00 +#define ALE_TD_LLC_SNAP 0x00000200 +#define ALE_TD_VLAN_TAGGED 0x00000100 +#define ALE_TD_UDPCSUM 0x00000080 +#define ALE_TD_TCPCSUM 0x00000040 +#define ALE_TD_IPCSUM 0x00000020 +#define ALE_TD_IPV6HDR_LEN1 0x000000E0 +#define ALE_TD_TSO 0x00000010 +#define ALE_TD_CXSUM 0x00000008 +#define ALE_TD_INSERT_VLAN_TAG 0x00000004 +#define ALE_TD_IPV6 0x00000002 +#define ALE_TD_EOP 0x00000001 + +#define ALE_TD_CSUM_PLOADOFFSET 0x00FF0000 +#define ALE_TD_CSUM_XSUMOFFSET 0xFF000000 +#define ALE_TD_CSUM_XSUMOFFSET_SHIFT 24 +#define ALE_TD_CSUM_PLOADOFFSET_SHIFT 16 +#define ALE_TD_MSS_SHIFT 19 +#define ALE_TD_TCPHDR_LEN_SHIFT 14 +#define ALE_TD_IPHDR_LEN_SHIFT 10 +} __packed; + +#endif /* _IF_ALEREG_H */ diff --git a/sys/dev/netif/ale/if_alevar.h b/sys/dev/netif/ale/if_alevar.h new file mode 100644 index 0000000000..5e5c2ce75f --- /dev/null +++ b/sys/dev/netif/ale/if_alevar.h @@ -0,0 +1,248 @@ +/*- + * Copyright (c) 2008, Pyun YongHyeon + * 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 unmodified, 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: src/sys/dev/ale/if_alevar.h,v 1.1 2008/11/12 09:52:06 yongari Exp $ + */ + +#ifndef _IF_ALEVAR_H +#define _IF_ALEVAR_H + +#define ALE_TX_RING_CNT 256 /* Should be multiple of 4. */ +#define ALE_TX_RING_CNT_MIN 32 +#define ALE_TX_RING_CNT_MAX 1020 +#define ALE_TX_RING_ALIGN 8 +#define ALE_RX_PAGE_ALIGN 32 +#define ALE_RX_PAGES 2 +#define ALE_CMB_ALIGN 32 + +#define ALE_TSO_MAXSEGSIZE 4096 +#define ALE_TSO_MAXSIZE (65535 + sizeof(struct ether_vlan_header)) +#define ALE_MAXTXSEGS 32 + +#define ALE_ADDR_LO(x) ((uint64_t) (x) & 0xFFFFFFFF) +#define ALE_ADDR_HI(x) ((uint64_t) (x) >> 32) + +/* Water mark to kick reclaiming Tx buffers. */ +#define ALE_TX_DESC_HIWAT (ALE_TX_RING_CNT - ((ALE_TX_RING_CNT * 4) / 10)) + +#define ALE_MSI_MESSAGES 1 +#define ALE_MSIX_MESSAGES 1 + +/* + * TODO : Should get real jumbo MTU size. + * The hardware seems to have trouble in dealing with large + * frame length. If you encounter unstability issue, use + * lower MTU size. + */ +#define ALE_JUMBO_FRAMELEN 8132 +#define ALE_JUMBO_MTU \ + (ALE_JUMBO_FRAMELEN - sizeof(struct ether_vlan_header) - ETHER_CRC_LEN) +#define ALE_MAX_FRAMELEN (ETHER_MAX_LEN + EVL_ENCAPLEN) + +#define ALE_DESC_INC(x, y) ((x) = ((x) + 1) % (y)) + +struct ale_txdesc { + struct mbuf *tx_m; + bus_dmamap_t tx_dmamap; +}; + +struct ale_rx_page { + bus_dma_tag_t page_tag; + bus_dmamap_t page_map; + uint8_t *page_addr; + bus_addr_t page_paddr; + bus_dma_tag_t cmb_tag; + bus_dmamap_t cmb_map; + uint32_t *cmb_addr; + bus_addr_t cmb_paddr; + uint32_t cons; +}; + +struct ale_chain_data{ + bus_dma_tag_t ale_parent_tag; + bus_dma_tag_t ale_buffer_tag; + bus_dma_tag_t ale_tx_tag; + struct ale_txdesc ale_txdesc[ALE_TX_RING_CNT]; + bus_dma_tag_t ale_tx_ring_tag; + bus_dmamap_t ale_tx_ring_map; + bus_dma_tag_t ale_rx_mblock_tag[ALE_RX_PAGES]; + bus_dmamap_t ale_rx_mblock_map[ALE_RX_PAGES]; + struct tx_desc *ale_tx_ring; + bus_addr_t ale_tx_ring_paddr; + uint32_t *ale_tx_cmb; + bus_addr_t ale_tx_cmb_paddr; + bus_dma_tag_t ale_tx_cmb_tag; + bus_dmamap_t ale_tx_cmb_map; + + uint32_t ale_tx_prod; + uint32_t ale_tx_cons; + int ale_tx_cnt; + struct ale_rx_page ale_rx_page[ALE_RX_PAGES]; + int ale_rx_curp; + uint16_t ale_rx_seqno; +}; + +#define ALE_TX_RING_SZ \ + (sizeof(struct tx_desc) * ALE_TX_RING_CNT) +#define ALE_RX_PAGE_SZ_MIN (8 * 1024) +#define ALE_RX_PAGE_SZ_MAX (1024 * 1024) +#define ALE_RX_FRAMES_PAGE 128 +#define ALE_RX_PAGE_SZ \ + (roundup(ALE_MAX_FRAMELEN, ALE_RX_PAGE_ALIGN) * ALE_RX_FRAMES_PAGE) +#define ALE_TX_CMB_SZ (sizeof(uint32_t)) +#define ALE_RX_CMB_SZ (sizeof(uint32_t)) + +#define ALE_PROC_MIN (ALE_RX_FRAMES_PAGE / 4) +#define ALE_PROC_MAX \ + ((ALE_RX_PAGE_SZ * ALE_RX_PAGES) / ETHER_MAX_LEN) +#define ALE_PROC_DEFAULT (ALE_PROC_MAX / 4) + +struct ale_hw_stats { + /* Rx stats. */ + uint32_t rx_frames; + uint32_t rx_bcast_frames; + uint32_t rx_mcast_frames; + uint32_t rx_pause_frames; + uint32_t rx_control_frames; + uint32_t rx_crcerrs; + uint32_t rx_lenerrs; + uint64_t rx_bytes; + uint32_t rx_runts; + uint32_t rx_fragments; + uint32_t rx_pkts_64; + uint32_t rx_pkts_65_127; + uint32_t rx_pkts_128_255; + uint32_t rx_pkts_256_511; + uint32_t rx_pkts_512_1023; + uint32_t rx_pkts_1024_1518; + uint32_t rx_pkts_1519_max; + uint32_t rx_pkts_truncated; + uint32_t rx_fifo_oflows; + uint32_t rx_rrs_errs; + uint32_t rx_alignerrs; + uint64_t rx_bcast_bytes; + uint64_t rx_mcast_bytes; + uint32_t rx_pkts_filtered; + /* Tx stats. */ + uint32_t tx_frames; + uint32_t tx_bcast_frames; + uint32_t tx_mcast_frames; + uint32_t tx_pause_frames; + uint32_t tx_excess_defer; + uint32_t tx_control_frames; + uint32_t tx_deferred; + uint64_t tx_bytes; + uint32_t tx_pkts_64; + uint32_t tx_pkts_65_127; + uint32_t tx_pkts_128_255; + uint32_t tx_pkts_256_511; + uint32_t tx_pkts_512_1023; + uint32_t tx_pkts_1024_1518; + uint32_t tx_pkts_1519_max; + uint32_t tx_single_colls; + uint32_t tx_multi_colls; + uint32_t tx_late_colls; + uint32_t tx_excess_colls; + uint32_t tx_abort; + uint32_t tx_underrun; + uint32_t tx_desc_underrun; + uint32_t tx_lenerrs; + uint32_t tx_pkts_truncated; + uint64_t tx_bcast_bytes; + uint64_t tx_mcast_bytes; + /* Misc. */ + uint32_t reset_brk_seq; +}; + +/* + * Software state per device. + */ +struct ale_softc { + struct arpcom arpcom; + device_t ale_dev; + + int ale_mem_rid; + struct resource *ale_mem_res; + bus_space_tag_t ale_mem_bt; + bus_space_handle_t ale_mem_bh; + + int ale_irq_rid; + struct resource *ale_irq_res; + void *ale_irq_handle; + + int ale_phyaddr; + device_t ale_miibus; + + int ale_rev; + int ale_chip_rev; + uint8_t ale_eaddr[ETHER_ADDR_LEN]; + uint32_t ale_dma_rd_burst; + uint32_t ale_dma_wr_burst; + int ale_flags; +#define ALE_FLAG_PCIE 0x0001 +#define ALE_FLAG_PCIX 0x0002 +#define ALE_FLAG_MSI 0x0004 +#define ALE_FLAG_MSIX 0x0008 +#define ALE_FLAG_PMCAP 0x0010 +#define ALE_FLAG_FASTETHER 0x0020 +#define ALE_FLAG_JUMBO 0x0040 +#define ALE_FLAG_RXCSUM_BUG 0x0080 +#define ALE_FLAG_TXCSUM_BUG 0x0100 +#define ALE_FLAG_TXCMB_BUG 0x0200 +#define ALE_FLAG_DETACH 0x4000 +#define ALE_FLAG_LINK 0x8000 + + struct callout ale_tick_ch; + struct ale_hw_stats ale_stats; + struct ale_chain_data ale_cdata; + int ale_if_flags; + int ale_int_rx_mod; + int ale_int_tx_mod; + int ale_max_frame_size; + int ale_pagesize; + + struct sysctl_ctx_list ale_sysctl_ctx; + struct sysctl_oid *ale_sysctl_tree; +}; + +/* Register access macros. */ +#define CSR_WRITE_4(_sc, reg, val) \ + bus_space_write_4((_sc)->ale_mem_bt, (_sc)->ale_mem_bh, (reg), (val)) +#define CSR_WRITE_2(_sc, reg, val) \ + bus_space_write_2((_sc)->ale_mem_bt, (_sc)->ale_mem_bh, (reg), (val)) +#define CSR_WRITE_1(_sc, reg, val) \ + bus_space_write_1((_sc)->ale_mem_bt, (_sc)->ale_mem_bh, (reg), (val)) +#define CSR_READ_2(_sc, reg) \ + bus_space_read_2((_sc)->ale_mem_bt, (_sc)->ale_mem_bh, (reg)) +#define CSR_READ_4(_sc, reg) \ + bus_space_read_4((_sc)->ale_mem_bt, (_sc)->ale_mem_bh, (reg)) + +#define ALE_TX_TIMEOUT 5 +#define ALE_RESET_TIMEOUT 100 +#define ALE_TIMEOUT 1000 +#define ALE_PHY_TIMEOUT 1000 + +#endif /* _IF_ATEVAR_H */ -- 2.41.0 From 9fb4241d779f7a928c8605d8ffe110dd5c3340c7 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Wed, 31 Dec 2008 23:44:46 +0100 Subject: [PATCH 02/16] Welcome 2009 to our copyrights. Happy new year, everybody! :) --- COPYRIGHT | 2 +- sys/sys/copyright.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index 321a2845ec..42a7c3829e 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -15,7 +15,7 @@ Copyright line. Multiple authors should simply append their names to the The software known as "DragonFly" or "DragonFly BSD" is distributed under the following terms: -Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 +Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009 The DragonFly Project. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/sys/sys/copyright.h b/sys/sys/copyright.h index 0d96d8cb81..7997045662 100644 --- a/sys/sys/copyright.h +++ b/sys/sys/copyright.h @@ -36,7 +36,7 @@ /* DragonFly */ #define COPYRIGHT_DragonFly \ - "Copyright (c) 2003-2008 The DragonFly Project.\n" + "Copyright (c) 2003-2009 The DragonFly Project.\n" /* Berkeley */ #define COPYRIGHT_UCB \ -- 2.41.0 From ac59e9bb07474aa0766e18879f8743169a589b69 Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Thu, 1 Jan 2009 12:32:57 +0000 Subject: [PATCH 03/16] Bring in priv(9) man page from FreeBSD (rev 1.7) --- share/man/man9/priv.9 | 122 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 share/man/man9/priv.9 diff --git a/share/man/man9/priv.9 b/share/man/man9/priv.9 new file mode 100644 index 0000000000..5247edee19 --- /dev/null +++ b/share/man/man9/priv.9 @@ -0,0 +1,122 @@ +.\"- +.\" Copyright (c) 2006 nCircle Network Security, Inc. +.\" All rights reserved. +.\" +.\" This software was developed by Robert N. M. Watson for the TrustedBSD +.\" Project under contract to nCircle Network Security, Inc. +.\" +.\" 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, NCIRCLE NETWORK SECURITY, +.\" INC., 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: src/share/man/man9/priv.9,v 1.7 2008/09/17 15:49:44 attilio Exp $ +.\" +.Dd August 30, 2006 +.Dt PRIV 9 +.Os +.Sh NAME +.Nm priv +.Nd kernel privilege checking API +.Sh SYNOPSIS +.In sys/priv.h +.Ft int +.Fn priv_check "struct thread *td" "int priv" +.Ft int +.Fn priv_check_cred "struct ucred *cred" "int priv" "int flags" +.Sh DESCRIPTION +The +.Nm +interfaces check to see if specific system privileges are granted to the +passed thread, +.Fa td , +or credential, +.Fa cred . +This interface replaces the now removed +.Xr suser 9 +privilege checking interface. +Privileges typically represent rights in one of two categories: the right to +manage a particular component of the system, or an exemption to a specific +policy or access control list. +The caller identifies the desired privilege via the +.Fa priv +argument. +The optional flags argument, +.Fa flags , +is currently unused. +.Ss Privilege Policies +Privileges are typically granted based on one of two base system policies: +the superuser policy, which grants privilege based on the effective (or +sometimes real) UID having a value of 0, and the +.Xr jail 2 +policy, which permits only certain privileges to be granted to processes in a +jail. +The set of available privileges may also be influenced by the TrustedBSD MAC +Framework, described in +.Xr mac 9 . +.Sh IMPLEMENTATION NOTES +When adding a new privilege check to a code path, first check the complete +list of current privileges in +.Pa sys/priv.h +to see if one already exists for the class of privilege required. +Only if there is not an exact match should a new privilege be added to the +privilege list. +As privilege numbers becomes encoded in the kernel module ABI, privilege +constants must not be changed as any kernel modules depending on privileges +will then need to be recompiled. +When adding a new privilege, be certain to also determine whether it should +be listed in +.Fn prison_priv_check , +which includes a complete list of privileges granted to the root user in +.Xr jail 2 . +.Pp +Certain catch-all privileges exist, such as +.Dv PRIV_DRIVER , +intended to be used by device drivers, rather than adding a new +driver-specific privilege. +.Sh RETURN VALUES +Typically, 0 will be returned for success, and +.Er EPERM +will be returned on failure. +Most consumers of +.Nm +will wish to directly return the error code from a failed privilege check to +user space; a small number will wish to translate it to another error code +appropriate to a specific context. +.Pp +When designing new APIs, it is preferable to return explicit errors from a +call if privilege is not granted rather than changing the semantics of the +call but returning success. +For example, the behavior exhibited by +.Xr stat 2 , +in which the generation field is optionally zero'd out when there is +insufficient privilege is highly undesirable, as it results in frequent +privilege checks, and the caller is unable to tell if an access control +failure occurred. +.Sh SEE ALSO +.Xr jail 2 , +.Xr mac 9 , +.Xr ucred 9 +.Sh AUTHORS +The +.Nm +API and implementation were created by +.An Robert Watson +under contract to +nCircle Network Security, Inc. -- 2.41.0 From ca16d5b07ed885d38570d40804edab0a3ec50a43 Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Thu, 1 Jan 2009 12:52:49 +0000 Subject: [PATCH 04/16] Remove some sentences that do not apply to DragonFly --- share/man/man9/priv.9 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/share/man/man9/priv.9 b/share/man/man9/priv.9 index 5247edee19..5bddef47ed 100644 --- a/share/man/man9/priv.9 +++ b/share/man/man9/priv.9 @@ -48,7 +48,7 @@ passed thread, .Fa td , or credential, .Fa cred . -This interface replaces the now removed +This interface replaces the .Xr suser 9 privilege checking interface. Privileges typically represent rights in one of two categories: the right to @@ -67,9 +67,6 @@ sometimes real) UID having a value of 0, and the .Xr jail 2 policy, which permits only certain privileges to be granted to processes in a jail. -The set of available privileges may also be influenced by the TrustedBSD MAC -Framework, described in -.Xr mac 9 . .Sh IMPLEMENTATION NOTES When adding a new privilege check to a code path, first check the complete list of current privileges in @@ -111,7 +108,6 @@ privilege checks, and the caller is unable to tell if an access control failure occurred. .Sh SEE ALSO .Xr jail 2 , -.Xr mac 9 , .Xr ucred 9 .Sh AUTHORS The -- 2.41.0 From a640d20054e6eec54173f2155c281f837aab9717 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Thu, 1 Jan 2009 14:29:05 +0100 Subject: [PATCH 05/16] Fix typo (unbreaks LINT build). --- sys/dev/netif/wl/if_wl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/netif/wl/if_wl.c b/sys/dev/netif/wl/if_wl.c index 8df10fda65..985f297286 100644 --- a/sys/dev/netif/wl/if_wl.c +++ b/sys/dev/netif/wl/if_wl.c @@ -1429,7 +1429,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cred) /* copy the EEPROM in 2.4 Gz WaveMODEM out to the caller */ case SIOCGWLEEPROM: /* root only */ - if ((error = priv_check(td; PRIV_ROOT))) + if ((error = priv_check(td, PRIV_ROOT))) break; /* pointer to buffer in user space */ up = (void *)ifr->ifr_data; -- 2.41.0 From 8a506447b9506b8baded881dd271f8f089857913 Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Thu, 1 Jan 2009 14:50:34 +0000 Subject: [PATCH 06/16] Cosmetic changes + comments --- sys/kern/kern_jail.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index acd7022145..677372b3ff 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -146,19 +146,21 @@ sys_jail(struct jail_args *uap) error = priv_check(td, PRIV_ROOT); if (error) { uap->sysmsg_result = -1; - return(error); + return (error); } - error = copyin(uap->jail, &jversion, sizeof jversion); + error = copyin(uap->jail, &jversion, sizeof(jversion)); if (error) { uap->sysmsg_result = -1; - return(error); + return (error); } pr = kmalloc(sizeof *pr , M_PRISON, M_WAITOK | M_ZERO); SLIST_INIT(&pr->pr_ips); switch (jversion) { case 0: - error = copyin(uap->jail, &jv0, sizeof(struct jail_v0)); + /* Single IPv4 jails. */ + + error = copyin(uap->jail, &jv0, sizeof(jv0)); if (error) goto bail; jip = kmalloc(sizeof(*jip), M_PRISON, M_WAITOK | M_ZERO); @@ -168,6 +170,13 @@ sys_jail(struct jail_args *uap) SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries); break; case 1: + /* + * DragonFly multi noIP/IPv4/IPv6 jails + * + * NOTE: This version is unsupported by FreeBSD + * (which uses version 2 instead). + */ + error = copyin(uap->jail, &j, sizeof(j)); if (error) goto bail; -- 2.41.0 From 81be0cb8c445ffb4220a5bf5d782de2c8516c839 Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Thu, 1 Jan 2009 14:52:15 +0000 Subject: [PATCH 07/16] Use kfree() instead of FREE macro --- sys/kern/kern_jail.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 677372b3ff..6c42ff46a5 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -251,9 +251,9 @@ bail: while (!SLIST_EMPTY(&pr->pr_ips)) { jip = SLIST_FIRST(&pr->pr_ips); SLIST_REMOVE_HEAD(&pr->pr_ips, entries); - FREE(jip, M_PRISON); + kfree(jip, M_PRISON); } - FREE(pr, M_PRISON); + kfree(pr, M_PRISON); return(error); } @@ -620,7 +620,7 @@ prison_free(struct prison *pr) while (!SLIST_EMPTY(&pr->pr_ips)) { jls = SLIST_FIRST(&pr->pr_ips); SLIST_REMOVE_HEAD(&pr->pr_ips, entries); - FREE(jls, M_PRISON); + kfree(jls, M_PRISON); } LIST_REMOVE(pr, pr_list); prisoncount--; -- 2.41.0 From f5b8f0d899db733bddc7cabf1c17a9673a265d39 Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Thu, 1 Jan 2009 14:56:21 +0000 Subject: [PATCH 08/16] Use consistent sizeof() style --- sys/kern/kern_jail.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 6c42ff46a5..b17f4290c4 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -153,7 +153,7 @@ sys_jail(struct jail_args *uap) uap->sysmsg_result = -1; return (error); } - pr = kmalloc(sizeof *pr , M_PRISON, M_WAITOK | M_ZERO); + pr = kmalloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); SLIST_INIT(&pr->pr_ips); switch (jversion) { @@ -200,7 +200,7 @@ sys_jail(struct jail_args *uap) goto bail; } - error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0); + error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); if (error) goto bail; error = nlookup_init(&nd, j.path, UIO_USERSPACE, NLC_FOLLOW); -- 2.41.0 From f5573138baa249de8803cb2d36c8855d10df3a14 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 1 Jan 2009 22:51:52 +0800 Subject: [PATCH 09/16] Add weak symbol for inet_ntop() Reported-by: hasso@ While I am here, move inet_net_ntop() weak reference generation macro to its own file. --- contrib/bind-9.3/lib/bind/inet/inet_net_ntop.c | 9 +++++++++ contrib/bind-9.3/lib/bind/inet/inet_ntop.c | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/contrib/bind-9.3/lib/bind/inet/inet_net_ntop.c b/contrib/bind-9.3/lib/bind/inet/inet_net_ntop.c index 47af6284ed..acf49b38e4 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_net_ntop.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_net_ntop.c @@ -275,3 +275,12 @@ emsgsize: errno = EMSGSIZE; return (NULL); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_net_ntop +__weak_reference(__inet_net_ntop, inet_net_ntop); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_ntop.c b/contrib/bind-9.3/lib/bind/inet/inet_ntop.c index eefc5214be..ece29989d6 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_ntop.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_ntop.c @@ -205,6 +205,6 @@ inet_ntop6(src, dst, size) * Weak aliases for applications that use certain private entry points, * and fail to include . */ -#undef inet_net_ntop -__weak_reference(__inet_net_ntop, inet_net_ntop); +#undef inet_ntop +__weak_reference(__inet_ntop, inet_ntop); #endif -- 2.41.0 From ad7a24578559032149483739f67dc265bfbf8c4d Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Thu, 1 Jan 2009 17:35:53 +0100 Subject: [PATCH 10/16] Re-add ascii2addr() and addr2ascii() prototypes. --- include/arpa/inet.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/arpa/inet.h b/include/arpa/inet.h index 163f9106f5..3f697165f8 100644 --- a/include/arpa/inet.h +++ b/include/arpa/inet.h @@ -118,6 +118,8 @@ const char *inet_ntop(int, const void * __restrict, char * __restrict, int inet_pton(int, const char * __restrict, void * __restrict); #if __BSD_VISIBLE +int ascii2addr (int, const char *, void *); +char *addr2ascii (int, const void *, int, char *); int inet_aton(const char *, struct in_addr *); in_addr_t inet_lnaof(struct in_addr); struct in_addr inet_makeaddr(in_addr_t, in_addr_t); -- 2.41.0 From 0933d3a2bc494936486f1b96389e6494ac19746a Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Thu, 1 Jan 2009 17:48:50 +0100 Subject: [PATCH 11/16] Hook in priv.9 and add MLINKS. --- share/man/man9/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 14b206877e..9028eb880e 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -112,6 +112,7 @@ MAN= accept_filter.9 \ pfil.9 \ physio.9 \ posix4.9 \ + priv.9 \ resettodr.9 \ rman.9 \ rtalloc.9 \ @@ -470,6 +471,8 @@ MLINKS+=pfil.9 pfil_add_hook.9 \ MLINKS+=physio.9 physread.9 \ physio.9 physwrite.9 MLINKS+=posix4.9 p1003_1b.9 +MLINKS+=priv.9 priv_check.9 \ + priv.9 priv_check_cred.9 MLINKS+=rman.9 rman_activate_resource.9 \ rman.9 rman_await_resource.9 \ rman.9 rman_deactivate_resource.9 \ -- 2.41.0 From 456338f39777ef3ce5c6d039dbbf4d9a81c7e58a Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Thu, 1 Jan 2009 17:59:35 +0100 Subject: [PATCH 12/16] Regenerate the pciconf(8) database from the following files: Hart: Jan 22, 2008 (version 671) Boemler: Jan 1, 2009 Mares: Dec 27, 2008 --- share/misc/pci_vendors | 287 +++++++++++++++++++++++++++-------------- 1 file changed, 188 insertions(+), 99 deletions(-) diff --git a/share/misc/pci_vendors b/share/misc/pci_vendors index 1018dc48da..4e1f6b267e 100644 --- a/share/misc/pci_vendors +++ b/share/misc/pci_vendors @@ -1,4 +1,3 @@ -; $DragonFly: src/share/misc/pci_vendors,v 1.18 2008/11/02 17:59:37 swildner Exp $ ; ; Automatically generated by src/tools/tools/pciid/mk_pci_vendors.pl ; (with the -l option), using the following source lists: @@ -291,6 +290,13 @@ 005E SAS 3000 series, 6-port with 1066 -StorPort 0060 SAS1078 PCI-X Fusion-MPT SAS 0062 LSISAS1078 PCI-Express Fusion-MPT SAS + 0064 SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] + 0065 SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] + 0070 SAS2004 PCI-Express Fusion-MPT SAS-2 [Spitfire] + 0072 SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] + 0074 SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] + 0076 SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] + 0077 SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] 007C MegaRAID SAS 1078DE 008F 53C810 LSI 53C8xx SCSI host adapter chip 0407 MegaRAID @@ -333,7 +339,7 @@ 0017 ispLSI1032E PROTO-3 PCI, digital I/O with chipselect 0020 ispLSI1032E Universal digital I/O PCI-Interface 9100 INI-9100/9100W SCSI Host -1002 ATI Technologies Inc +1002 ATI Technologies Inc. 0B12 ati 1900 ati 1900 3150 M24 1P Radeon Mobility X600 3151 FIREMV 2400 @@ -407,7 +413,7 @@ 4378 IXP SB400 AC'97 Modem Controller 4379 IXP SB400 Serial ATA Controller 437A IXP SB400 Serial ATA Controller - 437B OEM Intel Corporation& Microsoft UAA Bus Driver for High Definition Audio + 437B Intel Corporation IXP SB450 High Definition Audio Controller 4380 IXP SB600 Serial ATA Controller 4381 IXP SB600 Serial ATA RAID Controller 4382 IXP SB600 AC'97 Audio Controller @@ -448,13 +454,13 @@ 474F Rage XL PCI-66 I Need Driver for the Chip 4750 ATI 3D Rage Pro 215GP ATI 3D Rage Pro 215GP 4751 Rage 3D Pro PCI (PQFP Package, Limited 3D) - 4752 Rage XL PCI sf + 4752 Rage XL PCI ATI On-Board VGA for HP Proliant 350 G3 4753 Rage XC PCI 4754 Mach 64 VT Rage 3D II Graphics Accelerator 4755 Rage 3D II+pci 3d rage 2 + dvd 4756 Rage 3D IIC PCI [Mach64 GT IIC] (PQFP Package) 4757 Rage 3D IIC AGP (BGA Package) - 4758 Mach64 GX (210888GX) + 4758 210888GXControladores ATI 210888GX [Mach64 GX] Mach 64 GT 4759 215r2qzua21 m3d agp card on agp slot 475A Rage 3D IIC AGP (PQFP Package) 4964 Radeon 9000 Series (RV250 Id) @@ -866,7 +872,7 @@ 71C7 RADEON X1650 SERIES 71CD Radeon X1600 Series 71CE Radeon X1600 PRO / X1300XT (RV530 VE) - 71D2 FireGL V3400 FireGL V3400 + 71D2 RV530GL FireGL V3400 71D4 Mobility FireGL V5250 (M56GL) 71D5 Mobility Radeon X1700 (M66-P) 71D6 Mobility Radeon X1700 (M66-XT) @@ -881,7 +887,7 @@ 71E7 RADEON X1650 SERIES SECONDARY 71ED Radeon X1600 Series Secondary 71EE Radeon X1600 PRO / X1300XT Secondary (RV530 VE) - 71F2 FIREGL V3400 Secondary + 71F2 RV530GL ATI FireGL V3400 Secondary 71FA FIREGL V5200 Secondary 71FE RV530 SE Secondary 7205 1106 S3G Unichrome IGP KM400/KN400 @@ -961,7 +967,7 @@ 940A FireGL V8650 940B FireGL V8600 940F FireGL V7600 - 9440 RV770 [Radeon HD 4870] + 9440 Radeon 4870 Graphics adapter 9441 R700 [Radeon HD 4870 X2] 9442 RV770 [Radeon HD 4850] 9443 R700 [Radeon HD 4850] @@ -969,8 +975,10 @@ 944C RV770 LE [Radeon HD 4800 Series] 945A M98 XT [Mobility Radeon HD 4870] 9480 M96 [Mobility Radeon HD 4650] + 9489 M96 XT [Mobility FireGL V5725] 9490 RV730XT [Radeon HD 4670] 9498 RV730 PRO [Radeon HD 4650] + 949F RV730 [FirePro V5700] 94C1 REV_00 ATI Radeon HD 2400 PRO 94C3 RV610 ATI Radeon HD 2400 PRO 94C4 RV610 ATI Radeon HD 3470 PRO AGP @@ -979,7 +987,7 @@ 94C8 Mobility Radeon HD 2400 XT 94C9 Mobility Radeon HD 2400 94CB Radeon E2400 - 94CC RV 610LE PCI [Radeon HD 2400] + 94CC ATI Radeon HD 2400 Series ATI Radeon HD 2400 Series 9501 RV670 ATI Radeon HD 3870 9504 Mobility Radeon HD 3850 9505 Radeon HD 3850 @@ -991,6 +999,8 @@ 9519 RV670 [FireStream 9170] 9540 RV710 [Radeon HD 4550] 954F RV710 [Radeon HD 4350] + 9552 M92 LP [Mobility Radeon HD 4300 Series] + 9553 M92 [Mobility Radeon HD 4500 Series] 9559 Mobility Radeon HD 3600 Series 9581 600458 ATI Mobility Radeon HD2600 9583 Mobility Radeon HD 2600 XT @@ -1021,6 +1031,7 @@ 9612 RS780M/RS780MN [Radeon HD 3200 Graphics] 9613 RS780MC [Radeon HD 3100 Graphics] 9614 Radeon HD 3300 Graphics + 9616 760G [Radeon 3000] 9876 ATI GTC (GT-C2U2) ATI 3D Rage Pro AGP 2X AA00 R600 Audio Device [Radeon HD 2900 Series] AA01 Ati Function driver for high definition audio - AT Ati Mobility Radeon HD 2600 @@ -1572,7 +1583,7 @@ 0525 MGA G450 Dual Head Chip of G450 graphics card 0527 Parhelia AGP 0528 Parhelia Parhelia 128MB/256MB/PCI/HR256 - 0532 MGA G200eW WPCM450 [Hermon] - Winbond/Nuvoton + 0532 MGA G200eW WPCM450 0540 M91XX 0D10 MGA-I Athena (Ultima/Impression board) 1000 MGA-G100 Chipset PCI @@ -1638,7 +1649,7 @@ 0002 PCI to VL98 Bridge 0003 ATM Controller 0004 R4000 PCI bus Bridge - 0005 PCI to 486 like peripheral bus Bridge + 0005 pci 7432 PCI to 486 like peripheral bus Bridge 0006 GUI Accelerator 0007 unknown from Creative.com PCI to ux-bus Bridge 0008 GUI Accelerator (vga equivalent) @@ -2051,12 +2062,13 @@ 8119 na iRDA Compatible Controller 8201 006D103C TI UltraMedia Firmware Loader Device 8204 4610, 4515, 4610FM, 7510 PCI 7510/4510 Cardbus Controller - 8231 PCIe to PCI Bridge + 8231 XIO2000A PCI-Express to PCI/PCI-X bridge 8235 XIO2200(A) IEEE-1394a-2000 Controller (PHY/Link) 823E XIO2213A PCI Express to PCI Bridge 823F XIO2213A 1394b OHCI with 3-Port PHY - 8400 ???? D-Link AirPlus DWL-520+, Uses a TI 802.11b 22 MBPS Chip + 8400 ACX100AGHK D-Link AirPlus DWL-520+, Uses a TI 802.11b 22 MBPS Chip 8401 ACX 100 22Mbps Wireless Interface + 8671 12500 TI Boulevard M/S 8671 Dallas TX 75243-3500 972-644-5580 9000 Wireless Interface (??) 9065 TMX320C6412 Fixed Point Digital Signal Processor 9066 USR5410 U.S. Robotics 802.11g Wireless Turbo PC Card @@ -2069,7 +2081,7 @@ AC10 PCI1050 PC Card Controller AC11 PCI1030/1053 PC Card Controller AC12 PCI1130 PC card CardBus Controller - AC13 PCI9440 PCI\VEN_104C&DEV_803B&SUBSYS_00011179&REV_00\4&6B16D5B&0&5AF0 + AC13 PCI9440 PCI\VEN_104C&DEV_803B&SUBSYS_30AA103C&REV_00\4&33F64D4&0&32F0 AC15 PCI1131 PC Card CardBus Controller AC16 PCI1250 PC Card CardBus Controller AC17 PCI1220 PC Card CardBus Controller @@ -2115,6 +2127,8 @@ AC8D PCI7620 AC8E PCI7420 CardBus Controller AC8F PCI7420/PCI7620 Dual Socket CardBus and Smart Card Cont. w/ 1394a-2000 OHCI Two-Port PHY/Link-Layer Cont. and SD/MS-Pro Sockets + B000 TMS320C645x Device ID: 0xB001 + B001 TMS320DM647-DM648 DSP with a C64x+ core and M/S PCI interface FE00 tsb12lv26 FireWire Host Controller FE03 12C01A FireWire Host Controller 104D Sony Corporation @@ -2166,6 +2180,7 @@ 3012 ColdFusion 3e Chipset Memory Controller Hub 3017 Unassigned Hitachi Shared FC Device 3017 301D PCIe-to-PCIe Bridge with Virtualization IO Assist Feature + 3020 FIVE-EX based Fibre Channel to PCIe HBA 3505 SH7751 SuperH (SH) 32-Bit RISC MCU/MPU Series 350E SH7751R PCI Controller (PCIC) 1055 Standard Microsystems Corp (Was: EFAR Microsystems) @@ -2219,48 +2234,62 @@ 1058 Electronics Telecommunication Research Inc (ETRI) 1059 Kontron Canada (Was: Teknor Microsystems) 105A Promise Technology Inc - 0D30 PDC20265R Promise Ultra100 (tm) IDE Controller (PDC20265) + 0D30 PDC20265/R MBUltra100/MBFastTrack100 Lite 0D38 PDC20263 FastTrak66 Lite EIDE Controller - 1275 PDC20275 FastTrack TX EIDE Controller + 1275 PDC20275 MBUltra133 EIDE Controller + 1960 ? SuperTrak 66/100 RAID + 1962 ? SuperTrak SX 6000 3318 PDC20318(??) FastTrak SATA150 TX4 Controller 3319 PDC20319(??) FastTrak SATA150 TX4 Controller 3371 PDC20371(??) FastTrak SATA150 TX2plus Controller 3373 PDC20378 FastTrak 378/SATA 378 RAID Controller 3375 PDC20375(??) FastTrak SATA150 TX2plus Controller 3376 PDC20376 FastTrak 376 SATA/RAID Controller - 3515 PDC40719 - 3519 PDC40519 FastTrak TX4200 + 3515 PDC40719 FastTrak TX43xx + 3519 PDC40519 FastTrak TX42xx 3570 PDC20771 FastTrak TX2300 SATA300 Controller - 3571 PDC20571 FastTrak TX2200 + 3571 PDC20571 Fasttrack TX2200 3574 Promise SATAII150 579 (tm) IDE Controller 3577 PDC40779 SATA-300 779 3D17 PDC40718-GP SATA 300 TX4 Controller 3D18 Promise SATAII150 518 (tm) IDE Controller - 3D73 PDC20775 SATAII 300 TX2plus IDE Controller + 3D73 PDC40775 SATA-300 TX2plus 3D75 PDC20575 SATAII150 TX2plus - 3F20 PDC42819 [FastTrak TX2650/TX4650] + 3F19 ? FastTrak TX2650/4650/4652 + 3F20 PDC42819 FastTrak TX2650(3F21)/4650(3F22)/PDC42819(3716) 4302 SuperTrak EX Series (tm) Controller - 4D30 PDC20267 FastTrack100 EIDE Controller - 4D33 PDC20246 FastTrak Ultra ATA RAID controller + 4D30 PDC20267 FastTrack100 on Intel MB SE7500CW2 + 4D33 PDC20246 FastTrak/Ultra33 ATA RAID controller 4D38 PDC20262 FastTrak66 EIDE Controller - 4D68 PDC20268 Ultra100 TX2 EIDE Controller + 4D68 PDC20268/R Ultra100TX2/FastTrak100TX/LP 4D69 PDC20269 Ultra133 TX2 EIDE Controller 5275 PDC20276 Ultra133 TX2/FastTrak TX Lite EIDE Controller 5300 DC5300 EIDE Controller - 6268 PDC20268R FastTrak100 TX2/TX4/LP EIDE controller + 6268 PDC20268R FastTrak100 TX2/TX4/LP EIDE Controller 6269 PDC20271 FastTrak TX2000 EIDE controller - 6300 PDC81731 [FastTrak SX8300] + 6300 ? FastTrak SX 8300 + 6301 ? FastTrak SX8300-1 + 6302 ? FastTrak SX 4300 + 6303 ? FastTrak SX 4300-1 + 6304 ? FastTrak SX8300-2 + 6305 ? FastTrak SX8300-3 + 6306 ? FastTrak SX 4300-2 + 6307 ? FastTrak SX 4300-3 6621 PDC20621 (FastTrak S150 SX4/FastTrak SX4000 lite) 6622 PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller 6624 PDC20621 [FastTrak SX4100] 6626 PDC20618 (Ultra 618) 6629 FastTrak TX4000 Controller + 7250 ? Vitesse 7250 SAS RAID 7275 PDC20277 FastTrak TX/SBFastTrak133 Lite EIDE Controller - 8002 SATAII150 SX8 - 8350 SuperTrak EX Series (tm) Controller - 8650 81384 [SuperTrak EX SAS and SATA RAID Controller] + 8000 ? SATAII150 SX8 + 8002 ? SATAII150 SX8 + 8004 ? SATAII150 SX8 + 8006 ? SATAII150 SX8 + 8350 ? SuperTrak EX8350/16350/8300/16300 + 8650 ? SuperTrak EX SAS RAID C350 SuperTrak EX Series (tm) Controller - E350 80333 [SuperTrak EX24350] + E350 ? SuperTrak EX 243X0 105B Foxconn International Inc. 0C4D SiS AC'97 Sound Controller 105C Wipro Infotech Limited @@ -2331,7 +2360,7 @@ BA56 eXtremeRAID Disk Array BA57 eXtremeRAID 4000/5000 support Device 106A Aten Research Inc. -106B Apple Computer Inc. +106B Apple Computer Inc 0001 Bandit PowerPC Host-PCI Bridge 0002 Grand Central I/O Controller 0003 Control Video @@ -2480,7 +2509,7 @@ 0402 ZFMicro IDE Controller 0403 ZFMicro Expansion Bus 1079 I-Bus -107A Networth +107A Networth controls 107B Gateway 2000 107C LG Electronics / Goldstar Co Ltd 107D Leadtek Research @@ -2705,7 +2734,9 @@ D130 PCI-232/2 2-port RS-232 Serial Interface Board 1094 First International Computers 1095 Silicon Image Inc (Was: CMD Technology Inc) - 0240 Adaptec AAR-1210SA SATA HostRAID Controller + 0240 SIL3112 SATA/Raid controller(2XSATA150) + 0242 SIL3132 SATAII/Raid controller + 0244 SIL3132 eSATA/Raid controller 0640 PCI-0640 EIDE Adapter (Single FIFO) 0641 PCI0640 PCI EIDE Adapter with RAID 1 0642 PCI-0642 EIDE Adapter with RAID 1 @@ -2720,7 +2751,7 @@ 0680 SiI 0680 (Was: PCI-0680) Ultra ATA133 EIDE Controller 1392 1392 INTEL HDMI AUDIO 2455 SI3124 SATALink 4-Port PCI-X Host Controller - 3112 SiI 3112 SATARaid Controller + 3112 SIL3112 SATA/Raid controller(2XSATA150) 3114 Sil 3114 SATALink/SATARaid Controller 3124 SiI 3124 PCI-X to Serial ATA Controller 3132 SiI 3132 PCI Express (1x) to 2 Port SATA300 @@ -2927,7 +2958,7 @@ 1002 Ambassador ATM Adapter 10B7 3COM Corp, Networking Division 0001 3C985 1000BaseSX Gigabit Ethernet Adapter - 0013 3com p/n: 3CRDAG675 3Com� 11a/b/g Wireless PCI Adapter + 0013 3com p/n: 3CRDAG675 3Com11a/b/g Wireless PCI Adapter 0910 3C910-A01 1000 3C905CX-TXNM 3COM 3C905CX-TXNM with 40-0664-003 ASIC 1006 14e4:1645 Broadcom Corporation NetXtreme BCM5701 Gigabit Ethernet @@ -3099,7 +3130,7 @@ 5457 M1563M AC97 Modem controller 5459 56k Voice Modem 545A 56K Voice Modem - 5461 SW\{CD171DE3-69E5-11D2-B56D-0000F8754380}\{9B36589 Microsoft UAA Bus Driver for High Definition Audio + 5461 M5461 High Definition Audio Controller 5471 M1563M Southbridge Memory Stick Host 5473 M1563M Southbridge MMC/SD controller 7101 ALI M7101 Power Management Controller @@ -3188,7 +3219,7 @@ 10D3 Jabil Circuit Inc. 10D4 Hualon Microelectronics 10D5 Autologic Inc. -10D6 Cetia +10D6 Wilson .co .ltd FF51 0x0100 C87899D 10D7 BCM Advanced Research 10D8 Advanced Peripherals Labs @@ -3393,7 +3424,7 @@ 0145 NV43 NVIDIA GeForce 6610 XL 0146 Geforce Go 6600TE/6200TE [NV43] 0147 GeForce 6700 XL - 0148 GeForce Go 6600 [NV43] + 0148 unknown GeForce Go 6600 0149 GeForce Go 6600 [NV43] 014A Quadro NVS 440 014C Quadro FX 540 MXM @@ -3470,7 +3501,7 @@ 01C3 nForce MCP Networking Adapter 01D0 GeForce 7350 LE 01D1 unknown NVIDIA GeForce 7300 LE - 01D3 GeForce 7300 SE + 01D3 nVidia nVidia GeForce 7300 SE 01D6 GeForce Go 7200 01D7 Quadro NVS 110M / GeForce Go 7300 01D8 Quadro NVS 120M / GeForce Go 7400 @@ -3532,7 +3563,7 @@ 0266 MCP51S NVIDIA nForce 430/410 Serial ATA Controller 0267 MCP51S NVIDIA nForce 430/410 Serial ATA Controller 0268 430 NVIDIA nForce Networking Controller - 0269 MCP51 Network Bus Enumerator + 0269 2A34103C MCP51 Ethernet Controller 026A MCP51 MCI 026B MCP51 AC'97 Audio Controller 026C MCP51 High Definition Audio @@ -3557,7 +3588,7 @@ 0293 GeForce 7900 GX2 0294 GeForce 7950 GX2 0295 GeForce 7950 GT - 0297 GeForce Go 7950 GTX + 0297 G71 NVIDIA GeForce Go 7950 GTX 0298 GeForce Go 7900 GS 0299 GeForce Go 7900 GTX 029A Quadro FX 2500M @@ -3661,7 +3692,7 @@ 036E MCP55 MCP55 PATA Controller 036F MCP55 MCP55 SATA/RAID Controller 0370 MCP55 PCI bridge - 0371 ADI 1988 8 Channel High Definition Audio + 0371 ADI 1988 MCP55 High Definition Audio 0372 MCP55 Ethernet 0373 MCP55 Ethernet 0374 MCP55 PCIe bridge @@ -3675,7 +3706,7 @@ 037F MCP55S MCP55 SATA/RAID Controller 0390 GeForce 7650 GS 0391 G73 B1 Ge-Force 7600GT - 0392 GeForce 7600 GS + 0392 NVIDIA GeForce 7600 GS NVIDIA GeForce 7600 GS 0393 UNKOWN NVIDIA GeForce 7300GT 0394 GeForce 7600 LE 0395 GeForce 7300 GT @@ -3684,7 +3715,7 @@ 0399 GeForce Go 7600 GT 039B GeForce Go 7900 SE 039C Quadro FX 550M - 039E Quadro FX 560 + 039E Quadro FX 560 Quadro FX 560 03A0 C55 Host Bridge 03A1 C55 Host Bridge 03A2 C55 Host Bridge @@ -3759,7 +3790,7 @@ 0420 GeForce 8400 SE 0421 G86 GeForce 8500 GT 0422 GeForce 8400 GS - 0423 GeForce 8300 GS + 0423 G86 NVIDIA Geforce 8300 GS 0424 GeForce 8400 GS 0425 GeForce 8600M GS 0426 GeForce 8400M GT @@ -3770,7 +3801,7 @@ 042B 8400 ?? NVIDIA Quadro NVS 135M 042D Quadro FX 360 M Quadro FX 360 M (Mobile) 042E GeForce 9300M G - 042F Quadro NVS 290 + 042F NVS 290 NVIDIA Quadro NVS 290 0440 MCP65 LPC Bridge 0441 MCP65 LPC Bridge 0442 MCP65 LPC Bridge @@ -3849,19 +3880,21 @@ 060C GeForce 8800M GTX 060D GeForce 8800 GS 0610 GeForce 9600 GSO - 0611 GeForce 8800 GT + 0611 8800 GT Alphadog edition from XFX 0612 GeForce 9800 GTX 0614 GeForce 9800 GT 061A Quadro FX 3700 061C Quadro FX 3600M - 0622 nVidia GeForce 9600GT nVidia + 0622 nVidia GeForce 9600GSO nVidia 0623 GeForce 9600 GS + 063A Quadro FX 2700M 0640 G96-300-A1 Nvidia 9500GT graphic controller + 0641 D9M-20 [GeForce 9400 GT] 0644 G96 GeForce 9500 GS 0645 G96 GeForce 9500 GS 0647 GeForce 9600M GT 0648 GeForce 9600M GS - 0649 nVidia nVidia GeForce 9600M GT + 0649 G96 nVidia GeForce 9600M GT 064B GeForce 9500M G 06E2 GeForce 8400 06E4 GeForce 8400 GS @@ -3933,6 +3966,8 @@ 0849 GeForce 8200 084A nForce 730a 084B GeForce 8200 + 084C nForce 780a SLI + 084D nForce 750a SLI 084F GeForce 8100 / nForce 720a 0860 GeForce 9300 0861 GeForce 9400 @@ -3999,6 +4034,10 @@ 0AC8 MCP79 PCI Express Bridge 0AD0 MCP78 SATA Controller IDE mode 0AD4 MCP78S [GeForce 8200] AHCI Controller + 0BC4 MCP? AHCI Controller + 0BC5 MCP? AHCI Controller + 0BCC MCP? Raid Controller + 0BCD MCP? Raid Controller 10DE NV3 Riva 128 21C3 nVidia Corporation G73 [GeForce 7600 GS] (rev a2) C615 G70 [GeForce 7600 GT] @@ -4061,7 +4100,7 @@ 9128 IMS9129 TwinTurbo 128 GUI Accelerator 9135 IMS9135 TwinTurbo 128-3D Display Adapter 10E1 Tekram Technology Corp. Ltd. - 0391 TRM-S1040 + 0391 TRM-S1040 0000 690C DC-690c DC20 DC-290 EIDE Controller DC29 DC-290 @@ -4149,15 +4188,15 @@ 0880 880 High Definition Audio 0883 alc888S Realtek High Definition Audio 0885 ALC885 7.1+2 Channel High-Performance HDA Codec with Content Protection - 0888 realtek high definition audio pavillion a6030n + 0888 realtek high definition audio Realtek Azak´lia chipset 8021 RTL8029AS NIC 8029 RTL8029(as)pci ethernet nic windot XPse 8119 10 32BIT Card Bus 10/100 (10EC-8119) 8129 RTL8139d 10/100 Fast Ethernet Controller 8131 LFE8139ATX - 8136 RTL8100-8101E-8102E-PCIEXPRESS Realtek 8139/810x Family Fast Ethernet NIC + 8136 RTL8100-8101E-8102E-PCIEXPRESS RTL8100E/RTL8101E/RTL8102E-GR 8138 RT8139 (B/C) CardBus Fast Ethernet Adapter - 8139 RTL-8139/8139C/8139C+ 10/100 Mbps Fast Ethernet NIC + 8139 RTL-8139/8139C/8139C+ Realtek RTL8139 Family PCI Fast Ethernet NIC 8167 RTL8169/8110 Family Gigabit Ethernet NIC 8168 RTL8168/8111 PCI-E Gigabit Ethernet NIC 8169 RTL8119 Single Gigabit LOM Ethernet Controller @@ -4203,6 +4242,7 @@ 1677 Multimedia 2013 RS-56 sp-pci Conexant RS-56 PCI Modem 2865 Tyan Thunder K8E S2865 + 5300 Tyan S5380 Mainboard 10F2 Achme Computer Inc. - GONE !!!! 10F3 Alaris Inc. 10F4 S-Mos Systems @@ -4252,7 +4292,7 @@ 0002 INI-920 Ultra SCSI Adapter 1060 INI-A100U2W Orchid Ultra-2 SCSI Controller 134A Ultra SCSI Adapter - 1622 inic1620 S-ATA Adapter + 1622 INIC1620 PCI SATA Controller 9100 INI-9010/9010W Fast Wide SCSI Controller 9400 INIC-940 Fast Wide SCSI Controller 9401 INIC-935 Fast Wide SCSI Controller @@ -4265,7 +4305,7 @@ 0004 Creative SB Audigy 2 ZS (WDM) Audigy Audio Processor 0005 SB0460 SoundBlaster X-FI XtremeMusic 0006 emu10k1x Soundblaster Live! 5.1 - 0007 C6SB0410515017656A Audigy SE + 0007 C6SB0410515017656A Audigy ls 0008 ca0108 sound blaster Audigy 2 0009 [SB X-Fi Xtreme Audio] CA0110-IBG 1017 CT6760 3D Blaster Banshee PCI CT6760 @@ -4285,8 +4325,8 @@ 9838 Ectiva EV1938 1103 Triones Technologies Inc. (HighPoint) 0003 HPT343/5/6,HPT363 UDMA EIDE Controller - 0004 HPT3xx UDMA66/100/133 EIDE Controller - 0005 HPT372x UDMA/ATA133 RAID Controller + 0004 HPT366/368/370/370A ATA Raid Controller + 0005 HPT372/372N PATA133 Raid Controller 0006 HPT302N UDMA/ATA133 RAID Controller 0007 HPT371/N UDMA/ATA133 EIDE Controller 0008 HPT374 Rocket 154x/1640, RocketRAID 154x/1640 RAID EIDE Controller @@ -4644,6 +4684,7 @@ E238 K8T890 PCI-to-PCI Bridge E340 PT900 PCI to PCI Bridge Controller E353 VX800/VX820 PCI Express Root Port + E721 VT1708B 8-channel High Definition Audio CODEC F208 PT890 PCI-to-PCI Bridge F238 K8T890 PCI-to-PCI Bridge F340 PT900 PCI to PCI Bridge Controller @@ -4820,6 +4861,7 @@ 0003 IDT77222/252 MICRO ABR SAR PCI ATM Controller 0004 IDT77V252 MICRO ABR SAR PCI ATM Controller 0005 IDT77V222 155Mbps ATM MICRO ABR SAR Controller + 76B2 92HD71B7 IDT Audio 8018 PES12N3A PCI Express Switch 801C PES24N3A PCI Express Switch 8028 PES4T4 PCI Express Switch @@ -4907,7 +4949,7 @@ 5402 TriMedia TM-1300EH Media Processor 5405 TriMedia TM1500 5406 TriMedia PNX1700 - 7130 73c0a1434628 Philips SAA7130HL Multimedia Capture Device + 7130 73c0a1434628 Philips SAA7135HL Multimedia Capture Device 7133 Pinnacle PCTV 110i Pinnacle PCTV 110i Capture Device 7134 SAA7134HL Multimedia Capture Device 7135 SAA???? Multimedia Device(??) @@ -4982,6 +5024,10 @@ 1136 Momentum Data Systems 0002 PCI-JTAG 1137 Cisco Systems Inc + 0023 PCIe Upstream Port Bridge + 0041 PCIe Downstream Port Bridge + 0043 10G Ethernet NIC + 0045 FCoE HBA 1138 Ziatech Corporation 8905 8905 STD 32 Bridge 1139 Dynamic Pictures Inc @@ -5019,7 +5065,7 @@ 6425 ProMotion AT25 0752 20005 6426 GUI Accelerator 643D AT25 ProMotion-AT3D - 9876 ProMotion AT25 139K76B 9808 + 9876 ProMotion 6422 139K76B 9808 1143 Netpower Inc 1144 Vickers Inc/Cincinnati Milacron 0001 Noservo Controller @@ -5033,6 +5079,7 @@ F020 CardBus ATAPI Host Adapter F021 NPATA32 CardBus CompactFlash Adapter F024 NPATA-32 CardBus CompactFlash Adapter + F103 NinjaPATA-32 Delkin Cardbus UDMA 1146 Force Computers 1147 Interface Corp 1123 123 131dq @@ -5294,7 +5341,7 @@ 13A8 XR17C158/154/152 Multi-channel PCI UART 117A A-Trend Technology 117B LG (Lucky Goldstar) Electronics Inc. - 8320 GCE-8320B CD-R/RW Drive + 8320 NOFM12 USB DEVICE 117C Atto Technology 002C SAS RAID Adapter 0030 Ultra320 SCSI Host Adapter @@ -5485,6 +5532,7 @@ 1FAB Libertas 802.11b/g Wireless LAN Client Adapter 2A01 Libertas 802.11a/b/g Wireless Controller (CB55) 2A02 88W8361 [TopDog] 802.11n Wireless + 2A30 ? PCI-Express 802.11bg Wireless 4101 OLPC Cafe Controller Secure Digital Controller 4320 Yukon 88E8001/8003/8010 PCI Gigabit Ethernet Controller (Copper) 4340 Yukon 88E8021 PCI-X IPMI Gigabit Ethernet Controller @@ -5496,14 +5544,14 @@ 4346 Yukon 88E8061 PCI-E IPMI Gigabit Ethernet Controller 4347 Yukon 88E8062 PCI-E IPMI Gigabit Ethernet Controller 4350 88E8036 Yukon PCI-E Fast Ethernet Controller - 4351 88E8039 Yukon PCI-E Fast Ethernet Controller + 4351 88E8038 Yukon PCI-E Fast Ethernet Controller 4352 88E8038 Marvell Yukon 88E8038 PCI-E Fast Ethernet Controller 4353 88E8039 - http://www.marvell.com/drivers/driverDis Gigabit 4354 88E8040 Marvell Yukon 88E8040 PCI-E Fast Ethernet Controller 4355 88E8040T Marvell Yukon 88E8040T PCI-E Fast Ethernet Controller 4356 Yukon 88EC033 PCI-E Fast Ethernet Controller 435A 88E8048 PCI-E Fast Ethernet Controller - 4360 88E8052 Yukon PCI-E ASF Gigabit Ethernet Controller + 4360 88E8050 Yukon PCI-E ASF Gigabit Ethernet Controller 4361 88E8036 Marvell Yukon -EC 88E8036 PCI Express Fast Ethernet Controller 4362 88E8053 Marvell Yukon 88E8053 PCI-E Gigabit Ethernet Controller 4363 88E8053 Yukon PCI-E Gigabit Ethernet Controller @@ -5539,17 +5587,19 @@ 6122 6122 SATA2 Controller 6140 6140 SATA2 Controller 6141 6141 SATA2 Controller - 6145 ? Add-on IC to provide 4x SATA Ports, attached to ICH7 (SthBridge?) via PCI-Express. + 6145 88SE6145 Add-on IC to provide 4x SATA Ports, attached to ICH7 (SthBridge?) via PCI-Express. 6320 GT-64130/131 System Controller for PowerPC Processors + 6440 ? 64xx/63xx SAS 6450 64560 System Controller 6460 MV64360/64361/64362 System Controller - 6480 MV6446x System Controller for PowerPC Processors + 6480 MV64460/64461/64462 System Controller 6485 MV6446x System Controller for PowerPC Processors, Revision B 7042 MV88SXxxxx Family 4-port SATA II PCIe Controller (??) 9653 GT-96100A Advanced Communication Controller F003 GT-64010 Primary Image Piranha Image Generator F004 GT-64120 Primary Image Barracuda Image Generator F006 GT-64120A Primary Image Cruncher Geometry Accelerator + FFFF 88SA8040 PATA2SATA/SATA2PATA Bridge 11AC Canon Information Systems 11AD Lite-On Communications Inc 0001 LC82C168 Fast Ethernet Adapter (??) @@ -5612,7 +5662,7 @@ 11BB Pyramid Technology/DAPHA Electronics Corp 11BC Network Peripherals Inc 0001 NPI NuCard PCI FDDI -11BD Pinnacle Systems Inc. +11BD Pinnacle Systems Inc 0015 FireWire IEEE1394 002E PCTV 40i 0040 Royal TS Function 1 @@ -5676,7 +5726,7 @@ 5803 USS-344 Quadrabus 4-port OpenHCI USB Host Controller 5805 uss344 USB Advanced Host Controller 5811 FW322 1394A PCI PHY/Link Open Host Ctrlr I/F - 5901 FW643 PCI Express1394b Controller (PHY/Link) + 5901 unknown firewire chip for macbook pro 8110 T8110 H.100/H.110 TDM switch 9876 lucent 1646T00 LT WinModem 56K Data+Fax AB10 WL60010 Wireless LAN MAC @@ -5729,7 +5779,7 @@ 1889 AD1980 Sound Chip 1981 AD1981HD SoundMAX Integrated Digital HD Audio 1983 AD1983HD SoundMAX Integrated Digital HD Audio - 1984 AD1984HD sound chip + 1984 Analog Devices ADI 198x Analog Devices ADI 198x Integrated HD Audio 1986 AD1986A SoundMAX Integrated Digital HD Audio 198B AD1988B AD1988B HD Audio CODEC 2192 ADSP-2192 DSP Microcomputer (function #0) @@ -5752,7 +5802,9 @@ 11DC Questra Corp 11DD Crosfield Electronics Ltd 11DE Zoran Corporation + 6017 miroVIDEO DC30 6057 ZR36057/36067 MotionJPEG/TV Card + 6067 zr36067pqc zoran 6120 ZR36120PQC MPEG VideoBVPSXI Capture Card 11DF New Wave PDG 11E0 Cray Communications A/S @@ -5919,6 +5971,7 @@ 71E2 OZ711E2 SmartCardBus Controller 7212 OZ711M2 SmartCardBus MultiMediaBay Controller 7213 OZ6933E CardBus Controller + 7222 unknow pci to pcmcia bridge 7223 OZ711M3 SmartCardBus MultiMediaBay Controller 7233 OZ711MP3/MS3 MemoryCardBus Controller 1218 Hybricon Corp @@ -6098,7 +6151,7 @@ 1968 ES2839 Maestro-2 PCI audio accelerator 1969 ES72222 Solo-1 PCI AudioDrive family 1978 ES1978 Maestro-2E Audiodrive, ES1970 Canyon3D - 1988 ES1988 ESS Allegro PCI Audio (WDM) + 1988 ES1989 ESS Allegro PCI Audio (WDM) 1989 ES1989 Allegro ES56CVM-PI PCI Voice+Fax Modem 1990 ES2898S 1998 ES1980 Maestro-3 PCI Audio Accelerator @@ -6339,7 +6392,7 @@ FFF3 MPG600/Kuroutoshikou ITVC16-STVLP FFFF MPG600/Kuroutoshikou ITVC16-STVLP 12AC MeasureX Corp. -12AD Multidata GmbH +12AD MULTIDATA GmbH 0010 1 HERMES-S0 0020 1 HERMES-PRI 0080 1 HERMES-PRI/PCIX @@ -6654,7 +6707,7 @@ 0003 9060 CompactPCI Interface 000D FPGA PCI Bridge 1311 VideoServer Inc -1312 Robotic Vision Systems Incorporated +1312 Microscan Systems Inc 1313 Yaskawa Electric Co. 1315 Wavesat 1316 Teradyne Inc. @@ -7218,11 +7271,11 @@ 0011 CMI8738 0100 CMI8338/C3DX PCI Audio Device 0101 CMI8338-031 PCI Audio Device - 0111 CMI8738/PCI C3DX C-Media Audio Controller + 0111 PCI\VEN_13F6&DEV_0111&SUBSYS_011113F6&REV_10\2&EBB C-Media Audio Controller 0112 CMI-8378B/PCI-6CH PCI Audio Chip 0211 CMI8738/PCI-SX HSP56 MICROMODEM 0300 0x4005 pci audio driver - 8788 CMI8788 [Oxygen HD Audio] + 8788 CMI8788/PCI-8CH C-Media Oxygen HD 9880 CM9880 13F7 Wildfire Communications 13F8 Ad Lib Multimedia Inc @@ -7596,6 +7649,7 @@ 1480 SCII Telecom 1481 Biopac Systems Inc 1482 Isytec - Integrierte Systemtechnik Gmbh + 0001 PCI-16 Host Interface for ITC-16 1483 Labway Coporation 1484 Logic Coporation 1485 Erma - Electronic GMBH @@ -7820,6 +7874,7 @@ 1639 NetXtreme II BCM5709 Gigabit Ethernet 163A NetXtreme II BCM5709S Gigabit Ethernet 163B NetXtreme II BCM5716 Gigabit Ethernet + 163C NetXtreme II BCM5716S Gigabit Ethernet 1644 BCM5700 NetXtreme Gigabit Ethernet Controller 1645 BCM5701 broadtcomBCM5701 Gigabit Ethernet 1646 BCM5702x1 NetXtreme Gigabit Ethernet @@ -7904,7 +7959,7 @@ 4311 BCM4311 Broadcom Corporation Dell Wireless 1390 WLAN Mini-PCI Card 4312 BCM4310 UART (Wireless Ethernet Adapter) 4313 BCM4310 usb controller, wireless network card - 4315 BCM4312 Broadcom Wireless + 4315 BCM2046 Broadcom Wireless 4318 BCM43XX Broadcom 802.11b/g 4319 Dell Wireless 1470 DualBand WLAN 431A 802.11a Network Adapter @@ -7994,7 +8049,7 @@ 14EE Maspro Kenkoh Corp 14EF Carry Computer Engineering Co Ltd 14F0 Canon Reseach Centre France -14F1 Conexant Systems, Inc. +14F1 Conexant Systems 1002 HCF 56k Modem 1003 HCF 56k Modem 1004 HCF 56k Modem @@ -8108,7 +8163,7 @@ 2F14 US Robotics 56K PCI Software Modem 2F15 US Robotics 56K Fax Host Int 2F20 CX11256 Software data fax modem with SmartCP - 2F30 01 hp/compaq alhena 5-gl6 + 2F30 01 Zyxel OMNI 56K PCI Plus Rev.3 2F40 71030277 Conexant Modem RD02-D490 2F50 Conexant SoftK56 Data/Fax Modem 2F82 cx9510-11z Conexant PCI-E Soft Data/Fax Modem with SmartCP @@ -8131,7 +8186,7 @@ 8803 CX2388x TV Capture Chip 8804 CX2388x TV Capture Chip 8811 CX2388x TV Capture Chip - 8852 0x7717 CX23881 + 8852 0x7717 CX23881-21 14F2 Mobility Electronics, Inc. 0001 Moselle Split Bridge 0002 Capilano Split Bridge @@ -8207,7 +8262,7 @@ 1519 Telefon Aktiebolaget LM Ericsson 2004 0x1 PCI Interface bus 151A Globetek Inc. - 1002 PCI-1002 4383 + 1002 PCI-1002 4370 1004 PCI-1004 1008 PCI-1008 151B Combox Ltd @@ -8375,6 +8430,7 @@ 1575 Voltaire Advanced Data Security Ltd 1576 Viewcast Com 1578 Hitt + 4D34 VPMK4 [Video Processor Mk IV] 5615 VPMK3 [Video Processor Mk III] 1579 Dual Technology Corporation 157A Japan Elecronics Ind. Inc @@ -8454,6 +8510,8 @@ 0740 Virtual Machine Communication Interface 0770 n/a Standard Enhanced PCI to USB Host Controller 0790 PCI bridge + 07B0 VMXNET3 Ethernet Adapter + 07C0 PVSCSI SCSI Controller 0801 Virtual Machine Interface 15AE Amersham Pharmacia Biotech 15B0 Zoltrix International Limited @@ -8583,7 +8641,7 @@ 15F6 Extreme Packet Device Inc 15F7 Banctec 15F8 Koga Electronics Co -15F9 Zenith Electronics Corporation +15F9 Zenith Electronics Corp 15FA Axzam Corporation 15FB Zilog Inc. 15FC Techsan Electronics Co Ltd @@ -8803,11 +8861,12 @@ 001C AR5006 family 802.11abg Wireless NIC 001D AR5007G Wireless Network Adapter 0020 AR5005VL 802.11bg Wireless NIC - 0023 AR5008 Wireless Network Adapter + 0023 AR5416 802.11a/b/g/n Wireless PCI Adapter 0024 AR5008 Atheros 802.11a/b/g/n (pre-N) radio 0027 AR9160 802.11abgn Wireless PCI Adapter 0029 AR922X Wireless Network Adapter 002A AR928X Wireless Network Adapter (PCI-Express) + 002B AR9285 Wireless Network Adapter (PCI-Express) 0033 11a/b/g/n Wireless LAN Mini-PCI Express Adapter 0207 AR5210 1014 AR5212 Atheros AR5212 802.11abg wireless @@ -8910,6 +8969,7 @@ 5602 PMC-VLX110 Reconfigurable Virtex-5 FPGA with plug-in I/O 5603 PMC-VSX95 Reconfigurable Virtex-5 FPGA with plug-in I/O 5604 PMC-VLX155 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5605 PMC-VFX70 Reconfigurable Virtex-5 FPGA with plug-in I/O 16D8 Omnicluster Technologies 16DA Marek Micro GmBH 0011 INES GPIB-PCI @@ -9004,6 +9064,7 @@ 1078 Amilo Pro v2010 1085 Celsius M450 1098 Amilo L 1310G + 10B9 0x00541000 SAS 3000 series, 8-port with 1068 -StorPort 1735 ATEN International Co Ltd 1737 LinkSys 0013 WMP54G Wireless Pci Card @@ -9141,6 +9202,7 @@ 179C Indus TeQ Site Pvt Ltd 0557 DP-PCI-557 [PCI 1553B] 0566 DP-PCI-566 [Intelligent PCI 1553B] + 1152 DP-cPCI-1152 (8–channel Isolated ADC Module) 5031 DP-CPCI-5031-Synchro Module 5121 DP-CPCI-5121-IP Carrier 5211 DP-CPCI-5211-IP Carrier @@ -9306,7 +9368,7 @@ 1810 HCL Technologies Ltd 1811 Wipro Technologies 1812 LANergy -1813 Ambient Technologies Inc. +1813 Ambient Technologies Inc 3059 VT8237 AC97 Enhanced Audio Controller - the 8251 controller is different 4000 MD5628D-L-A intel V.92 HaM Modem 4100 Ambient MD8820 Intel HaM V.92 Modem @@ -9321,6 +9383,7 @@ 0601 RT2800 802.11n PCI 0681 RT2860 Wireless 802.11n PCIe 0701 RT2760 Wireless 802.11n 1T/2R Cardbus + 0781 RT2860/RT2890 Wireless E932 RT2560F 802.11 b/g PCI 1815 devolo AG 1816 Pro Team Computer Corporation @@ -9521,6 +9584,7 @@ 0014 SuperFSCC 0015 SuperFSCC-104 0016 Fastcom FSCC-232 + 0017 SuperFSCC-104-NOUART 18FB Resilience Corporation 1904 Hangzhou Silan Microelectronics Co Ltd 2031 SC92031 PCI Fast Ethernet Adapter @@ -9550,6 +9614,7 @@ 193F Comtech AHA Corp. 0001 AHA36x-PCIX 0363 AHA363-PCIe + 0364 AHA364-PCIe 1942 ClearSpeed Technology plc E511 CSX600 Advance Accelerator Board E521 Advance e620 accelerator card @@ -9610,8 +9675,10 @@ 1966 Orad Hi-Tec Systems 1975 DVG64 family 1969 Attansic (Now owned by Atheros) - 1026 L1 Gigabit Ethernet Adapter + 1026 L1e Gigabit Ethernet Adapter 1048 L1 Gigabit Ethernet 10/100/1000Base-T Ethernet Controller + 1066 L2c Gigabit Ethernet Adapter + 1067 L1c Gigabit Ethernet Adapter 2048 L2 Fast Ethernet 10/100 Base-T Controller 196A Sensory Networks Inc 0101 NodalCore C-1000 Content Classification Accelerator @@ -9639,6 +9706,10 @@ 2382 SD/MMC Host Controller 2383 MS Host Controller 2384 xD Host Controller + 2386 Standard SD Host Controller + 2387 SD/MMC Host Controller + 2388 MS Host Controller + 2389 xD Host Controller 1982 Distant Early Warning Communications Inc 1600 OX16C954 HOST-A 16FF OX16C954 HOST-B @@ -9665,6 +9736,8 @@ 19DA ZOTAC International (MCO) Ltd. 19DE Pico Computing 19E2 Vector Informatik GmbH +19E3 DDRdrive LLC + DD52 DDRdrive X1 19E7 NET (Network Equipment Technologies) 1001 STIX DSP Card 1002 STIX - 1 Port T1/E1 Card @@ -9683,6 +9756,8 @@ 0000 SC15064 1A0E DekTec Digital Video B.V. 0069 DTA-105 +1A17 Force10 Networks, Inc. + 8002 PB-10GE-2P 10GbE Security Card 1A1D GFaI e.V. 1A17 Meta Networks MTP-1G IDPS NIC 1A1E 3Leaf Systems, Inc. @@ -9729,6 +9804,7 @@ 0A41 microEnable IV-FULL x1 0A44 microEnable IV-FULL x4 0E44 microEnable IV-GigE x4 +1AEC Wolfson Microelectronics 1AEE Caustic Graphics Inc. 1AF4 Qumranet, Inc. 1000 Virtio network device @@ -9738,8 +9814,12 @@ 1B13 Jaton Corporation USA 0001 GeForce4 MX 440 nVidia Corporation NV17 1B28 Taicom Data Systems Co Ltd +1B36 Red Hat, Inc. + 1000 Virtio network device + 1001 Virtio block device 1B3E Teradata Corp. 1FA8 BYNET BIC2SE/X +1B40 Schooner Information Technology, Inc. 1B47 Proxim(??) (Possibly Incorrect) 1B55 NetUP Inc. 2A2C Dual DVB-S2-CI card @@ -9903,6 +9983,10 @@ 004F ADM-XRC-4FX Virtex-II Pro PCI-X Bridge 0050 ADM-XRC-5LX Virtex-4LX Bridge 0051 ADM-XRC-5T1 ADM-XRC-5T1 +4150 ONA Electroerosion + 0001 PCI32TLITE FILSTRUP1 PCI to VME Bridge Controller + 0006 PCI32TLITE UART 16550 Opencores + 0007 PCI32TLITE CAN Controller Opencores 415A Auzentech, Inc. 416C Aladdin Knowledge Systems 0100 AlladinCARD @@ -9970,6 +10054,8 @@ 0B02 BU-65569I2 MIL-STD-1553 Data Bus 0B03 BU-65569I3 MIL-STD-1553 Data Bus 0B04 BU-65569I4 MIL-STD-1553 Data Bus +5045 University of Toronto + 4243 BLASTbus PCI Interface Card v1 5046 GemTek Technology corp 1001 PCI Radio 5053 TBS/Voyetra Technologies @@ -10020,7 +10106,7 @@ 88F2 86C968 Vision 968 GUI Accelerator VRAM rev. 2 88F3 86C968 Vision 968 GUI Accelerator VRAM rev. 3 8900 86C775 Trio64V2/DX - 8901 pci\ven_5333dev_8C2E&SUBSYS_00011179&REV_05\4&74C6 Trio64V2/DX-/GX Graphics Drivers + 8901 pci\ven_5333dev_8C2E&SUBSYS_00011179&REV_05\4&74C6 S3 trio64uv+ for windows xp 8902 86C551 SMA Family 8903 TrioV Family 8904 86C365 Trio3D QFP, 86C366 Trio3D BGA @@ -10173,6 +10259,7 @@ 0040 Auburndale/Havendale DRAM Controller 0041 Auburndale/Havendale PCI Express x16 Root Port 0042 Auburndale/Havendale Integrated Graphics Controller + 0050 Auburndale/Havendale Thermal Management Controller 0122 82437FX 430FX (Triton) System Controller 0309 80303 I/O Processor PCI-to-PCI Bridge Unit 030D 80312 I/O Companion Unit PCI-to-PCI Bridge @@ -10367,6 +10454,7 @@ 10C6 82598EB 10 Gigabit AF Dual Port Network Connection 10C7 82598EB 10 Gigabit AF Network Connection 10C8 82598EB 10 Gigabit AT Network Connection + 10C9 82576 Gigabit Network Connection 10CB 82567V Gigabit Network Connection 10CC 82567LM-2 Gigabit Network Connection 10CD 82567LF-2 Gigabit Network Connection @@ -10376,14 +10464,19 @@ 10D6 82575GB Gigabit Network Connection 10D9 82571EB Dual Port Gigabit Mezzanine Adapter 10DA 82571EB Quad Port Gigabit Mezzanine Adapter + 10DB 82598EB 10-Gigabit Dual Port Network Connection 10DD 82598EB 10 Gigabit AT CX4 Network Connection 10DE 82567LM-3 Gigabit Network Connection 10DF 82567LF-3 Gigabit Network Connection + 10E1 82598EB 10-Gigabit AT Dual Port Network Connection 10E2 82575GB Gigabit Network Connection 10E5 82567LM-4 Gigabit Network Connection - 10EC 10 Gigabit AT CX4 Network Connection - 10F4 10 Gigabit AT Network Connection - 10F5 82567LM Intel® 45 Express-Chipsatz + 10E6 82576 Gigabit Network Connection + 10E7 82576 Gigabit Network Connection + 10EC 82598EB 10-Gigabit AT CX4 Network Connection + 10F1 82598EB 10-Gigabit AT Dual Port Network Connection + 10F4 82598EB 10-Gigabit AT Network Connection + 10F5 82567LM Intel® 82567LM-2 Gigabit Network Connection 1100 82815 815/E (Solano) Host to I/O Hub Bridge with 100MHz DRAM Controller 1101 82815 815/E (Solano) PCI to AGP Bridge 1102 82815 815/E (Solano) Internal GUI Accelerator @@ -10405,7 +10498,7 @@ 1223 SAA 7116 H Video Controller 1225 82452KX/GX Orion Extended Express Processor to PCI Bridge 1226 82596 EtherExpress PRO/10 - 1227 82865g LAN Controller with 82562EM/EX PHY PCI + 1227 82801db ich4 LAN Controller with 82562EM/EX PHY PCI 1228 EE PRO/100 Smart Intelligent 10/100 Fast Ethernet Adapter 1229 82550/1/7/8/9 EtherExpress PRO/100(B) Ethernet Adapter 122D 82437FX 430FX (Triton) Cache/DRAM Controller @@ -10657,7 +10750,7 @@ 2662 82801FB/FR/FW/FRW PCI Express Port 2 2664 82801FB (ICH6) PCIe Root Port 3 2666 82801FB/FR/FW/FRW PCI Express Port 4 - 2668 11583659 Realtek High Definition Audio Controllers + 2668 11583659 82801FB (ICH6) High Definition Audio Controller 2669 2028026 jkn 266A 82801FB (ICH6) SMBus Controller 266C 82801FB/FR/FW/FRW LAN Controller @@ -10802,7 +10895,7 @@ 293B 82801IB/IR/IH (ICH9 Family) USB2 Enhanced Host Controller 293C 82801IB/IR/IH (ICH9 Family) USB2 Enhanced Host Controller 293D 82801IB/IR/IH (ICH9 Family) USB2 Enhanced Host Controller - 293E 486486 Microsoft UAA Bus Driver for High Definition Audio + 293E 486486 82801IB/IR/IH (ICH9 Family) HD Audio Controller 2940 82801IB/IR/IH (ICH9 Family) PCIe Root Port 1 2941 82801IB/IR/IH (ICH9 Family) PCIe Root Port 1 2942 82801IB/IR/IH (ICH9 Family) PCIe Root Port 2 @@ -10918,7 +11011,7 @@ 2C10 QuickPath Interconnect Link 0 2C11 QuickPath Interconnect Physical 0 2C14 QuickPath Interconnect Link 1 - 2C15 QPI Physical 1 + 2C15 Core i7 QPI Physical 1 2C18 QuickPath Memory Controller 2C19 QuickPath Memory Controller Target Address Decoder 2C1A QuickPath Memory Controller RAS Registers @@ -10936,6 +11029,7 @@ 2C32 QuickPath Memory Controller Channel 2 Rank Registers 2C33 QuickPath Memory Controller Channel 2 Thermal Control Registers 2C40 QuickPath Architecture Generic Non-Core Registers + 2C41 QuickPath Architecture Generic Non-Core Registers 2C50 QuickPath Architecture Generic Non-Core Registers 2C51 QuickPath Architecture Generic Non-Core Registers 2C52 QuickPath Architecture Generic Non-Core Registers @@ -11016,6 +11110,7 @@ 3341 82855PM Processor to AGP Controller 3342 82855PM Power Management 3363 IOC340 I/O Controller in IOC Mode SAS/SATA + 3382 81342 [Chevelon] I/O Processor (ATUe) 33C3 IOP348 I/O Processor (SL8De) in IOC Mode SAS/SATA 33CB IOP348 I/O Processor (SL8Dx) in IOC Mode SAS/SATA 3400 QuickPath Architecture I/O Hub to ESI Port @@ -11278,7 +11373,7 @@ 4229 Intel 4965AGN Intel® Wireless WiFi Link 4965AGN(supporting 802.11a/b/g/Draft-N) 422D Intel 4965AGN Intel® Wireless WiFi Link 4965AGN 4230 Intel 4965AGN Intel® Wireless WiFi Link 4965AGN - 4232 Wireless WiFi Link 5100 + 4232 unknown Intel® WiFi Link 5100 4233 Intel 4965AGN Intel® Wireless WiFi Link 4965AGN 4235 5300AGN Intel® WiFi Link 5300 AGN 4236 Wireless WiFi Link 5100 @@ -11406,7 +11501,7 @@ 7800 Intel740 AGP Graphics Accelerator 8002 Trusted Execution Technology 8003 Trusted Execution Technology Registers - 8086 park lsdurjlk + 8086 park55 lsdurjlk 8100 System Controller Hub (SCH Poulsbo) 8108 System Controller Hub (SCH Poulsbo) Graphics Controller 8110 System Controller Hub (SCH Poulsbo) PCI Express Port 1 @@ -11877,6 +11972,7 @@ EDD8 ARK Logic, Inc A0A1 Stingray 64 ARK2000MT 64-bit GUI W/DCI Playback A0A9 ARK2000MI Quadro645 GUI Accelerator A0B1 ARK2000MI+ GUI Accelerator +F05B Foxconn International, Inc. (Wrong ID) F1D0 AJA Video C0FE Xena HS/HD-R C0FF Kona/Xena 2 @@ -11887,6 +11983,7 @@ F1D0 AJA Video EFAC KONA SD SMPTE 259M I/O FACD KONA HD SMPTE 292M I/O F5F5 F5 Networks Inc. +F849 ASRock Incorporation (Wrong ID) FA57 Interagon AS (Was: Fast Search & Transfer ASA) 0001 PMC Pattern Matching Chip FAB7 Fabric7 Systems Inc @@ -11899,14 +11996,6 @@ FEDE Fedetec Inc FFFD XenSource Inc 0101 PCI Event Channel Controller FFFE VMWare Inc (Older Product Versions) - 0000 GESP 1.0 - 0002 GESP 1.0 - 0003 GESP 1.0 - 0004 GESP 1.1 - 0006 GESP 1.1 - 0007 GESP 1.1 - 0008 GESP 1.1 - 0009 GESP 1.1 0405 Virtual SVGA 4.0 0710 Virtual SVGA FFFF Illegal Vendor ID -- 2.41.0 From 5825b2265ea18876420a0aa5e62216a0592b0065 Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Thu, 1 Jan 2009 18:24:10 +0000 Subject: [PATCH 13/16] Refactor sys_jail() and fix bugs. Fixes two issues: * uap->sysmsg_result was not consistently assigned -1 in case of an error. * A version 0 syscall triggered a copyinstr(j.hostname, ...) on an uninitialized struct jail j. --- sys/kern/kern_jail.c | 170 +++++++++++++++++++++++++------------------ 1 file changed, 99 insertions(+), 71 deletions(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index b17f4290c4..15e94565da 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -122,6 +122,70 @@ kern_jail_attach(int jid) return(0); } +static int +assign_prison_id(struct prison *pr) +{ + int tryprid; + struct prison *tpr; + + tryprid = lastprid + 1; + if (tryprid == JAIL_MAX) + tryprid = 1; +next: + LIST_FOREACH(tpr, &allprison, pr_list) { + if (tpr->pr_id != tryprid) + continue; + tryprid++; + if (tryprid == JAIL_MAX) { + return (ERANGE); + } + goto next; + } + pr->pr_id = lastprid = tryprid; + + return (0); +} + +static int +kern_jail(struct prison *pr, struct jail *j) +{ + int error; + struct nlookupdata nd; + + error = nlookup_init(&nd, j->path, UIO_USERSPACE, NLC_FOLLOW); + if (error) { + nlookup_done(&nd); + return (error); + } + error = nlookup(&nd); + if (error) { + nlookup_done(&nd); + return (error); + } + cache_copy(&nd.nl_nch, &pr->pr_root); + + varsymset_init(&pr->pr_varsymset, NULL); + prison_ipcache_init(pr); + + error = assign_prison_id(pr); + if (error) { + varsymset_clean(&pr->pr_varsymset); + nlookup_done(&nd); + return (error); + } + + LIST_INSERT_HEAD(&allprison, pr, pr_list); + prisoncount++; + + error = kern_jail_attach(pr->pr_id); + if (error) { + LIST_REMOVE(pr, pr_list); + varsymset_clean(&pr->pr_varsymset); + } + nlookup_done(&nd); + return (error); +} + /* * jail() * @@ -130,45 +194,48 @@ kern_jail_attach(int jid) int sys_jail(struct jail_args *uap) { - struct prison *pr, *tpr; - struct jail j; - struct jail_v0 jv0; struct thread *td = curthread; - int error, tryprid, i; - uint32_t jversion; - struct nlookupdata nd; - /* Multiip */ - struct sockaddr_storage *uips; /* Userland ips */ - struct sockaddr_in ip4addr; + struct prison *pr; struct jail_ip_storage *jip; - /* Multiip */ + struct jail j; + int error; + uint32_t jversion; + + uap->sysmsg_result = -1; error = priv_check(td, PRIV_ROOT); - if (error) { - uap->sysmsg_result = -1; + if (error) return (error); - } + error = copyin(uap->jail, &jversion, sizeof(jversion)); - if (error) { - uap->sysmsg_result = -1; + if (error) return (error); - } + pr = kmalloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); SLIST_INIT(&pr->pr_ips); switch (jversion) { case 0: /* Single IPv4 jails. */ - + { + struct jail_v0 jv0; + struct sockaddr_in ip4addr; + error = copyin(uap->jail, &jv0, sizeof(jv0)); if (error) - goto bail; + goto out; + + j.path = jv0.path; + j.hostname = jv0.hostname; + jip = kmalloc(sizeof(*jip), M_PRISON, M_WAITOK | M_ZERO); ip4addr.sin_family = AF_INET; ip4addr.sin_addr.s_addr = htonl(jv0.ip_number); memcpy(&jip->ip, &ip4addr, sizeof(ip4addr)); SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries); break; + } + case 1: /* * DragonFly multi noIP/IPv4/IPv6 jails @@ -179,74 +246,35 @@ sys_jail(struct jail_args *uap) error = copyin(uap->jail, &j, sizeof(j)); if (error) - goto bail; - uips = kmalloc((sizeof(*uips) * j.n_ips), M_PRISON, - M_WAITOK | M_ZERO); - error = copyin(j.ips, uips, (sizeof(*uips) * j.n_ips)); - if (error) { - kfree(uips, M_PRISON); - goto bail; - } - for (i = 0; i < j.n_ips; i++) { - jip = kmalloc(sizeof(*jip), M_PRISON, + goto out; + + for (int i = 0; i < j.n_ips; i++) { + jip = kmalloc(sizeof(*jip), M_PRISON, M_WAITOK | M_ZERO); - memcpy(&jip->ip, &uips[i], sizeof(*uips)); SLIST_INSERT_HEAD(&pr->pr_ips, jip, entries); + error = copyin(&j.ips[i], &jip->ip, + sizeof(struct sockaddr_storage)); + if (error) + goto out; } - kfree(uips, M_PRISON); break; default: error = EINVAL; - goto bail; + goto out; } error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); if (error) - goto bail; - error = nlookup_init(&nd, j.path, UIO_USERSPACE, NLC_FOLLOW); - if (error) - goto nlookup_init_clean; - error = nlookup(&nd); - if (error) - goto nlookup_init_clean; - cache_copy(&nd.nl_nch, &pr->pr_root); + goto out; - varsymset_init(&pr->pr_varsymset, NULL); - prison_ipcache_init(pr); - - tryprid = lastprid + 1; - if (tryprid == JAIL_MAX) - tryprid = 1; -next: - LIST_FOREACH(tpr, &allprison, pr_list) { - if (tpr->pr_id != tryprid) - continue; - tryprid++; - if (tryprid == JAIL_MAX) { - error = ERANGE; - goto varsym_clean; - } - goto next; - } - pr->pr_id = lastprid = tryprid; - LIST_INSERT_HEAD(&allprison, pr, pr_list); - prisoncount++; - - error = kern_jail_attach(pr->pr_id); + error = kern_jail(pr, &j); if (error) - goto jail_attach_clean; + goto out; - nlookup_done(&nd); uap->sysmsg_result = pr->pr_id; return (0); -jail_attach_clean: - LIST_REMOVE(pr, pr_list); -varsym_clean: - varsymset_clean(&pr->pr_varsymset); -nlookup_init_clean: - nlookup_done(&nd); -bail: +out: /* Delete all ips */ while (!SLIST_EMPTY(&pr->pr_ips)) { jip = SLIST_FIRST(&pr->pr_ips); @@ -254,7 +282,7 @@ bail: kfree(jip, M_PRISON); } kfree(pr, M_PRISON); - return(error); + return (error); } /* -- 2.41.0 From dcea93a000b5b7ae9ff06da9ab2c770df938a54f Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Thu, 1 Jan 2009 20:05:12 +0100 Subject: [PATCH 14/16] Some fixes related to the HAMMER support in the installer. * Add HAMMER related command names to the correct cmdnames.conf and remove the one in contrib/ to avoid future confusion. * Fix array initialization. * Improve wording a bit. --- .../src/backend/installer/conf/cmdnames.conf | 107 ------------------ .../src/backend/installer/flow.c | 4 +- .../src/backend/installer/fn_subpart_hammer.c | 2 +- share/installer/cmdnames.conf | 5 + 4 files changed, 8 insertions(+), 110 deletions(-) delete mode 100644 contrib/bsdinstaller-1.1.6/src/backend/installer/conf/cmdnames.conf diff --git a/contrib/bsdinstaller-1.1.6/src/backend/installer/conf/cmdnames.conf b/contrib/bsdinstaller-1.1.6/src/backend/installer/conf/cmdnames.conf deleted file mode 100644 index 758b31749e..0000000000 --- a/contrib/bsdinstaller-1.1.6/src/backend/installer/conf/cmdnames.conf +++ /dev/null @@ -1,107 +0,0 @@ -# Command names for DragonFly installer backend. -# $Id: cmdnames.conf,v 1.15 2005/04/08 02:29:17 cpressey Exp $ - -# This is in Bourne shell syntax so that it is easily editable; -# it is also sourced by the installer, a C program. - -# Note that file names here should all be relative to the -# installation media. They should NOT include leading slashes. -# They may contain extra command-line options. - -SH=bin/sh -MKDIR=bin/mkdir -CHMOD=bin/chmod -LN=bin/ln -RM=bin/rm -CP=bin/cp -DATE=bin/date -ECHO=bin/echo -DD=bin/dd -MV=bin/mv -CAT=bin/cat -TEST=bin/test - -# XXX 'sysctl' and '[' in the following tests should ideally include -# the full path to the executable. - -# Some operating systems (OpenBSD) have block devices for disks, slices, etc. -# Others don't. - -if [ X`sysctl -n kern.ostype` = "XOpenBSD" ]; then - TEST_DEV="$TEST -b" -else - TEST_DEV="$TEST -c" -fi - -# Some operating systems (DragonFly) have a version of cpdup that supports -u. -# Others don't, and we assume it is installed as a 'port' on those systems. - -if [ X`sysctl -n kern.ostype` = "XDragonFly" ]; then - CPDUP="bin/cpdup -o -vvv -u" - DHCPD=usr/sbin/dhcpd - RPCBIND=usr/sbin/portmap - MOUNTD=sbin/mountd - NFSD=sbin/nfsd -else - CPDUP="usr/local/bin/cpdup -o -vvv" - DHCPD=usr/local/sbin/dhcpd - RPCBIND=usr/sbin/rpcbind - MOUNTD=usr/sbin/mountd - NFSD=usr/sbin/nfsd -fi - -MOUNT=sbin/mount -MOUNT_HAMMER=sbin/mount_hammer -MOUNT_NULL=sbin/mount_null -MOUNT_MFS=sbin/mount_mfs -UMOUNT=sbin/umount -SWAPON=sbin/swapon -DISKLABEL=sbin/disklabel -DISKLABEL64=sbin/disklabel64 -HAMMER=sbin/hammer -NEWFS=sbin/newfs -NEWFS_HAMMER=sbin/newfs_hammer -NEWFS_MSDOS=sbin/newfs_msdos -FDISK=sbin/fdisk -DUMPON=sbin/dumpon -IFCONFIG=sbin/ifconfig -ROUTE=sbin/route -DHCLIENT=sbin/dhclient -SYSCTL=sbin/sysctl - -TOUCH=usr/bin/touch -YES=usr/bin/yes -BUNZIP2=usr/bin/bunzip2 -GREP=usr/bin/grep -KILLALL=usr/bin/killall -BASENAME=usr/bin/basename -SORT=usr/bin/sort -COMM=usr/bin/comm -AWK=usr/bin/awk -SED=usr/bin/sed -BC=usr/bin/bc -TR=usr/bin/tr - -PWD_MKDB=usr/sbin/pwd_mkdb -CHROOT=usr/sbin/chroot -VIDCONTROL=usr/sbin/vidcontrol -KBDCONTROL=usr/sbin/kbdcontrol -PW=usr/sbin/pw -SWAPINFO=usr/sbin/swapinfo -BOOT0CFG=usr/sbin/boot0cfg -FDFORMAT=usr/sbin/fdformat -PKG_ADD=usr/sbin/pkg_add -PKG_DELETE=usr/sbin/pkg_delete -PKG_CREATE=usr/sbin/pkg_create -PKG_INFO=usr/sbin/pkg_info -INETD=usr/sbin/inetd - -TFTPD=usr/libexec/tftpd - -CVSUP=usr/local/bin/cvsup -MEMTEST=usr/local/bin/memtest - -# These aren't commands, but they're configurable here nonetheless. - -DMESG_BOOT=var/run/dmesg.boot -INSTALLER_TEMP="/tmp/" diff --git a/contrib/bsdinstaller-1.1.6/src/backend/installer/flow.c b/contrib/bsdinstaller-1.1.6/src/backend/installer/flow.c index 0691bb2dfa..95a1cebf65 100644 --- a/contrib/bsdinstaller-1.1.6/src/backend/installer/flow.c +++ b/contrib/bsdinstaller-1.1.6/src/backend/installer/flow.c @@ -986,8 +986,8 @@ state_ask_fs(struct i_fn_args *a) switch (dfui_be_present_dialog(a->c, _("Select file system"), _("Use HAMMER|Use UFS|Return to Select Disk"), - _("Please select the file system you want to use with %s\n\n" - "HAMMER is the new %s file system. UFS the traditional BSD file system"), + _("Please select the file system you want to use with %s.\n\n" + "HAMMER is the new %s file system. UFS is the traditional BSD file system."), OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME)) { diff --git a/contrib/bsdinstaller-1.1.6/src/backend/installer/fn_subpart_hammer.c b/contrib/bsdinstaller-1.1.6/src/backend/installer/fn_subpart_hammer.c index 1cd411e660..320478be59 100644 --- a/contrib/bsdinstaller-1.1.6/src/backend/installer/fn_subpart_hammer.c +++ b/contrib/bsdinstaller-1.1.6/src/backend/installer/fn_subpart_hammer.c @@ -76,7 +76,7 @@ static struct dfui_form *make_create_subpartitions_form(struct i_fn_args *); static int show_create_subpartitions_form(struct dfui_form *, struct i_fn_args *); static const char *def_mountpt[7] = {"/", "swap", "/var", "/tmp", "/usr", "/home", NULL}; -static long def_capacity[7] = {-1, 128, 128, 128, 128, 256, 128, 0}; +static long def_capacity[7] = {-1, 128, 128, 128, 256, 128, 0}; static int expert = 0; diff --git a/share/installer/cmdnames.conf b/share/installer/cmdnames.conf index b6bce06a38..f48bebfcd6 100644 --- a/share/installer/cmdnames.conf +++ b/share/installer/cmdnames.conf @@ -52,11 +52,16 @@ else fi MOUNT=sbin/mount +MOUNT_HAMMER=sbin/mount_hammer MOUNT_MFS=sbin/mount_mfs +MOUNT_NULL=sbin/mount_null UMOUNT=sbin/umount SWAPON=sbin/swapon DISKLABEL=sbin/disklabel +DISKLABEL64=sbin/disklabel64 +HAMMER=sbin/hammer NEWFS=sbin/newfs +NEWFS_HAMMER=sbin/newfs_hammer NEWFS_MSDOS=sbin/newfs_msdos FDISK=sbin/fdisk DUMPON=sbin/dumpon -- 2.41.0 From 5cb5194da153cf9dab3ae963229583a4a161b635 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Thu, 1 Jan 2009 23:42:55 +0100 Subject: [PATCH 15/16] Handle 'hammer cleanup' using the output of mount instead of df. This fixes hammer(8) trying to cleanup null mounts which are not HAMMER related. --- sbin/hammer/cmd_cleanup.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/sbin/hammer/cmd_cleanup.c b/sbin/hammer/cmd_cleanup.c index ef4e448eef..8cc13f968b 100644 --- a/sbin/hammer/cmd_cleanup.c +++ b/sbin/hammer/cmd_cleanup.c @@ -92,32 +92,31 @@ void hammer_cmd_cleanup(char **av, int ac) { FILE *fp; - char *ptr; - char *path; + char *fs, *ptr, *path; char buf[256]; tzset(); if (ac == 0) { - fp = popen("df -t hammer,null", "r"); + fp = popen("mount -t hammer,null", "r"); if (fp == NULL) - errx(1, "hammer cleanup: 'df' failed"); + errx(1, "hammer cleanup: 'mount' failed"); while (fgets(buf, sizeof(buf), fp) != NULL) { - ptr = strtok(buf, WS); - if (ptr && strcmp(ptr, "Filesystem") == 0) + fs = strtok(buf, WS); + if (fs == NULL) continue; - if (ptr) - ptr = strtok(NULL, WS); - if (ptr) - ptr = strtok(NULL, WS); - if (ptr) - ptr = strtok(NULL, WS); - if (ptr) - ptr = strtok(NULL, WS); - if (ptr) { - path = strtok(NULL, WS); - if (path) - do_cleanup(path); - } + ptr = strtok(NULL, WS); + if (ptr == NULL) + continue; + path = strtok(NULL, WS); + if (path == NULL) + continue; + ptr = strtok(NULL, WS); + if (ptr == NULL) + continue; + if ((strncmp(ptr, "(hammer,", 8) == 0) || + ((strncmp(ptr, "(null,", 6) == 0) && + (strncmp(fs, "/pfs", 4) == 0))) + do_cleanup(path); } fclose(fp); } else { -- 2.41.0 From de5fa51db91ef4d0f59cec7af8553b7342af842d Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sun, 28 Dec 2008 14:21:45 -0500 Subject: [PATCH 16/16] Add a pam_chroot(8) module. Also, let's make pam_module/Makefile a little easier to deal with. Obtained-from: FreeBSD --- lib/pam_module/Makefile | 16 +++- lib/pam_module/pam_chroot/Makefile | 7 ++ lib/pam_module/pam_chroot/pam_chroot.8 | 94 +++++++++++++++++++++ lib/pam_module/pam_chroot/pam_chroot.c | 108 +++++++++++++++++++++++++ 4 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 lib/pam_module/pam_chroot/Makefile create mode 100644 lib/pam_module/pam_chroot/pam_chroot.8 create mode 100644 lib/pam_module/pam_chroot/pam_chroot.c diff --git a/lib/pam_module/Makefile b/lib/pam_module/Makefile index 67c2ea6a12..e5b94c67c0 100644 --- a/lib/pam_module/Makefile +++ b/lib/pam_module/Makefile @@ -1,9 +1,19 @@ # $DragonFly: src/lib/pam_module/Makefile,v 1.4 2008/01/02 17:41:30 matthias Exp $ -SUBDIR= pam_cleartext_pass_ok pam_deny pam_nologin pam_opie pam_opieaccess -SUBDIR+= pam_permit pam_radius pam_ssh pam_tacplus pam_unix +SUBDIR= pam_chroot \ + pam_cleartext_pass_ok \ + pam_deny \ + pam_nologin \ + pam_opie \ + pam_opieaccess \ + pam_permit \ + pam_radius \ + pam_ssh \ + pam_tacplus \ + pam_unix + .if defined(WANT_KERBEROS) && !defined(NO_CRYPT) && !defined(NO_OPENSSL) -SUBDIR+= pam_krb5 +SUBDIR+=pam_krb5 .endif .include diff --git a/lib/pam_module/pam_chroot/Makefile b/lib/pam_module/pam_chroot/Makefile new file mode 100644 index 0000000000..018d7a7e26 --- /dev/null +++ b/lib/pam_module/pam_chroot/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD: src/lib/libpam/modules/pam_chroot/Makefile,v 1.1 2003/03/30 22:58:23 des Exp $ + +LIB= pam_chroot +SRCS= pam_chroot.c +MAN= pam_chroot.8 + +.include diff --git a/lib/pam_module/pam_chroot/pam_chroot.8 b/lib/pam_module/pam_chroot/pam_chroot.8 new file mode 100644 index 0000000000..08cf1c6188 --- /dev/null +++ b/lib/pam_module/pam_chroot/pam_chroot.8 @@ -0,0 +1,94 @@ +.\" Copyright (c) 2003 Networks Associates Technology, Inc. +.\" All rights reserved. +.\" +.\" Portions of this software were developed for the FreeBSD Project by +.\" ThinkSec AS and NAI Labs, the Security Research Division of Network +.\" Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 +.\" ("CBOSS"), as part of the DARPA CHATS research program. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote +.\" products derived from this software without specific prior written +.\" permission. +.\" +.\" 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: src/lib/libpam/modules/pam_chroot/pam_chroot.8,v 1.4 2004/07/02 23:52:16 ru Exp $ +.\" +.Dd February 10, 2003 +.Dt PAM_CHROOT 8 +.Os +.Sh NAME +.Nm pam_chroot +.Nd Chroot PAM module +.Sh SYNOPSIS +.Op Ar service-name +.Ar module-type +.Ar control-flag +.Pa pam_chroot +.Op Ar arguments +.Sh DESCRIPTION +The chroot service module for PAM chroots users into either a +predetermined directory or one derived from their home directory. +If a user's home directory as specified in the +.Vt passwd +structure returned by +.Xr getpwnam 3 +contains the string +.Dq Li /./ , +the portion of the directory name to the left of that string is used +as the chroot directory, and the portion to the right will be the +current working directory inside the chroot tree. +Otherwise, the directories specified by the +.Cm dir +and +.Cm cwd +options (see below) are used. +.Bl -tag -width ".Cm also_root" +.It Cm also_root +Do not hold user ID 0 exempt from the chroot requirement. +.It Cm always +Report a failure if a chroot directory could not be derived from the +user's home directory, and the +.Cm dir +option was not specified. +.It Cm cwd Ns = Ns Ar directory +Specify the directory to +.Xr chdir 2 +into after a successful +.Xr chroot 2 +call. +.It Cm dir Ns = Ns Ar directory +Specify the chroot directory to use if one could not be derived from +the user's home directory. +.El +.Sh SEE ALSO +.Xr pam.conf 5 , +.Xr pam 8 +.Sh AUTHORS +The +.Nm +module and this manual page were developed for the +.Fx +Project by +ThinkSec AS and NAI Labs, the Security Research Division of Network +Associates, Inc.\& under DARPA/SPAWAR contract N66001-01-C-8035 +.Pq Dq CBOSS , +as part of the DARPA CHATS research program. diff --git a/lib/pam_module/pam_chroot/pam_chroot.c b/lib/pam_module/pam_chroot/pam_chroot.c new file mode 100644 index 0000000000..512a8fb5e7 --- /dev/null +++ b/lib/pam_module/pam_chroot/pam_chroot.c @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 2003 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by ThinkSec AS and + * NAI Labs, the Security Research Division of Network Associates, Inc. + * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the + * DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * 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: src/lib/libpam/modules/pam_chroot/pam_chroot.c,v 1.3 2003/04/30 00:40:24 des Exp $ + */ + +#include + +#include +#include +#include +#include + +#define PAM_SM_SESSION + +#include +#include +#include + +PAM_EXTERN int +pam_sm_open_session(pam_handle_t *pamh, int flags __unused, + int argc __unused, const char *argv[] __unused) +{ + const char *dir, *end, *cwd, *user; + struct passwd *pwd; + char buf[PATH_MAX]; + + if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || + user == NULL || (pwd = getpwnam(user)) == NULL) + return (PAM_SESSION_ERR); + if (pwd->pw_uid == 0 && !openpam_get_option(pamh, "also_root")) + return (PAM_SUCCESS); + if (pwd->pw_dir == NULL) + return (PAM_SESSION_ERR); + if ((end = strstr(pwd->pw_dir, "/./")) != NULL) { + if (snprintf(buf, sizeof(buf), "%.*s", + (int)(end - pwd->pw_dir), pwd->pw_dir) > (int)sizeof(buf)) { + openpam_log(PAM_LOG_ERROR, + "%s's home directory is too long", user); + return (PAM_SESSION_ERR); + } + dir = buf; + cwd = end + 2; + } else if ((dir = openpam_get_option(pamh, "dir")) != NULL) { + if ((cwd = openpam_get_option(pamh, "cwd")) == NULL) + cwd = "/"; + } else { + if (openpam_get_option(pamh, "always")) { + openpam_log(PAM_LOG_ERROR, + "%s has no chroot directory", user); + return (PAM_SESSION_ERR); + } + return (PAM_SUCCESS); + } + + openpam_log(PAM_LOG_DEBUG, "chrooting %s to %s", dir, user); + + if (chroot(dir) == -1) { + openpam_log(PAM_LOG_ERROR, "chroot(): %m"); + return (PAM_SESSION_ERR); + } + if (chdir(cwd) == -1) { + openpam_log(PAM_LOG_ERROR, "chdir(): %m"); + return (PAM_SESSION_ERR); + } + pam_setenv(pamh, "HOME", cwd, 1); + return (PAM_SUCCESS); +} + +PAM_EXTERN int +pam_sm_close_session(pam_handle_t *pamh __unused, int flags __unused, + int argc __unused, const char *argv[] __unused) +{ + + return (PAM_SUCCESS); +} + +PAM_MODULE_ENTRY("pam_chroot"); -- 2.41.0