summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2005-10-18 06:10:03 +0000
committerimp <imp@FreeBSD.org>2005-10-18 06:10:03 +0000
commit76e76faeb15cbd90e274a75211ed30cb7b7aa3ef (patch)
treea77304cc85e9cd895075d12b0de41fc4233903e6
parente4a2a89b0fe921cadf5b798c8a2f10cab992adcb (diff)
downloadFreeBSD-src-76e76faeb15cbd90e274a75211ed30cb7b7aa3ef.zip
FreeBSD-src-76e76faeb15cbd90e274a75211ed30cb7b7aa3ef.tar.gz
Remove dc after repo copy.
-rw-r--r--sys/pci/if_dc.c3863
-rw-r--r--sys/pci/if_dcreg.h1225
2 files changed, 0 insertions, 5088 deletions
diff --git a/sys/pci/if_dc.c b/sys/pci/if_dc.c
deleted file mode 100644
index caaa7e6..0000000
--- a/sys/pci/if_dc.c
+++ /dev/null
@@ -1,3863 +0,0 @@
-/*-
- * Copyright (c) 1997, 1998, 1999
- * Bill Paul <wpaul@ee.columbia.edu>. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Bill Paul.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * DEC "tulip" clone ethernet driver. Supports the DEC/Intel 21143
- * series chips and several workalikes including the following:
- *
- * Macronix 98713/98715/98725/98727/98732 PMAC (www.macronix.com)
- * Macronix/Lite-On 82c115 PNIC II (www.macronix.com)
- * Lite-On 82c168/82c169 PNIC (www.litecom.com)
- * ASIX Electronics AX88140A (www.asix.com.tw)
- * ASIX Electronics AX88141 (www.asix.com.tw)
- * ADMtek AL981 (www.admtek.com.tw)
- * ADMtek AN985 (www.admtek.com.tw)
- * Netgear FA511 (www.netgear.com) Appears to be rebadged ADMTek AN985
- * Davicom DM9100, DM9102, DM9102A (www.davicom8.com)
- * Accton EN1217 (www.accton.com)
- * Xircom X3201 (www.xircom.com)
- * Abocom FE2500
- * Conexant LANfinity (www.conexant.com)
- * 3Com OfficeConnect 10/100B 3CSOHO100B (www.3com.com)
- *
- * Datasheets for the 21143 are available at developer.intel.com.
- * Datasheets for the clone parts can be found at their respective sites.
- * (Except for the PNIC; see www.freebsd.org/~wpaul/PNIC/pnic.ps.gz.)
- * The PNIC II is essentially a Macronix 98715A chip; the only difference
- * worth noting is that its multicast hash table is only 128 bits wide
- * instead of 512.
- *
- * Written by Bill Paul <wpaul@ee.columbia.edu>
- * Electrical Engineering Department
- * Columbia University, New York City
- */
-/*
- * The Intel 21143 is the successor to the DEC 21140. It is basically
- * the same as the 21140 but with a few new features. The 21143 supports
- * three kinds of media attachments:
- *
- * o MII port, for 10Mbps and 100Mbps support and NWAY
- * autonegotiation provided by an external PHY.
- * o SYM port, for symbol mode 100Mbps support.
- * o 10baseT port.
- * o AUI/BNC port.
- *
- * The 100Mbps SYM port and 10baseT port can be used together in
- * combination with the internal NWAY support to create a 10/100
- * autosensing configuration.
- *
- * Note that not all tulip workalikes are handled in this driver: we only
- * deal with those which are relatively well behaved. The Winbond is
- * handled separately due to its different register offsets and the
- * special handling needed for its various bugs. The PNIC is handled
- * here, but I'm not thrilled about it.
- *
- * All of the workalike chips use some form of MII transceiver support
- * with the exception of the Macronix chips, which also have a SYM port.
- * The ASIX AX88140A is also documented to have a SYM port, but all
- * the cards I've seen use an MII transceiver, probably because the
- * AX88140A doesn't support internal NWAY.
- */
-
-#ifdef HAVE_KERNEL_OPTION_HEADERS
-#include "opt_device_polling.h"
-#endif
-
-#include <sys/param.h>
-#include <sys/endian.h>
-#include <sys/systm.h>
-#include <sys/sockio.h>
-#include <sys/mbuf.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <net/ethernet.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-#include <net/if_vlan_var.h>
-
-#include <net/bpf.h>
-
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-
-#include <dev/mii/mii.h>
-#include <dev/mii/miivar.h>
-
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-
-#define DC_USEIOSPACE
-#ifdef __alpha__
-#define SRM_MEDIA
-#endif
-
-#include <pci/if_dcreg.h>
-
-#ifdef __sparc64__
-#include <dev/ofw/openfirm.h>
-#include <machine/ofw_machdep.h>
-#endif
-
-MODULE_DEPEND(dc, pci, 1, 1, 1);
-MODULE_DEPEND(dc, ether, 1, 1, 1);
-MODULE_DEPEND(dc, miibus, 1, 1, 1);
-
-/*
- * "device miibus" is required in kernel config. See GENERIC if you get
- * errors here.
- */
-#include "miibus_if.h"
-
-/*
- * Various supported device vendors/types and their names.
- */
-static struct dc_type dc_devs[] = {
- { DC_VENDORID_DEC, DC_DEVICEID_21143,
- "Intel 21143 10/100BaseTX" },
- { DC_VENDORID_DAVICOM, DC_DEVICEID_DM9009,
- "Davicom DM9009 10/100BaseTX" },
- { DC_VENDORID_DAVICOM, DC_DEVICEID_DM9100,
- "Davicom DM9100 10/100BaseTX" },
- { DC_VENDORID_DAVICOM, DC_DEVICEID_DM9102,
- "Davicom DM9102 10/100BaseTX" },
- { DC_VENDORID_DAVICOM, DC_DEVICEID_DM9102,
- "Davicom DM9102A 10/100BaseTX" },
- { DC_VENDORID_ADMTEK, DC_DEVICEID_AL981,
- "ADMtek AL981 10/100BaseTX" },
- { DC_VENDORID_ADMTEK, DC_DEVICEID_AN985,
- "ADMtek AN985 10/100BaseTX" },
- { DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9511,
- "ADMtek ADM9511 10/100BaseTX" },
- { DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9513,
- "ADMtek ADM9513 10/100BaseTX" },
- { DC_VENDORID_ADMTEK, DC_DEVICEID_FA511,
- "Netgear FA511 10/100BaseTX" },
- { DC_VENDORID_ASIX, DC_DEVICEID_AX88140A,
- "ASIX AX88140A 10/100BaseTX" },
- { DC_VENDORID_ASIX, DC_DEVICEID_AX88140A,
- "ASIX AX88141 10/100BaseTX" },
- { DC_VENDORID_MX, DC_DEVICEID_98713,
- "Macronix 98713 10/100BaseTX" },
- { DC_VENDORID_MX, DC_DEVICEID_98713,
- "Macronix 98713A 10/100BaseTX" },
- { DC_VENDORID_CP, DC_DEVICEID_98713_CP,
- "Compex RL100-TX 10/100BaseTX" },
- { DC_VENDORID_CP, DC_DEVICEID_98713_CP,
- "Compex RL100-TX 10/100BaseTX" },
- { DC_VENDORID_MX, DC_DEVICEID_987x5,
- "Macronix 98715/98715A 10/100BaseTX" },
- { DC_VENDORID_MX, DC_DEVICEID_987x5,
- "Macronix 98715AEC-C 10/100BaseTX" },
- { DC_VENDORID_MX, DC_DEVICEID_987x5,
- "Macronix 98725 10/100BaseTX" },
- { DC_VENDORID_MX, DC_DEVICEID_98727,
- "Macronix 98727/98732 10/100BaseTX" },
- { DC_VENDORID_LO, DC_DEVICEID_82C115,
- "LC82C115 PNIC II 10/100BaseTX" },
- { DC_VENDORID_LO, DC_DEVICEID_82C168,
- "82c168 PNIC 10/100BaseTX" },
- { DC_VENDORID_LO, DC_DEVICEID_82C168,
- "82c169 PNIC 10/100BaseTX" },
- { DC_VENDORID_ACCTON, DC_DEVICEID_EN1217,
- "Accton EN1217 10/100BaseTX" },
- { DC_VENDORID_ACCTON, DC_DEVICEID_EN2242,
- "Accton EN2242 MiniPCI 10/100BaseTX" },
- { DC_VENDORID_XIRCOM, DC_DEVICEID_X3201,
- "Xircom X3201 10/100BaseTX" },
- { DC_VENDORID_ABOCOM, DC_DEVICEID_FE2500,
- "Abocom FE2500 10/100BaseTX" },
- { DC_VENDORID_ABOCOM, DC_DEVICEID_FE2500MX,
- "Abocom FE2500MX 10/100BaseTX" },
- { DC_VENDORID_CONEXANT, DC_DEVICEID_RS7112,
- "Conexant LANfinity MiniPCI 10/100BaseTX" },
- { DC_VENDORID_HAWKING, DC_DEVICEID_HAWKING_PN672TX,
- "Hawking CB102 CardBus 10/100" },
- { DC_VENDORID_PLANEX, DC_DEVICEID_FNW3602T,
- "PlaneX FNW-3602-T CardBus 10/100" },
- { DC_VENDORID_3COM, DC_DEVICEID_3CSOHOB,
- "3Com OfficeConnect 10/100B" },
- { DC_VENDORID_MICROSOFT, DC_DEVICEID_MSMN120,
- "Microsoft MN-120 CardBus 10/100" },
- { DC_VENDORID_MICROSOFT, DC_DEVICEID_MSMN130,
- "Microsoft MN-130 10/100" },
- { DC_VENDORID_MICROSOFT, DC_DEVICEID_MSMN130_FAKE,
- "Microsoft MN-130 10/100" },
- { 0, 0, NULL }
-};
-
-static int dc_probe(device_t);
-static int dc_attach(device_t);
-static int dc_detach(device_t);
-static int dc_suspend(device_t);
-static int dc_resume(device_t);
-static struct dc_type *dc_devtype(device_t);
-static int dc_newbuf(struct dc_softc *, int, int);
-static int dc_encap(struct dc_softc *, struct mbuf **);
-static void dc_pnic_rx_bug_war(struct dc_softc *, int);
-static int dc_rx_resync(struct dc_softc *);
-static void dc_rxeof(struct dc_softc *);
-static void dc_txeof(struct dc_softc *);
-static void dc_tick(void *);
-static void dc_tx_underrun(struct dc_softc *);
-static void dc_intr(void *);
-static void dc_start(struct ifnet *);
-static void dc_start_locked(struct ifnet *);
-static int dc_ioctl(struct ifnet *, u_long, caddr_t);
-static void dc_init(void *);
-static void dc_init_locked(struct dc_softc *);
-static void dc_stop(struct dc_softc *);
-static void dc_watchdog(struct ifnet *);
-static void dc_shutdown(device_t);
-static int dc_ifmedia_upd(struct ifnet *);
-static void dc_ifmedia_sts(struct ifnet *, struct ifmediareq *);
-
-static void dc_delay(struct dc_softc *);
-static void dc_eeprom_idle(struct dc_softc *);
-static void dc_eeprom_putbyte(struct dc_softc *, int);
-static void dc_eeprom_getword(struct dc_softc *, int, u_int16_t *);
-static void dc_eeprom_getword_pnic(struct dc_softc *, int, u_int16_t *);
-static void dc_eeprom_getword_xircom(struct dc_softc *, int, u_int16_t *);
-static void dc_eeprom_width(struct dc_softc *);
-static void dc_read_eeprom(struct dc_softc *, caddr_t, int, int, int);
-
-static void dc_mii_writebit(struct dc_softc *, int);
-static int dc_mii_readbit(struct dc_softc *);
-static void dc_mii_sync(struct dc_softc *);
-static void dc_mii_send(struct dc_softc *, u_int32_t, int);
-static int dc_mii_readreg(struct dc_softc *, struct dc_mii_frame *);
-static int dc_mii_writereg(struct dc_softc *, struct dc_mii_frame *);
-static int dc_miibus_readreg(device_t, int, int);
-static int dc_miibus_writereg(device_t, int, int, int);
-static void dc_miibus_statchg(device_t);
-static void dc_miibus_mediainit(device_t);
-
-static void dc_setcfg(struct dc_softc *, int);
-static uint32_t dc_mchash_le(struct dc_softc *, const uint8_t *);
-static uint32_t dc_mchash_be(const uint8_t *);
-static void dc_setfilt_21143(struct dc_softc *);
-static void dc_setfilt_asix(struct dc_softc *);
-static void dc_setfilt_admtek(struct dc_softc *);
-static void dc_setfilt_xircom(struct dc_softc *);
-
-static void dc_setfilt(struct dc_softc *);
-
-static void dc_reset(struct dc_softc *);
-static int dc_list_rx_init(struct dc_softc *);
-static int dc_list_tx_init(struct dc_softc *);
-
-static void dc_read_srom(struct dc_softc *, int);
-static void dc_parse_21143_srom(struct dc_softc *);
-static void dc_decode_leaf_sia(struct dc_softc *, struct dc_eblock_sia *);
-static void dc_decode_leaf_mii(struct dc_softc *, struct dc_eblock_mii *);
-static void dc_decode_leaf_sym(struct dc_softc *, struct dc_eblock_sym *);
-static void dc_apply_fixup(struct dc_softc *, int);
-
-static void dc_dma_map_txbuf(void *, bus_dma_segment_t *, int, bus_size_t, int);
-static void dc_dma_map_rxbuf(void *, bus_dma_segment_t *, int, bus_size_t, int);
-
-#ifdef DC_USEIOSPACE
-#define DC_RES SYS_RES_IOPORT
-#define DC_RID DC_PCI_CFBIO
-#else
-#define DC_RES SYS_RES_MEMORY
-#define DC_RID DC_PCI_CFBMA
-#endif
-
-static device_method_t dc_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, dc_probe),
- DEVMETHOD(device_attach, dc_attach),
- DEVMETHOD(device_detach, dc_detach),
- DEVMETHOD(device_suspend, dc_suspend),
- DEVMETHOD(device_resume, dc_resume),
- DEVMETHOD(device_shutdown, dc_shutdown),
-
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
-
- /* MII interface */
- DEVMETHOD(miibus_readreg, dc_miibus_readreg),
- DEVMETHOD(miibus_writereg, dc_miibus_writereg),
- DEVMETHOD(miibus_statchg, dc_miibus_statchg),
- DEVMETHOD(miibus_mediainit, dc_miibus_mediainit),
-
- { 0, 0 }
-};
-
-static driver_t dc_driver = {
- "dc",
- dc_methods,
- sizeof(struct dc_softc)
-};
-
-static devclass_t dc_devclass;
-#ifdef __i386__
-static int dc_quick = 1;
-SYSCTL_INT(_hw, OID_AUTO, dc_quick, CTLFLAG_RW, &dc_quick, 0,
- "do not m_devget() in dc driver");
-#endif
-
-DRIVER_MODULE(dc, cardbus, dc_driver, dc_devclass, 0, 0);
-DRIVER_MODULE(dc, pci, dc_driver, dc_devclass, 0, 0);
-DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0);
-
-#define DC_SETBIT(sc, reg, x) \
- CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | (x))
-
-#define DC_CLRBIT(sc, reg, x) \
- CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) & ~(x))
-
-#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
-#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
-
-static void
-dc_delay(struct dc_softc *sc)
-{
- int idx;
-
- for (idx = (300 / 33) + 1; idx > 0; idx--)
- CSR_READ_4(sc, DC_BUSCTL);
-}
-
-static void
-dc_eeprom_width(struct dc_softc *sc)
-{
- int i;
-
- /* Force EEPROM to idle state. */
- dc_eeprom_idle(sc);
-
- /* Enter EEPROM access mode. */
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
- dc_delay(sc);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
- dc_delay(sc);
-
- for (i = 3; i--;) {
- if (6 & (1 << i))
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
- else
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- }
-
- for (i = 1; i <= 12; i++) {
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- if (!(CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)) {
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- break;
- }
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- }
-
- /* Turn off EEPROM access mode. */
- dc_eeprom_idle(sc);
-
- if (i < 4 || i > 12)
- sc->dc_romwidth = 6;
- else
- sc->dc_romwidth = i;
-
- /* Enter EEPROM access mode. */
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
- dc_delay(sc);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
- dc_delay(sc);
-
- /* Turn off EEPROM access mode. */
- dc_eeprom_idle(sc);
-}
-
-static void
-dc_eeprom_idle(struct dc_softc *sc)
-{
- int i;
-
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
- dc_delay(sc);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
- dc_delay(sc);
-
- for (i = 0; i < 25; i++) {
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- }
-
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CS);
- dc_delay(sc);
- CSR_WRITE_4(sc, DC_SIO, 0x00000000);
-}
-
-/*
- * Send a read command and address to the EEPROM, check for ACK.
- */
-static void
-dc_eeprom_putbyte(struct dc_softc *sc, int addr)
-{
- int d, i;
-
- d = DC_EECMD_READ >> 6;
- for (i = 3; i--; ) {
- if (d & (1 << i))
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
- else
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- }
-
- /*
- * Feed in each bit and strobe the clock.
- */
- for (i = sc->dc_romwidth; i--;) {
- if (addr & (1 << i)) {
- SIO_SET(DC_SIO_EE_DATAIN);
- } else {
- SIO_CLR(DC_SIO_EE_DATAIN);
- }
- dc_delay(sc);
- SIO_SET(DC_SIO_EE_CLK);
- dc_delay(sc);
- SIO_CLR(DC_SIO_EE_CLK);
- dc_delay(sc);
- }
-}
-
-/*
- * Read a word of data stored in the EEPROM at address 'addr.'
- * The PNIC 82c168/82c169 has its own non-standard way to read
- * the EEPROM.
- */
-static void
-dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, u_int16_t *dest)
-{
- int i;
- u_int32_t r;
-
- CSR_WRITE_4(sc, DC_PN_SIOCTL, DC_PN_EEOPCODE_READ | addr);
-
- for (i = 0; i < DC_TIMEOUT; i++) {
- DELAY(1);
- r = CSR_READ_4(sc, DC_SIO);
- if (!(r & DC_PN_SIOCTL_BUSY)) {
- *dest = (u_int16_t)(r & 0xFFFF);
- return;
- }
- }
-}
-
-/*
- * Read a word of data stored in the EEPROM at address 'addr.'
- * The Xircom X3201 has its own non-standard way to read
- * the EEPROM, too.
- */
-static void
-dc_eeprom_getword_xircom(struct dc_softc *sc, int addr, u_int16_t *dest)
-{
-
- SIO_SET(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ);
-
- addr *= 2;
- CSR_WRITE_4(sc, DC_ROM, addr | 0x160);
- *dest = (u_int16_t)CSR_READ_4(sc, DC_SIO) & 0xff;
- addr += 1;
- CSR_WRITE_4(sc, DC_ROM, addr | 0x160);
- *dest |= ((u_int16_t)CSR_READ_4(sc, DC_SIO) & 0xff) << 8;
-
- SIO_CLR(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ);
-}
-
-/*
- * Read a word of data stored in the EEPROM at address 'addr.'
- */
-static void
-dc_eeprom_getword(struct dc_softc *sc, int addr, u_int16_t *dest)
-{
- int i;
- u_int16_t word = 0;
-
- /* Force EEPROM to idle state. */
- dc_eeprom_idle(sc);
-
- /* Enter EEPROM access mode. */
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
- dc_delay(sc);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
- dc_delay(sc);
- DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
- dc_delay(sc);
-
- /*
- * Send address of word we want to read.
- */
- dc_eeprom_putbyte(sc, addr);
-
- /*
- * Start reading bits from EEPROM.
- */
- for (i = 0x8000; i; i >>= 1) {
- SIO_SET(DC_SIO_EE_CLK);
- dc_delay(sc);
- if (CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)
- word |= i;
- dc_delay(sc);
- SIO_CLR(DC_SIO_EE_CLK);
- dc_delay(sc);
- }
-
- /* Turn off EEPROM access mode. */
- dc_eeprom_idle(sc);
-
- *dest = word;
-}
-
-/*
- * Read a sequence of words from the EEPROM.
- */
-static void
-dc_read_eeprom(struct dc_softc *sc, caddr_t dest, int off, int cnt, int be)
-{
- int i;
- u_int16_t word = 0, *ptr;
-
- for (i = 0; i < cnt; i++) {
- if (DC_IS_PNIC(sc))
- dc_eeprom_getword_pnic(sc, off + i, &word);
- else if (DC_IS_XIRCOM(sc))
- dc_eeprom_getword_xircom(sc, off + i, &word);
- else
- dc_eeprom_getword(sc, off + i, &word);
- ptr = (u_int16_t *)(dest + (i * 2));
- if (be)
- *ptr = be16toh(word);
- else
- *ptr = le16toh(word);
- }
-}
-
-/*
- * The following two routines are taken from the Macronix 98713
- * Application Notes pp.19-21.
- */
-/*
- * Write a bit to the MII bus.
- */
-static void
-dc_mii_writebit(struct dc_softc *sc, int bit)
-{
-
- if (bit)
- CSR_WRITE_4(sc, DC_SIO,
- DC_SIO_ROMCTL_WRITE | DC_SIO_MII_DATAOUT);
- else
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
-
- DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK);
-}
-
-/*
- * Read a bit from the MII bus.
- */
-static int
-dc_mii_readbit(struct dc_softc *sc)
-{
-
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_READ | DC_SIO_MII_DIR);
- CSR_READ_4(sc, DC_SIO);
- DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK);
- DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK);
- if (CSR_READ_4(sc, DC_SIO) & DC_SIO_MII_DATAIN)
- return (1);
-
- return (0);
-}
-
-/*
- * Sync the PHYs by setting data bit and strobing the clock 32 times.
- */
-static void
-dc_mii_sync(struct dc_softc *sc)
-{
- int i;
-
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
-
- for (i = 0; i < 32; i++)
- dc_mii_writebit(sc, 1);
-}
-
-/*
- * Clock a series of bits through the MII.
- */
-static void
-dc_mii_send(struct dc_softc *sc, u_int32_t bits, int cnt)
-{
- int i;
-
- for (i = (0x1 << (cnt - 1)); i; i >>= 1)
- dc_mii_writebit(sc, bits & i);
-}
-
-/*
- * Read an PHY register through the MII.
- */
-static int
-dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
-{
- int i, ack;
-
- /*
- * Set up frame for RX.
- */
- frame->mii_stdelim = DC_MII_STARTDELIM;
- frame->mii_opcode = DC_MII_READOP;
- frame->mii_turnaround = 0;
- frame->mii_data = 0;
-
- /*
- * Sync the PHYs.
- */
- dc_mii_sync(sc);
-
- /*
- * Send command/address info.
- */
- dc_mii_send(sc, frame->mii_stdelim, 2);
- dc_mii_send(sc, frame->mii_opcode, 2);
- dc_mii_send(sc, frame->mii_phyaddr, 5);
- dc_mii_send(sc, frame->mii_regaddr, 5);
-
-#ifdef notdef
- /* Idle bit */
- dc_mii_writebit(sc, 1);
- dc_mii_writebit(sc, 0);
-#endif
-
- /* Check for ack. */
- ack = dc_mii_readbit(sc);
-
- /*
- * Now try reading data bits. If the ack failed, we still
- * need to clock through 16 cycles to keep the PHY(s) in sync.
- */
- if (ack) {
- for (i = 0; i < 16; i++)
- dc_mii_readbit(sc);
- goto fail;
- }
-
- for (i = 0x8000; i; i >>= 1) {
- if (!ack) {
- if (dc_mii_readbit(sc))
- frame->mii_data |= i;
- }
- }
-
-fail:
-
- dc_mii_writebit(sc, 0);
- dc_mii_writebit(sc, 0);
-
- if (ack)
- return (1);
- return (0);
-}
-
-/*
- * Write to a PHY register through the MII.
- */
-static int
-dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
-{
-
- /*
- * Set up frame for TX.
- */
-
- frame->mii_stdelim = DC_MII_STARTDELIM;
- frame->mii_opcode = DC_MII_WRITEOP;
- frame->mii_turnaround = DC_MII_TURNAROUND;
-
- /*
- * Sync the PHYs.
- */
- dc_mii_sync(sc);
-
- dc_mii_send(sc, frame->mii_stdelim, 2);
- dc_mii_send(sc, frame->mii_opcode, 2);
- dc_mii_send(sc, frame->mii_phyaddr, 5);
- dc_mii_send(sc, frame->mii_regaddr, 5);
- dc_mii_send(sc, frame->mii_turnaround, 2);
- dc_mii_send(sc, frame->mii_data, 16);
-
- /* Idle bit. */
- dc_mii_writebit(sc, 0);
- dc_mii_writebit(sc, 0);
-
- return (0);
-}
-
-static int
-dc_miibus_readreg(device_t dev, int phy, int reg)
-{
- struct dc_mii_frame frame;
- struct dc_softc *sc;
- int i, rval, phy_reg = 0;
-
- sc = device_get_softc(dev);
- bzero(&frame, sizeof(frame));
-
- /*
- * Note: both the AL981 and AN985 have internal PHYs,
- * however the AL981 provides direct access to the PHY
- * registers while the AN985 uses a serial MII interface.
- * The AN985's MII interface is also buggy in that you
- * can read from any MII address (0 to 31), but only address 1
- * behaves normally. To deal with both cases, we pretend
- * that the PHY is at MII address 1.
- */
- if (DC_IS_ADMTEK(sc) && phy != DC_ADMTEK_PHYADDR)
- return (0);
-
- /*
- * Note: the ukphy probes of the RS7112 report a PHY at
- * MII address 0 (possibly HomePNA?) and 1 (ethernet)
- * so we only respond to correct one.
- */
- if (DC_IS_CONEXANT(sc) && phy != DC_CONEXANT_PHYADDR)
- return (0);
-
- if (sc->dc_pmode != DC_PMODE_MII) {
- if (phy == (MII_NPHY - 1)) {
- switch (reg) {
- case MII_BMSR:
- /*
- * Fake something to make the probe
- * code think there's a PHY here.
- */
- return (BMSR_MEDIAMASK);
- break;
- case MII_PHYIDR1:
- if (DC_IS_PNIC(sc))
- return (DC_VENDORID_LO);
- return (DC_VENDORID_DEC);
- break;
- case MII_PHYIDR2:
- if (DC_IS_PNIC(sc))
- return (DC_DEVICEID_82C168);
- return (DC_DEVICEID_21143);
- break;
- default:
- return (0);
- break;
- }
- } else
- return (0);
- }
-
- if (DC_IS_PNIC(sc)) {
- CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_READ |
- (phy << 23) | (reg << 18));
- for (i = 0; i < DC_TIMEOUT; i++) {
- DELAY(1);
- rval = CSR_READ_4(sc, DC_PN_MII);
- if (!(rval & DC_PN_MII_BUSY)) {
- rval &= 0xFFFF;
- return (rval == 0xFFFF ? 0 : rval);
- }
- }
- return (0);
- }
-
- if (DC_IS_COMET(sc)) {
- switch (reg) {
- case MII_BMCR:
- phy_reg = DC_AL_BMCR;
- break;
- case MII_BMSR:
- phy_reg = DC_AL_BMSR;
- break;
- case MII_PHYIDR1:
- phy_reg = DC_AL_VENID;
- break;
- case MII_PHYIDR2:
- phy_reg = DC_AL_DEVID;
- break;
- case MII_ANAR:
- phy_reg = DC_AL_ANAR;
- break;
- case MII_ANLPAR:
- phy_reg = DC_AL_LPAR;
- break;
- case MII_ANER:
- phy_reg = DC_AL_ANER;
- break;
- default:
- device_printf(dev, "phy_read: bad phy register %x\n",
- reg);
- return (0);
- break;
- }
-
- rval = CSR_READ_4(sc, phy_reg) & 0x0000FFFF;
-
- if (rval == 0xFFFF)
- return (0);
- return (rval);
- }
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- if (sc->dc_type == DC_TYPE_98713) {
- phy_reg = CSR_READ_4(sc, DC_NETCFG);
- CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL);
- }
- dc_mii_readreg(sc, &frame);
- if (sc->dc_type == DC_TYPE_98713)
- CSR_WRITE_4(sc, DC_NETCFG, phy_reg);
-
- return (frame.mii_data);
-}
-
-static int
-dc_miibus_writereg(device_t dev, int phy, int reg, int data)
-{
- struct dc_softc *sc;
- struct dc_mii_frame frame;
- int i, phy_reg = 0;
-
- sc = device_get_softc(dev);
- bzero(&frame, sizeof(frame));
-
- if (DC_IS_ADMTEK(sc) && phy != DC_ADMTEK_PHYADDR)
- return (0);
-
- if (DC_IS_CONEXANT(sc) && phy != DC_CONEXANT_PHYADDR)
- return (0);
-
- if (DC_IS_PNIC(sc)) {
- CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_WRITE |
- (phy << 23) | (reg << 10) | data);
- for (i = 0; i < DC_TIMEOUT; i++) {
- if (!(CSR_READ_4(sc, DC_PN_MII) & DC_PN_MII_BUSY))
- break;
- }
- return (0);
- }
-
- if (DC_IS_COMET(sc)) {
- switch (reg) {
- case MII_BMCR:
- phy_reg = DC_AL_BMCR;
- break;
- case MII_BMSR:
- phy_reg = DC_AL_BMSR;
- break;
- case MII_PHYIDR1:
- phy_reg = DC_AL_VENID;
- break;
- case MII_PHYIDR2:
- phy_reg = DC_AL_DEVID;
- break;
- case MII_ANAR:
- phy_reg = DC_AL_ANAR;
- break;
- case MII_ANLPAR:
- phy_reg = DC_AL_LPAR;
- break;
- case MII_ANER:
- phy_reg = DC_AL_ANER;
- break;
- default:
- device_printf(dev, "phy_write: bad phy register %x\n",
- reg);
- return (0);
- break;
- }
-
- CSR_WRITE_4(sc, phy_reg, data);
- return (0);
- }
-
- frame.mii_phyaddr = phy;
- frame.mii_regaddr = reg;
- frame.mii_data = data;
-
- if (sc->dc_type == DC_TYPE_98713) {
- phy_reg = CSR_READ_4(sc, DC_NETCFG);
- CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL);
- }
- dc_mii_writereg(sc, &frame);
- if (sc->dc_type == DC_TYPE_98713)
- CSR_WRITE_4(sc, DC_NETCFG, phy_reg);
-
- return (0);
-}
-
-static void
-dc_miibus_statchg(device_t dev)
-{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifmedia *ifm;
-
- sc = device_get_softc(dev);
- if (DC_IS_ADMTEK(sc))
- return;
-
- mii = device_get_softc(sc->dc_miibus);
- ifm = &mii->mii_media;
- if (DC_IS_DAVICOM(sc) &&
- IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) {
- dc_setcfg(sc, ifm->ifm_media);
- sc->dc_if_media = ifm->ifm_media;
- } else {
- dc_setcfg(sc, mii->mii_media_active);
- sc->dc_if_media = mii->mii_media_active;
- }
-}
-
-/*
- * Special support for DM9102A cards with HomePNA PHYs. Note:
- * with the Davicom DM9102A/DM9801 eval board that I have, it seems
- * to be impossible to talk to the management interface of the DM9801
- * PHY (its MDIO pin is not connected to anything). Consequently,
- * the driver has to just 'know' about the additional mode and deal
- * with it itself. *sigh*
- */
-static void
-dc_miibus_mediainit(device_t dev)
-{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifmedia *ifm;
- int rev;
-
- rev = pci_read_config(dev, DC_PCI_CFRV, 4) & 0xFF;
-
- sc = device_get_softc(dev);
- mii = device_get_softc(sc->dc_miibus);
- ifm = &mii->mii_media;
-
- if (DC_IS_DAVICOM(sc) && rev >= DC_REVISION_DM9102A)
- ifmedia_add(ifm, IFM_ETHER | IFM_HPNA_1, 0, NULL);
-}
-
-#define DC_BITS_512 9
-#define DC_BITS_128 7
-#define DC_BITS_64 6
-
-static uint32_t
-dc_mchash_le(struct dc_softc *sc, const uint8_t *addr)
-{
- uint32_t crc;
-
- /* Compute CRC for the address value. */
- crc = ether_crc32_le(addr, ETHER_ADDR_LEN);
-
- /*
- * The hash table on the PNIC II and the MX98715AEC-C/D/E
- * chips is only 128 bits wide.
- */
- if (sc->dc_flags & DC_128BIT_HASH)
- return (crc & ((1 << DC_BITS_128) - 1));
-
- /* The hash table on the MX98715BEC is only 64 bits wide. */
- if (sc->dc_flags & DC_64BIT_HASH)
- return (crc & ((1 << DC_BITS_64) - 1));
-
- /* Xircom's hash filtering table is different (read: weird) */
- /* Xircom uses the LEAST significant bits */
- if (DC_IS_XIRCOM(sc)) {
- if ((crc & 0x180) == 0x180)
- return ((crc & 0x0F) + (crc & 0x70) * 3 + (14 << 4));
- else
- return ((crc & 0x1F) + ((crc >> 1) & 0xF0) * 3 +
- (12 << 4));
- }
-
- return (crc & ((1 << DC_BITS_512) - 1));
-}
-
-/*
- * Calculate CRC of a multicast group address, return the lower 6 bits.
- */
-static uint32_t
-dc_mchash_be(const uint8_t *addr)
-{
- uint32_t crc;
-
- /* Compute CRC for the address value. */
- crc = ether_crc32_be(addr, ETHER_ADDR_LEN);
-
- /* Return the filter bit position. */
- return ((crc >> 26) & 0x0000003F);
-}
-
-/*
- * 21143-style RX filter setup routine. Filter programming is done by
- * downloading a special setup frame into the TX engine. 21143, Macronix,
- * PNIC, PNIC II and Davicom chips are programmed this way.
- *
- * We always program the chip using 'hash perfect' mode, i.e. one perfect
- * address (our node address) and a 512-bit hash filter for multicast
- * frames. We also sneak the broadcast address into the hash filter since
- * we need that too.
- */
-static void
-dc_setfilt_21143(struct dc_softc *sc)
-{
- struct dc_desc *sframe;
- u_int32_t h, *sp;
- struct ifmultiaddr *ifma;
- struct ifnet *ifp;
- int i;
-
- ifp = sc->dc_ifp;
-
- i = sc->dc_cdata.dc_tx_prod;
- DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT);
- sc->dc_cdata.dc_tx_cnt++;
- sframe = &sc->dc_ldata->dc_tx_list[i];
- sp = sc->dc_cdata.dc_sbuf;
- bzero(sp, DC_SFRAME_LEN);
-
- sframe->dc_data = htole32(sc->dc_saddr);
- sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP |
- DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT);
-
- sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf;
-
- /* If we want promiscuous mode, set the allframes bit. */
- if (ifp->if_flags & IFF_PROMISC)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
- else
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
-
- if (ifp->if_flags & IFF_ALLMULTI)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
- else
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
-
- IF_ADDR_LOCK(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = dc_mchash_le(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- sp[h >> 4] |= htole32(1 << (h & 0xF));
- }
- IF_ADDR_UNLOCK(ifp);
-
- if (ifp->if_flags & IFF_BROADCAST) {
- h = dc_mchash_le(sc, ifp->if_broadcastaddr);
- sp[h >> 4] |= htole32(1 << (h & 0xF));
- }
-
- /* Set our MAC address */
- sp[39] = DC_SP_MAC(((u_int16_t *)IFP2ENADDR(sc->dc_ifp))[0]);
- sp[40] = DC_SP_MAC(((u_int16_t *)IFP2ENADDR(sc->dc_ifp))[1]);
- sp[41] = DC_SP_MAC(((u_int16_t *)IFP2ENADDR(sc->dc_ifp))[2]);
-
- sframe->dc_status = htole32(DC_TXSTAT_OWN);
- CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
-
- /*
- * The PNIC takes an exceedingly long time to process its
- * setup frame; wait 10ms after posting the setup frame
- * before proceeding, just so it has time to swallow its
- * medicine.
- */
- DELAY(10000);
-
- ifp->if_timer = 5;
-}
-
-static void
-dc_setfilt_admtek(struct dc_softc *sc)
-{
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- int h = 0;
- u_int32_t hashes[2] = { 0, 0 };
-
- ifp = sc->dc_ifp;
-
- /* Init our MAC address. */
- CSR_WRITE_4(sc, DC_AL_PAR0, *(u_int32_t *)(&IFP2ENADDR(sc->dc_ifp)[0]));
- CSR_WRITE_4(sc, DC_AL_PAR1, *(u_int32_t *)(&IFP2ENADDR(sc->dc_ifp)[4]));
-
- /* If we want promiscuous mode, set the allframes bit. */
- if (ifp->if_flags & IFF_PROMISC)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
- else
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
-
- if (ifp->if_flags & IFF_ALLMULTI)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
- else
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
-
- /* First, zot all the existing hash bits. */
- CSR_WRITE_4(sc, DC_AL_MAR0, 0);
- CSR_WRITE_4(sc, DC_AL_MAR1, 0);
-
- /*
- * If we're already in promisc or allmulti mode, we
- * don't have to bother programming the multicast filter.
- */
- if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))
- return;
-
- /* Now program new ones. */
- IF_ADDR_LOCK(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (DC_IS_CENTAUR(sc))
- h = dc_mchash_le(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- else
- h = dc_mchash_be(
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
- IF_ADDR_UNLOCK(ifp);
-
- CSR_WRITE_4(sc, DC_AL_MAR0, hashes[0]);
- CSR_WRITE_4(sc, DC_AL_MAR1, hashes[1]);
-}
-
-static void
-dc_setfilt_asix(struct dc_softc *sc)
-{
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- int h = 0;
- u_int32_t hashes[2] = { 0, 0 };
-
- ifp = sc->dc_ifp;
-
- /* Init our MAC address */
- CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR0);
- CSR_WRITE_4(sc, DC_AX_FILTDATA,
- *(u_int32_t *)(&IFP2ENADDR(sc->dc_ifp)[0]));
- CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR1);
- CSR_WRITE_4(sc, DC_AX_FILTDATA,
- *(u_int32_t *)(&IFP2ENADDR(sc->dc_ifp)[4]));
-
- /* If we want promiscuous mode, set the allframes bit. */
- if (ifp->if_flags & IFF_PROMISC)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
- else
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
-
- if (ifp->if_flags & IFF_ALLMULTI)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
- else
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
-
- /*
- * The ASIX chip has a special bit to enable reception
- * of broadcast frames.
- */
- if (ifp->if_flags & IFF_BROADCAST)
- DC_SETBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD);
- else
- DC_CLRBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD);
-
- /* first, zot all the existing hash bits */
- CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0);
- CSR_WRITE_4(sc, DC_AX_FILTDATA, 0);
- CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1);
- CSR_WRITE_4(sc, DC_AX_FILTDATA, 0);
-
- /*
- * If we're already in promisc or allmulti mode, we
- * don't have to bother programming the multicast filter.
- */
- if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))
- return;
-
- /* now program new ones */
- IF_ADDR_LOCK(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = dc_mchash_be(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- if (h < 32)
- hashes[0] |= (1 << h);
- else
- hashes[1] |= (1 << (h - 32));
- }
- IF_ADDR_UNLOCK(ifp);
-
- CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0);
- CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0]);
- CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1);
- CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[1]);
-}
-
-static void
-dc_setfilt_xircom(struct dc_softc *sc)
-{
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- struct dc_desc *sframe;
- u_int32_t h, *sp;
- int i;
-
- ifp = sc->dc_ifp;
- DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON));
-
- i = sc->dc_cdata.dc_tx_prod;
- DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT);
- sc->dc_cdata.dc_tx_cnt++;
- sframe = &sc->dc_ldata->dc_tx_list[i];
- sp = sc->dc_cdata.dc_sbuf;
- bzero(sp, DC_SFRAME_LEN);
-
- sframe->dc_data = htole32(sc->dc_saddr);
- sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP |
- DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT);
-
- sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf;
-
- /* If we want promiscuous mode, set the allframes bit. */
- if (ifp->if_flags & IFF_PROMISC)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
- else
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
-
- if (ifp->if_flags & IFF_ALLMULTI)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
- else
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
-
- IF_ADDR_LOCK(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- h = dc_mchash_le(sc,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- sp[h >> 4] |= htole32(1 << (h & 0xF));
- }
- IF_ADDR_UNLOCK(ifp);
-
- if (ifp->if_flags & IFF_BROADCAST) {
- h = dc_mchash_le(sc, ifp->if_broadcastaddr);
- sp[h >> 4] |= htole32(1 << (h & 0xF));
- }
-
- /* Set our MAC address */
- sp[0] = DC_SP_MAC(((u_int16_t *)IFP2ENADDR(sc->dc_ifp))[0]);
- sp[1] = DC_SP_MAC(((u_int16_t *)IFP2ENADDR(sc->dc_ifp))[1]);
- sp[2] = DC_SP_MAC(((u_int16_t *)IFP2ENADDR(sc->dc_ifp))[2]);
-
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON);
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- sframe->dc_status = htole32(DC_TXSTAT_OWN);
- CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
-
- /*
- * Wait some time...
- */
- DELAY(1000);
-
- ifp->if_timer = 5;
-}
-
-static void
-dc_setfilt(struct dc_softc *sc)
-{
-
- if (DC_IS_INTEL(sc) || DC_IS_MACRONIX(sc) || DC_IS_PNIC(sc) ||
- DC_IS_PNICII(sc) || DC_IS_DAVICOM(sc) || DC_IS_CONEXANT(sc))
- dc_setfilt_21143(sc);
-
- if (DC_IS_ASIX(sc))
- dc_setfilt_asix(sc);
-
- if (DC_IS_ADMTEK(sc))
- dc_setfilt_admtek(sc);
-
- if (DC_IS_XIRCOM(sc))
- dc_setfilt_xircom(sc);
-}
-
-/*
- * In order to fiddle with the 'full-duplex' and '100Mbps' bits in
- * the netconfig register, we first have to put the transmit and/or
- * receive logic in the idle state.
- */
-static void
-dc_setcfg(struct dc_softc *sc, int media)
-{
- int i, restart = 0, watchdogreg;
- u_int32_t isr;
-
- if (IFM_SUBTYPE(media) == IFM_NONE)
- return;
-
- if (CSR_READ_4(sc, DC_NETCFG) & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)) {
- restart = 1;
- DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON));
-
- for (i = 0; i < DC_TIMEOUT; i++) {
- isr = CSR_READ_4(sc, DC_ISR);
- if (isr & DC_ISR_TX_IDLE &&
- ((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
- (isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT))
- break;
- DELAY(10);
- }
-
- if (i == DC_TIMEOUT)
- if_printf(sc->dc_ifp,
- "failed to force tx and rx to idle state\n");
- }
-
- if (IFM_SUBTYPE(media) == IFM_100_TX) {
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL);
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT);
- if (sc->dc_pmode == DC_PMODE_MII) {
- if (DC_IS_INTEL(sc)) {
- /* There's a write enable bit here that reads as 1. */
- watchdogreg = CSR_READ_4(sc, DC_WATCHDOG);
- watchdogreg &= ~DC_WDOG_CTLWREN;
- watchdogreg |= DC_WDOG_JABBERDIS;
- CSR_WRITE_4(sc, DC_WATCHDOG, watchdogreg);
- } else {
- DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS);
- }
- DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS |
- DC_NETCFG_PORTSEL | DC_NETCFG_SCRAMBLER));
- if (sc->dc_type == DC_TYPE_98713)
- DC_SETBIT(sc, DC_NETCFG, (DC_NETCFG_PCS |
- DC_NETCFG_SCRAMBLER));
- if (!DC_IS_DAVICOM(sc))
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
- DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
- if (DC_IS_INTEL(sc))
- dc_apply_fixup(sc, IFM_AUTO);
- } else {
- if (DC_IS_PNIC(sc)) {
- DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_SPEEDSEL);
- DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP);
- DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL);
- }
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER);
- if (DC_IS_INTEL(sc))
- dc_apply_fixup(sc,
- (media & IFM_GMASK) == IFM_FDX ?
- IFM_100_TX | IFM_FDX : IFM_100_TX);
- }
- }
-
- if (IFM_SUBTYPE(media) == IFM_10_T) {
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL);
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT);
- if (sc->dc_pmode == DC_PMODE_MII) {
- /* There's a write enable bit here that reads as 1. */
- if (DC_IS_INTEL(sc)) {
- watchdogreg = CSR_READ_4(sc, DC_WATCHDOG);
- watchdogreg &= ~DC_WDOG_CTLWREN;
- watchdogreg |= DC_WDOG_JABBERDIS;
- CSR_WRITE_4(sc, DC_WATCHDOG, watchdogreg);
- } else {
- DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS);
- }
- DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS |
- DC_NETCFG_PORTSEL | DC_NETCFG_SCRAMBLER));
- if (sc->dc_type == DC_TYPE_98713)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
- if (!DC_IS_DAVICOM(sc))
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
- DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
- if (DC_IS_INTEL(sc))
- dc_apply_fixup(sc, IFM_AUTO);
- } else {
- if (DC_IS_PNIC(sc)) {
- DC_PN_GPIO_CLRBIT(sc, DC_PN_GPIO_SPEEDSEL);
- DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP);
- DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL);
- }
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER);
- if (DC_IS_INTEL(sc)) {
- DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET);
- DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
- if ((media & IFM_GMASK) == IFM_FDX)
- DC_SETBIT(sc, DC_10BTCTRL, 0x7F3D);
- else
- DC_SETBIT(sc, DC_10BTCTRL, 0x7F3F);
- DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
- DC_CLRBIT(sc, DC_10BTCTRL,
- DC_TCTL_AUTONEGENBL);
- dc_apply_fixup(sc,
- (media & IFM_GMASK) == IFM_FDX ?
- IFM_10_T | IFM_FDX : IFM_10_T);
- DELAY(20000);
- }
- }
- }
-
- /*
- * If this is a Davicom DM9102A card with a DM9801 HomePNA
- * PHY and we want HomePNA mode, set the portsel bit to turn
- * on the external MII port.
- */
- if (DC_IS_DAVICOM(sc)) {
- if (IFM_SUBTYPE(media) == IFM_HPNA_1) {
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
- sc->dc_link = 1;
- } else {
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
- }
- }
-
- if ((media & IFM_GMASK) == IFM_FDX) {
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX);
- if (sc->dc_pmode == DC_PMODE_SYM && DC_IS_PNIC(sc))
- DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_DUPLEX);
- } else {
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX);
- if (sc->dc_pmode == DC_PMODE_SYM && DC_IS_PNIC(sc))
- DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_DUPLEX);
- }
-
- if (restart)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON | DC_NETCFG_RX_ON);
-}
-
-static void
-dc_reset(struct dc_softc *sc)
-{
- int i;
-
- DC_SETBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET);
-
- for (i = 0; i < DC_TIMEOUT; i++) {
- DELAY(10);
- if (!(CSR_READ_4(sc, DC_BUSCTL) & DC_BUSCTL_RESET))
- break;
- }
-
- if (DC_IS_ASIX(sc) || DC_IS_ADMTEK(sc) || DC_IS_CONEXANT(sc) ||
- DC_IS_XIRCOM(sc) || DC_IS_INTEL(sc)) {
- DELAY(10000);
- DC_CLRBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET);
- i = 0;
- }
-
- if (i == DC_TIMEOUT)
- if_printf(sc->dc_ifp, "reset never completed!\n");
-
- /* Wait a little while for the chip to get its brains in order. */
- DELAY(1000);
-
- CSR_WRITE_4(sc, DC_IMR, 0x00000000);
- CSR_WRITE_4(sc, DC_BUSCTL, 0x00000000);
- CSR_WRITE_4(sc, DC_NETCFG, 0x00000000);
-
- /*
- * Bring the SIA out of reset. In some cases, it looks
- * like failing to unreset the SIA soon enough gets it
- * into a state where it will never come out of reset
- * until we reset the whole chip again.
- */
- if (DC_IS_INTEL(sc)) {
- DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
- CSR_WRITE_4(sc, DC_10BTCTRL, 0);
- CSR_WRITE_4(sc, DC_WATCHDOG, 0);
- }
-}
-
-static struct dc_type *
-dc_devtype(device_t dev)
-{
- struct dc_type *t;
- u_int32_t rev;
-
- t = dc_devs;
-
- while (t->dc_name != NULL) {
- if ((pci_get_vendor(dev) == t->dc_vid) &&
- (pci_get_device(dev) == t->dc_did)) {
- /* Check the PCI revision */
- rev = pci_read_config(dev, DC_PCI_CFRV, 4) & 0xFF;
- if (t->dc_did == DC_DEVICEID_98713 &&
- rev >= DC_REVISION_98713A)
- t++;
- if (t->dc_did == DC_DEVICEID_98713_CP &&
- rev >= DC_REVISION_98713A)
- t++;
- if (t->dc_did == DC_DEVICEID_987x5 &&
- rev >= DC_REVISION_98715AEC_C)
- t++;
- if (t->dc_did == DC_DEVICEID_987x5 &&
- rev >= DC_REVISION_98725)
- t++;
- if (t->dc_did == DC_DEVICEID_AX88140A &&
- rev >= DC_REVISION_88141)
- t++;
- if (t->dc_did == DC_DEVICEID_82C168 &&
- rev >= DC_REVISION_82C169)
- t++;
- if (t->dc_did == DC_DEVICEID_DM9102 &&
- rev >= DC_REVISION_DM9102A)
- t++;
- /*
- * The Microsoft MN-130 has a device ID of 0x0002,
- * which happens to be the same as the PNIC 82c168.
- * To keep dc_attach() from getting confused, we
- * pretend its ID is something different.
- * XXX: ideally, dc_attach() should be checking
- * vendorid+deviceid together to avoid such
- * collisions.
- */
- if (t->dc_vid == DC_VENDORID_MICROSOFT &&
- t->dc_did == DC_DEVICEID_MSMN130)
- t++;
- return (t);
- }
- t++;
- }
-
- return (NULL);
-}
-
-/*
- * Probe for a 21143 or clone chip. Check the PCI vendor and device
- * IDs against our list and return a device name if we find a match.
- * We do a little bit of extra work to identify the exact type of
- * chip. The MX98713 and MX98713A have the same PCI vendor/device ID,
- * but different revision IDs. The same is true for 98715/98715A
- * chips and the 98725, as well as the ASIX and ADMtek chips. In some
- * cases, the exact chip revision affects driver behavior.
- */
-static int
-dc_probe(device_t dev)
-{
- struct dc_type *t;
-
- t = dc_devtype(dev);
-
- if (t != NULL) {
- device_set_desc(dev, t->dc_name);
- return (BUS_PROBE_DEFAULT);
- }
-
- return (ENXIO);
-}
-
-static void
-dc_apply_fixup(struct dc_softc *sc, int media)
-{
- struct dc_mediainfo *m;
- u_int8_t *p;
- int i;
- u_int32_t reg;
-
- m = sc->dc_mi;
-
- while (m != NULL) {
- if (m->dc_media == media)
- break;
- m = m->dc_next;
- }
-
- if (m == NULL)
- return;
-
- for (i = 0, p = m->dc_reset_ptr; i < m->dc_reset_len; i++, p += 2) {
- reg = (p[0] | (p[1] << 8)) << 16;
- CSR_WRITE_4(sc, DC_WATCHDOG, reg);
- }
-
- for (i = 0, p = m->dc_gp_ptr; i < m->dc_gp_len; i++, p += 2) {
- reg = (p[0] | (p[1] << 8)) << 16;
- CSR_WRITE_4(sc, DC_WATCHDOG, reg);
- }
-}
-
-static void
-dc_decode_leaf_sia(struct dc_softc *sc, struct dc_eblock_sia *l)
-{
- struct dc_mediainfo *m;
-
- m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT | M_ZERO);
- switch (l->dc_sia_code & ~DC_SIA_CODE_EXT) {
- case DC_SIA_CODE_10BT:
- m->dc_media = IFM_10_T;
- break;
- case DC_SIA_CODE_10BT_FDX:
- m->dc_media = IFM_10_T | IFM_FDX;
- break;
- case DC_SIA_CODE_10B2:
- m->dc_media = IFM_10_2;
- break;
- case DC_SIA_CODE_10B5:
- m->dc_media = IFM_10_5;
- break;
- default:
- break;
- }
-
- /*
- * We need to ignore CSR13, CSR14, CSR15 for SIA mode.
- * Things apparently already work for cards that do
- * supply Media Specific Data.
- */
- if (l->dc_sia_code & DC_SIA_CODE_EXT) {
- m->dc_gp_len = 2;
- m->dc_gp_ptr =
- (u_int8_t *)&l->dc_un.dc_sia_ext.dc_sia_gpio_ctl;
- } else {
- m->dc_gp_len = 2;
- m->dc_gp_ptr =
- (u_int8_t *)&l->dc_un.dc_sia_noext.dc_sia_gpio_ctl;
- }
-
- m->dc_next = sc->dc_mi;
- sc->dc_mi = m;
-
- sc->dc_pmode = DC_PMODE_SIA;
-}
-
-static void
-dc_decode_leaf_sym(struct dc_softc *sc, struct dc_eblock_sym *l)
-{
- struct dc_mediainfo *m;
-
- m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT | M_ZERO);
- if (l->dc_sym_code == DC_SYM_CODE_100BT)
- m->dc_media = IFM_100_TX;
-
- if (l->dc_sym_code == DC_SYM_CODE_100BT_FDX)
- m->dc_media = IFM_100_TX | IFM_FDX;
-
- m->dc_gp_len = 2;
- m->dc_gp_ptr = (u_int8_t *)&l->dc_sym_gpio_ctl;
-
- m->dc_next = sc->dc_mi;
- sc->dc_mi = m;
-
- sc->dc_pmode = DC_PMODE_SYM;
-}
-
-static void
-dc_decode_leaf_mii(struct dc_softc *sc, struct dc_eblock_mii *l)
-{
- struct dc_mediainfo *m;
- u_int8_t *p;
-
- m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT | M_ZERO);
- /* We abuse IFM_AUTO to represent MII. */
- m->dc_media = IFM_AUTO;
- m->dc_gp_len = l->dc_gpr_len;
-
- p = (u_int8_t *)l;
- p += sizeof(struct dc_eblock_mii);
- m->dc_gp_ptr = p;
- p += 2 * l->dc_gpr_len;
- m->dc_reset_len = *p;
- p++;
- m->dc_reset_ptr = p;
-
- m->dc_next = sc->dc_mi;
- sc->dc_mi = m;
-}
-
-static void
-dc_read_srom(struct dc_softc *sc, int bits)
-{
- int size;
-
- size = 2 << bits;
- sc->dc_srom = malloc(size, M_DEVBUF, M_NOWAIT);
- dc_read_eeprom(sc, (caddr_t)sc->dc_srom, 0, (size / 2), 0);
-}
-
-static void
-dc_parse_21143_srom(struct dc_softc *sc)
-{
- struct dc_leaf_hdr *lhdr;
- struct dc_eblock_hdr *hdr;
- int have_mii, i, loff;
- char *ptr;
-
- have_mii = 0;
- loff = sc->dc_srom[27];
- lhdr = (struct dc_leaf_hdr *)&(sc->dc_srom[loff]);
-
- ptr = (char *)lhdr;
- ptr += sizeof(struct dc_leaf_hdr) - 1;
- /*
- * Look if we got a MII media block.
- */
- for (i = 0; i < lhdr->dc_mcnt; i++) {
- hdr = (struct dc_eblock_hdr *)ptr;
- if (hdr->dc_type == DC_EBLOCK_MII)
- have_mii++;
-
- ptr += (hdr->dc_len & 0x7F);
- ptr++;
- }
-
- /*
- * Do the same thing again. Only use SIA and SYM media
- * blocks if no MII media block is available.
- */
- ptr = (char *)lhdr;
- ptr += sizeof(struct dc_leaf_hdr) - 1;
- for (i = 0; i < lhdr->dc_mcnt; i++) {
- hdr = (struct dc_eblock_hdr *)ptr;
- switch (hdr->dc_type) {
- case DC_EBLOCK_MII:
- dc_decode_leaf_mii(sc, (struct dc_eblock_mii *)hdr);
- break;
- case DC_EBLOCK_SIA:
- if (! have_mii)
- dc_decode_leaf_sia(sc,
- (struct dc_eblock_sia *)hdr);
- break;
- case DC_EBLOCK_SYM:
- if (! have_mii)
- dc_decode_leaf_sym(sc,
- (struct dc_eblock_sym *)hdr);
- break;
- default:
- /* Don't care. Yet. */
- break;
- }
- ptr += (hdr->dc_len & 0x7F);
- ptr++;
- }
-}
-
-static void
-dc_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- u_int32_t *paddr;
-
- KASSERT(nseg == 1, ("wrong number of segments, should be 1"));
- paddr = arg;
- *paddr = segs->ds_addr;
-}
-
-/*
- * Attach the interface. Allocate softc structures, do ifmedia
- * setup and ethernet/BPF attach.
- */
-static int
-dc_attach(device_t dev)
-{
- int tmp = 0;
- u_char eaddr[ETHER_ADDR_LEN];
- u_int32_t command;
- struct dc_softc *sc;
- struct ifnet *ifp;
- u_int32_t revision;
- int error = 0, rid, mac_offset;
- int i;
- u_int8_t *mac;
-
- sc = device_get_softc(dev);
-
- mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
- MTX_DEF);
-
- /*
- * Map control/status registers.
- */
- pci_enable_busmaster(dev);
-
- rid = DC_RID;
- sc->dc_res = bus_alloc_resource_any(dev, DC_RES, &rid, RF_ACTIVE);
-
- if (sc->dc_res == NULL) {
- device_printf(dev, "couldn't map ports/memory\n");
- error = ENXIO;
- goto fail;
- }
-
- sc->dc_btag = rman_get_bustag(sc->dc_res);
- sc->dc_bhandle = rman_get_bushandle(sc->dc_res);
-
- /* Allocate interrupt. */
- rid = 0;
- sc->dc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
-
- if (sc->dc_irq == NULL) {
- device_printf(dev, "couldn't map interrupt\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Need this info to decide on a chip type. */
- sc->dc_info = dc_devtype(dev);
- revision = pci_read_config(dev, DC_PCI_CFRV, 4) & 0x000000FF;
-
- /* Get the eeprom width, but PNIC and XIRCOM have diff eeprom */
- if (sc->dc_info->dc_did != DC_DEVICEID_82C168 &&
- sc->dc_info->dc_did != DC_DEVICEID_X3201)
- dc_eeprom_width(sc);
-
- switch (sc->dc_info->dc_did) {
- case DC_DEVICEID_21143:
- sc->dc_type = DC_TYPE_21143;
- sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
- sc->dc_flags |= DC_REDUCED_MII_POLL;
- /* Save EEPROM contents so we can parse them later. */
- dc_read_srom(sc, sc->dc_romwidth);
- break;
- case DC_DEVICEID_DM9009:
- case DC_DEVICEID_DM9100:
- case DC_DEVICEID_DM9102:
- sc->dc_type = DC_TYPE_DM9102;
- sc->dc_flags |= DC_TX_COALESCE | DC_TX_INTR_ALWAYS;
- sc->dc_flags |= DC_REDUCED_MII_POLL | DC_TX_STORENFWD;
- sc->dc_flags |= DC_TX_ALIGN;
- sc->dc_pmode = DC_PMODE_MII;
- /* Increase the latency timer value. */
- command = pci_read_config(dev, DC_PCI_CFLT, 4);
- command &= 0xFFFF00FF;
- command |= 0x00008000;
- pci_write_config(dev, DC_PCI_CFLT, command, 4);
- break;
- case DC_DEVICEID_AL981:
- sc->dc_type = DC_TYPE_AL981;
- sc->dc_flags |= DC_TX_USE_TX_INTR;
- sc->dc_flags |= DC_TX_ADMTEK_WAR;
- sc->dc_pmode = DC_PMODE_MII;
- dc_read_srom(sc, sc->dc_romwidth);
- break;
- case DC_DEVICEID_AN985:
- case DC_DEVICEID_ADM9511:
- case DC_DEVICEID_ADM9513:
- case DC_DEVICEID_FA511:
- case DC_DEVICEID_FE2500:
- case DC_DEVICEID_EN2242:
- case DC_DEVICEID_HAWKING_PN672TX:
- case DC_DEVICEID_3CSOHOB:
- case DC_DEVICEID_MSMN120:
- case DC_DEVICEID_MSMN130_FAKE: /* XXX avoid collision with PNIC*/
- sc->dc_type = DC_TYPE_AN985;
- sc->dc_flags |= DC_64BIT_HASH;
- sc->dc_flags |= DC_TX_USE_TX_INTR;
- sc->dc_flags |= DC_TX_ADMTEK_WAR;
- sc->dc_pmode = DC_PMODE_MII;
- /* Don't read SROM for - auto-loaded on reset */
- break;
- case DC_DEVICEID_98713:
- case DC_DEVICEID_98713_CP:
- if (revision < DC_REVISION_98713A) {
- sc->dc_type = DC_TYPE_98713;
- }
- if (revision >= DC_REVISION_98713A) {
- sc->dc_type = DC_TYPE_98713A;
- sc->dc_flags |= DC_21143_NWAY;
- }
- sc->dc_flags |= DC_REDUCED_MII_POLL;
- sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
- break;
- case DC_DEVICEID_987x5:
- case DC_DEVICEID_EN1217:
- /*
- * Macronix MX98715AEC-C/D/E parts have only a
- * 128-bit hash table. We need to deal with these
- * in the same manner as the PNIC II so that we
- * get the right number of bits out of the
- * CRC routine.
- */
- if (revision >= DC_REVISION_98715AEC_C &&
- revision < DC_REVISION_98725)
- sc->dc_flags |= DC_128BIT_HASH;
- sc->dc_type = DC_TYPE_987x5;
- sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
- sc->dc_flags |= DC_REDUCED_MII_POLL | DC_21143_NWAY;
- break;
- case DC_DEVICEID_98727:
- sc->dc_type = DC_TYPE_987x5;
- sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
- sc->dc_flags |= DC_REDUCED_MII_POLL | DC_21143_NWAY;
- break;
- case DC_DEVICEID_82C115:
- sc->dc_type = DC_TYPE_PNICII;
- sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR | DC_128BIT_HASH;
- sc->dc_flags |= DC_REDUCED_MII_POLL | DC_21143_NWAY;
- break;
- case DC_DEVICEID_82C168:
- sc->dc_type = DC_TYPE_PNIC;
- sc->dc_flags |= DC_TX_STORENFWD | DC_TX_INTR_ALWAYS;
- sc->dc_flags |= DC_PNIC_RX_BUG_WAR;
- sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF, M_NOWAIT);
- if (revision < DC_REVISION_82C169)
- sc->dc_pmode = DC_PMODE_SYM;
- break;
- case DC_DEVICEID_AX88140A:
- sc->dc_type = DC_TYPE_ASIX;
- sc->dc_flags |= DC_TX_USE_TX_INTR | DC_TX_INTR_FIRSTFRAG;
- sc->dc_flags |= DC_REDUCED_MII_POLL;
- sc->dc_pmode = DC_PMODE_MII;
- break;
- case DC_DEVICEID_X3201:
- sc->dc_type = DC_TYPE_XIRCOM;
- sc->dc_flags |= DC_TX_INTR_ALWAYS | DC_TX_COALESCE |
- DC_TX_ALIGN;
- /*
- * We don't actually need to coalesce, but we're doing
- * it to obtain a double word aligned buffer.
- * The DC_TX_COALESCE flag is required.
- */
- sc->dc_pmode = DC_PMODE_MII;
- break;
- case DC_DEVICEID_RS7112:
- sc->dc_type = DC_TYPE_CONEXANT;
- sc->dc_flags |= DC_TX_INTR_ALWAYS;
- sc->dc_flags |= DC_REDUCED_MII_POLL;
- sc->dc_pmode = DC_PMODE_MII;
- dc_read_srom(sc, sc->dc_romwidth);
- break;
- default:
- device_printf(dev, "unknown device: %x\n", sc->dc_info->dc_did);
- break;
- }
-
- /* Save the cache line size. */
- if (DC_IS_DAVICOM(sc))
- sc->dc_cachesize = 0;
- else
- sc->dc_cachesize = pci_read_config(dev,
- DC_PCI_CFLT, 4) & 0xFF;
-
- /* Reset the adapter. */
- dc_reset(sc);
-
- /* Take 21143 out of snooze mode */
- if (DC_IS_INTEL(sc) || DC_IS_XIRCOM(sc)) {
- command = pci_read_config(dev, DC_PCI_CFDD, 4);
- command &= ~(DC_CFDD_SNOOZE_MODE | DC_CFDD_SLEEP_MODE);
- pci_write_config(dev, DC_PCI_CFDD, command, 4);
- }
-
- /*
- * Try to learn something about the supported media.
- * We know that ASIX and ADMtek and Davicom devices
- * will *always* be using MII media, so that's a no-brainer.
- * The tricky ones are the Macronix/PNIC II and the
- * Intel 21143.
- */
- if (DC_IS_INTEL(sc))
- dc_parse_21143_srom(sc);
- else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
- if (sc->dc_type == DC_TYPE_98713)
- sc->dc_pmode = DC_PMODE_MII;
- else
- sc->dc_pmode = DC_PMODE_SYM;
- } else if (!sc->dc_pmode)
- sc->dc_pmode = DC_PMODE_MII;
-
- /*
- * Get station address from the EEPROM.
- */
- switch(sc->dc_type) {
- case DC_TYPE_98713:
- case DC_TYPE_98713A:
- case DC_TYPE_987x5:
- case DC_TYPE_PNICII:
- dc_read_eeprom(sc, (caddr_t)&mac_offset,
- (DC_EE_NODEADDR_OFFSET / 2), 1, 0);
- dc_read_eeprom(sc, (caddr_t)&eaddr, (mac_offset / 2), 3, 0);
- break;
- case DC_TYPE_PNIC:
- dc_read_eeprom(sc, (caddr_t)&eaddr, 0, 3, 1);
- break;
- case DC_TYPE_DM9102:
- dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0);
-#ifdef __sparc64__
- /*
- * If this is an onboard dc(4) the station address read from
- * the EEPROM is all zero and we have to get it from the fcode.
- */
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- if (eaddr[i] != 0x00)
- break;
- if (i >= ETHER_ADDR_LEN)
- OF_getetheraddr(dev, eaddr);
-#endif
- break;
- case DC_TYPE_21143:
- case DC_TYPE_ASIX:
- dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0);
- break;
- case DC_TYPE_AL981:
- case DC_TYPE_AN985:
- *(u_int32_t *)(&eaddr[0]) = CSR_READ_4(sc, DC_AL_PAR0);
- *(u_int16_t *)(&eaddr[4]) = CSR_READ_4(sc, DC_AL_PAR1);
- break;
- case DC_TYPE_CONEXANT:
- bcopy(sc->dc_srom + DC_CONEXANT_EE_NODEADDR, &eaddr,
- ETHER_ADDR_LEN);
- break;
- case DC_TYPE_XIRCOM:
- /* The MAC comes from the CIS. */
- mac = pci_get_ether(dev);
- if (!mac) {
- device_printf(dev, "No station address in CIS!\n");
- error = ENXIO;
- goto fail;
- }
- bcopy(mac, eaddr, ETHER_ADDR_LEN);
- break;
- default:
- dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0);
- break;
- }
-
- /* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
- error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
- BUS_SPACE_MAXADDR, NULL, NULL, sizeof(struct dc_list_data), 1,
- sizeof(struct dc_list_data), 0, NULL, NULL, &sc->dc_ltag);
- if (error) {
- device_printf(dev, "failed to allocate busdma tag\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamem_alloc(sc->dc_ltag, (void **)&sc->dc_ldata,
- BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->dc_lmap);
- if (error) {
- device_printf(dev, "failed to allocate DMA safe memory\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamap_load(sc->dc_ltag, sc->dc_lmap, sc->dc_ldata,
- sizeof(struct dc_list_data), dc_dma_map_addr, &sc->dc_laddr,
- BUS_DMA_NOWAIT);
- if (error) {
- device_printf(dev, "cannot get address of the descriptors\n");
- error = ENXIO;
- goto fail;
- }
-
- /*
- * Allocate a busdma tag and DMA safe memory for the multicast
- * setup frame.
- */
- error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
- BUS_SPACE_MAXADDR, NULL, NULL, DC_SFRAME_LEN + DC_MIN_FRAMELEN, 1,
- DC_SFRAME_LEN + DC_MIN_FRAMELEN, 0, NULL, NULL, &sc->dc_stag);
- if (error) {
- device_printf(dev, "failed to allocate busdma tag\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamem_alloc(sc->dc_stag, (void **)&sc->dc_cdata.dc_sbuf,
- BUS_DMA_NOWAIT, &sc->dc_smap);
- if (error) {
- device_printf(dev, "failed to allocate DMA safe memory\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamap_load(sc->dc_stag, sc->dc_smap, sc->dc_cdata.dc_sbuf,
- DC_SFRAME_LEN, dc_dma_map_addr, &sc->dc_saddr, BUS_DMA_NOWAIT);
- if (error) {
- device_printf(dev, "cannot get address of the descriptors\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Allocate a busdma tag for mbufs. */
- error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
- BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, DC_TX_LIST_CNT, MCLBYTES,
- 0, NULL, NULL, &sc->dc_mtag);
- if (error) {
- device_printf(dev, "failed to allocate busdma tag\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Create the TX/RX busdma maps. */
- for (i = 0; i < DC_TX_LIST_CNT; i++) {
- error = bus_dmamap_create(sc->dc_mtag, 0,
- &sc->dc_cdata.dc_tx_map[i]);
- if (error) {
- device_printf(dev, "failed to init TX ring\n");
- error = ENXIO;
- goto fail;
- }
- }
- for (i = 0; i < DC_RX_LIST_CNT; i++) {
- error = bus_dmamap_create(sc->dc_mtag, 0,
- &sc->dc_cdata.dc_rx_map[i]);
- if (error) {
- device_printf(dev, "failed to init RX ring\n");
- error = ENXIO;
- goto fail;
- }
- }
- error = bus_dmamap_create(sc->dc_mtag, 0, &sc->dc_sparemap);
- if (error) {
- device_printf(dev, "failed to init RX ring\n");
- error = ENXIO;
- goto fail;
- }
-
- ifp = sc->dc_ifp = if_alloc(IFT_ETHER);
- if (ifp == NULL) {
- device_printf(dev, "can not if_alloc()\n");
- error = ENOSPC;
- goto fail;
- }
- ifp->if_softc = sc;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- /* XXX: bleah, MTU gets overwritten in ether_ifattach() */
- ifp->if_mtu = ETHERMTU;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = dc_ioctl;
- ifp->if_start = dc_start;
- ifp->if_watchdog = dc_watchdog;
- ifp->if_init = dc_init;
- ifp->if_baudrate = 10000000;
- IFQ_SET_MAXLEN(&ifp->if_snd, DC_TX_LIST_CNT - 1);
- ifp->if_snd.ifq_drv_maxlen = DC_TX_LIST_CNT - 1;
- IFQ_SET_READY(&ifp->if_snd);
-
- /*
- * Do MII setup. If this is a 21143, check for a PHY on the
- * MII bus after applying any necessary fixups to twiddle the
- * GPIO bits. If we don't end up finding a PHY, restore the
- * old selection (SIA only or SIA/SYM) and attach the dcphy
- * driver instead.
- */
- if (DC_IS_INTEL(sc)) {
- dc_apply_fixup(sc, IFM_AUTO);
- tmp = sc->dc_pmode;
- sc->dc_pmode = DC_PMODE_MII;
- }
-
- /*
- * Setup General Purpose port mode and data so the tulip can talk
- * to the MII. This needs to be done before mii_phy_probe so that
- * we can actually see them.
- */
- if (DC_IS_XIRCOM(sc)) {
- CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_WRITE_EN | DC_SIAGP_INT1_EN |
- DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT);
- DELAY(10);
- CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_INT1_EN |
- DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT);
- DELAY(10);
- }
-
- error = mii_phy_probe(dev, &sc->dc_miibus,
- dc_ifmedia_upd, dc_ifmedia_sts);
-
- if (error && DC_IS_INTEL(sc)) {
- sc->dc_pmode = tmp;
- if (sc->dc_pmode != DC_PMODE_SIA)
- sc->dc_pmode = DC_PMODE_SYM;
- sc->dc_flags |= DC_21143_NWAY;
- mii_phy_probe(dev, &sc->dc_miibus,
- dc_ifmedia_upd, dc_ifmedia_sts);
- /*
- * For non-MII cards, we need to have the 21143
- * drive the LEDs. Except there are some systems
- * like the NEC VersaPro NoteBook PC which have no
- * LEDs, and twiddling these bits has adverse effects
- * on them. (I.e. you suddenly can't get a link.)
- */
- if (pci_read_config(dev, DC_PCI_CSID, 4) != 0x80281033)
- sc->dc_flags |= DC_TULIP_LEDS;
- error = 0;
- }
-
- if (error) {
- device_printf(dev, "MII without any PHY!\n");
- goto fail;
- }
-
- if (DC_IS_ADMTEK(sc)) {
- /*
- * Set automatic TX underrun recovery for the ADMtek chips
- */
- DC_SETBIT(sc, DC_AL_CR, DC_AL_CR_ATUR);
- }
-
- /*
- * Tell the upper layer(s) we support long frames.
- */
- ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
- ifp->if_capabilities |= IFCAP_VLAN_MTU;
- ifp->if_capenable = ifp->if_capabilities;
-#ifdef DEVICE_POLLING
- ifp->if_capabilities |= IFCAP_POLLING;
-#endif
-
- callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0);
-
-#ifdef SRM_MEDIA
- sc->dc_srm_media = 0;
-
- /* Remember the SRM console media setting */
- if (DC_IS_INTEL(sc)) {
- command = pci_read_config(dev, DC_PCI_CFDD, 4);
- command &= ~(DC_CFDD_SNOOZE_MODE | DC_CFDD_SLEEP_MODE);
- switch ((command >> 8) & 0xff) {
- case 3:
- sc->dc_srm_media = IFM_10_T;
- break;
- case 4:
- sc->dc_srm_media = IFM_10_T | IFM_FDX;
- break;
- case 5:
- sc->dc_srm_media = IFM_100_TX;
- break;
- case 6:
- sc->dc_srm_media = IFM_100_TX | IFM_FDX;
- break;
- }
- if (sc->dc_srm_media)
- sc->dc_srm_media |= IFM_ACTIVE | IFM_ETHER;
- }
-#endif
-
- /*
- * Call MI attach routine.
- */
- ether_ifattach(ifp, eaddr);
-
- /* Hook interrupt last to avoid having to lock softc */
- error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | INTR_MPSAFE,
- dc_intr, sc, &sc->dc_intrhand);
-
- if (error) {
- device_printf(dev, "couldn't set up irq\n");
- ether_ifdetach(ifp);
- goto fail;
- }
-
-fail:
- if (error)
- dc_detach(dev);
- return (error);
-}
-
-/*
- * Shutdown hardware and free up resources. This can be called any
- * time after the mutex has been initialized. It is called in both
- * the error case in attach and the normal detach case so it needs
- * to be careful about only freeing resources that have actually been
- * allocated.
- */
-static int
-dc_detach(device_t dev)
-{
- struct dc_softc *sc;
- struct ifnet *ifp;
- struct dc_mediainfo *m;
- int i;
-
- sc = device_get_softc(dev);
- KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized"));
-
- ifp = sc->dc_ifp;
-
-#ifdef DEVICE_POLLING
- if (ifp->if_capenable & IFCAP_POLLING)
- ether_poll_deregister(ifp);
-#endif
-
- /* These should only be active if attach succeeded */
- if (device_is_attached(dev)) {
- DC_LOCK(sc);
- dc_stop(sc);
- DC_UNLOCK(sc);
- callout_drain(&sc->dc_stat_ch);
- ether_ifdetach(ifp);
- }
- if (sc->dc_miibus)
- device_delete_child(dev, sc->dc_miibus);
- bus_generic_detach(dev);
-
- if (sc->dc_intrhand)
- bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand);
- if (sc->dc_irq)
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq);
- if (sc->dc_res)
- bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res);
-
- if (ifp)
- if_free(ifp);
-
- if (sc->dc_cdata.dc_sbuf != NULL)
- bus_dmamem_free(sc->dc_stag, sc->dc_cdata.dc_sbuf, sc->dc_smap);
- if (sc->dc_ldata != NULL)
- bus_dmamem_free(sc->dc_ltag, sc->dc_ldata, sc->dc_lmap);
- if (sc->dc_mtag) {
- for (i = 0; i < DC_TX_LIST_CNT; i++)
- if (sc->dc_cdata.dc_tx_map[i] != NULL)
- bus_dmamap_destroy(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[i]);
- for (i = 0; i < DC_RX_LIST_CNT; i++)
- if (sc->dc_cdata.dc_rx_map[i] != NULL)
- bus_dmamap_destroy(sc->dc_mtag,
- sc->dc_cdata.dc_rx_map[i]);
- bus_dmamap_destroy(sc->dc_mtag, sc->dc_sparemap);
- }
- if (sc->dc_stag)
- bus_dma_tag_destroy(sc->dc_stag);
- if (sc->dc_mtag)
- bus_dma_tag_destroy(sc->dc_mtag);
- if (sc->dc_ltag)
- bus_dma_tag_destroy(sc->dc_ltag);
-
- free(sc->dc_pnic_rx_buf, M_DEVBUF);
-
- while (sc->dc_mi != NULL) {
- m = sc->dc_mi->dc_next;
- free(sc->dc_mi, M_DEVBUF);
- sc->dc_mi = m;
- }
- free(sc->dc_srom, M_DEVBUF);
-
- mtx_destroy(&sc->dc_mtx);
-
- return (0);
-}
-
-/*
- * Initialize the transmit descriptors.
- */
-static int
-dc_list_tx_init(struct dc_softc *sc)
-{
- struct dc_chain_data *cd;
- struct dc_list_data *ld;
- int i, nexti;
-
- cd = &sc->dc_cdata;
- ld = sc->dc_ldata;
- for (i = 0; i < DC_TX_LIST_CNT; i++) {
- if (i == DC_TX_LIST_CNT - 1)
- nexti = 0;
- else
- nexti = i + 1;
- ld->dc_tx_list[i].dc_next = htole32(DC_TXDESC(sc, nexti));
- cd->dc_tx_chain[i] = NULL;
- ld->dc_tx_list[i].dc_data = 0;
- ld->dc_tx_list[i].dc_ctl = 0;
- }
-
- cd->dc_tx_prod = cd->dc_tx_cons = cd->dc_tx_cnt = 0;
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- return (0);
-}
-
-
-/*
- * Initialize the RX descriptors and allocate mbufs for them. Note that
- * we arrange the descriptors in a closed ring, so that the last descriptor
- * points back to the first.
- */
-static int
-dc_list_rx_init(struct dc_softc *sc)
-{
- struct dc_chain_data *cd;
- struct dc_list_data *ld;
- int i, nexti;
-
- cd = &sc->dc_cdata;
- ld = sc->dc_ldata;
-
- for (i = 0; i < DC_RX_LIST_CNT; i++) {
- if (dc_newbuf(sc, i, 1) != 0)
- return (ENOBUFS);
- if (i == DC_RX_LIST_CNT - 1)
- nexti = 0;
- else
- nexti = i + 1;
- ld->dc_rx_list[i].dc_next = htole32(DC_RXDESC(sc, nexti));
- }
-
- cd->dc_rx_prod = 0;
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- return (0);
-}
-
-static void
-dc_dma_map_rxbuf(arg, segs, nseg, mapsize, error)
- void *arg;
- bus_dma_segment_t *segs;
- int nseg;
- bus_size_t mapsize;
- int error;
-{
- struct dc_softc *sc;
- struct dc_desc *c;
-
- sc = arg;
- c = &sc->dc_ldata->dc_rx_list[sc->dc_cdata.dc_rx_cur];
- if (error) {
- sc->dc_cdata.dc_rx_err = error;
- return;
- }
-
- KASSERT(nseg == 1, ("wrong number of segments, should be 1"));
- sc->dc_cdata.dc_rx_err = 0;
- c->dc_data = htole32(segs->ds_addr);
-}
-
-/*
- * Initialize an RX descriptor and attach an MBUF cluster.
- */
-static int
-dc_newbuf(struct dc_softc *sc, int i, int alloc)
-{
- struct mbuf *m_new;
- bus_dmamap_t tmp;
- int error;
-
- if (alloc) {
- m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- if (m_new == NULL)
- return (ENOBUFS);
- } else {
- m_new = sc->dc_cdata.dc_rx_chain[i];
- m_new->m_data = m_new->m_ext.ext_buf;
- }
- m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
- m_adj(m_new, sizeof(u_int64_t));
-
- /*
- * If this is a PNIC chip, zero the buffer. This is part
- * of the workaround for the receive bug in the 82c168 and
- * 82c169 chips.
- */
- if (sc->dc_flags & DC_PNIC_RX_BUG_WAR)
- bzero(mtod(m_new, char *), m_new->m_len);
-
- /* No need to remap the mbuf if we're reusing it. */
- if (alloc) {
- sc->dc_cdata.dc_rx_cur = i;
- error = bus_dmamap_load_mbuf(sc->dc_mtag, sc->dc_sparemap,
- m_new, dc_dma_map_rxbuf, sc, 0);
- if (error) {
- m_freem(m_new);
- return (error);
- }
- if (sc->dc_cdata.dc_rx_err != 0) {
- m_freem(m_new);
- return (sc->dc_cdata.dc_rx_err);
- }
- bus_dmamap_unload(sc->dc_mtag, sc->dc_cdata.dc_rx_map[i]);
- tmp = sc->dc_cdata.dc_rx_map[i];
- sc->dc_cdata.dc_rx_map[i] = sc->dc_sparemap;
- sc->dc_sparemap = tmp;
- sc->dc_cdata.dc_rx_chain[i] = m_new;
- }
-
- sc->dc_ldata->dc_rx_list[i].dc_ctl = htole32(DC_RXCTL_RLINK | DC_RXLEN);
- sc->dc_ldata->dc_rx_list[i].dc_status = htole32(DC_RXSTAT_OWN);
- bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_rx_map[i],
- BUS_DMASYNC_PREREAD);
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- return (0);
-}
-
-/*
- * Grrrrr.
- * The PNIC chip has a terrible bug in it that manifests itself during
- * periods of heavy activity. The exact mode of failure if difficult to
- * pinpoint: sometimes it only happens in promiscuous mode, sometimes it
- * will happen on slow machines. The bug is that sometimes instead of
- * uploading one complete frame during reception, it uploads what looks
- * like the entire contents of its FIFO memory. The frame we want is at
- * the end of the whole mess, but we never know exactly how much data has
- * been uploaded, so salvaging the frame is hard.
- *
- * There is only one way to do it reliably, and it's disgusting.
- * Here's what we know:
- *
- * - We know there will always be somewhere between one and three extra
- * descriptors uploaded.
- *
- * - We know the desired received frame will always be at the end of the
- * total data upload.
- *
- * - We know the size of the desired received frame because it will be
- * provided in the length field of the status word in the last descriptor.
- *
- * Here's what we do:
- *
- * - When we allocate buffers for the receive ring, we bzero() them.
- * This means that we know that the buffer contents should be all
- * zeros, except for data uploaded by the chip.
- *
- * - We also force the PNIC chip to upload frames that include the
- * ethernet CRC at the end.
- *
- * - We gather all of the bogus frame data into a single buffer.
- *
- * - We then position a pointer at the end of this buffer and scan
- * backwards until we encounter the first non-zero byte of data.
- * This is the end of the received frame. We know we will encounter
- * some data at the end of the frame because the CRC will always be
- * there, so even if the sender transmits a packet of all zeros,
- * we won't be fooled.
- *
- * - We know the size of the actual received frame, so we subtract
- * that value from the current pointer location. This brings us
- * to the start of the actual received packet.
- *
- * - We copy this into an mbuf and pass it on, along with the actual
- * frame length.
- *
- * The performance hit is tremendous, but it beats dropping frames all
- * the time.
- */
-
-#define DC_WHOLEFRAME (DC_RXSTAT_FIRSTFRAG | DC_RXSTAT_LASTFRAG)
-static void
-dc_pnic_rx_bug_war(struct dc_softc *sc, int idx)
-{
- struct dc_desc *cur_rx;
- struct dc_desc *c = NULL;
- struct mbuf *m = NULL;
- unsigned char *ptr;
- int i, total_len;
- u_int32_t rxstat = 0;
-
- i = sc->dc_pnic_rx_bug_save;
- cur_rx = &sc->dc_ldata->dc_rx_list[idx];
- ptr = sc->dc_pnic_rx_buf;
- bzero(ptr, DC_RXLEN * 5);
-
- /* Copy all the bytes from the bogus buffers. */
- while (1) {
- c = &sc->dc_ldata->dc_rx_list[i];
- rxstat = le32toh(c->dc_status);
- m = sc->dc_cdata.dc_rx_chain[i];
- bcopy(mtod(m, char *), ptr, DC_RXLEN);
- ptr += DC_RXLEN;
- /* If this is the last buffer, break out. */
- if (i == idx || rxstat & DC_RXSTAT_LASTFRAG)
- break;
- dc_newbuf(sc, i, 0);
- DC_INC(i, DC_RX_LIST_CNT);
- }
-
- /* Find the length of the actual receive frame. */
- total_len = DC_RXBYTES(rxstat);
-
- /* Scan backwards until we hit a non-zero byte. */
- while (*ptr == 0x00)
- ptr--;
-
- /* Round off. */
- if ((uintptr_t)(ptr) & 0x3)
- ptr -= 1;
-
- /* Now find the start of the frame. */
- ptr -= total_len;
- if (ptr < sc->dc_pnic_rx_buf)
- ptr = sc->dc_pnic_rx_buf;
-
- /*
- * Now copy the salvaged frame to the last mbuf and fake up
- * the status word to make it look like a successful
- * frame reception.
- */
- dc_newbuf(sc, i, 0);
- bcopy(ptr, mtod(m, char *), total_len);
- cur_rx->dc_status = htole32(rxstat | DC_RXSTAT_FIRSTFRAG);
-}
-
-/*
- * This routine searches the RX ring for dirty descriptors in the
- * event that the rxeof routine falls out of sync with the chip's
- * current descriptor pointer. This may happen sometimes as a result
- * of a "no RX buffer available" condition that happens when the chip
- * consumes all of the RX buffers before the driver has a chance to
- * process the RX ring. This routine may need to be called more than
- * once to bring the driver back in sync with the chip, however we
- * should still be getting RX DONE interrupts to drive the search
- * for new packets in the RX ring, so we should catch up eventually.
- */
-static int
-dc_rx_resync(struct dc_softc *sc)
-{
- struct dc_desc *cur_rx;
- int i, pos;
-
- pos = sc->dc_cdata.dc_rx_prod;
-
- for (i = 0; i < DC_RX_LIST_CNT; i++) {
- cur_rx = &sc->dc_ldata->dc_rx_list[pos];
- if (!(le32toh(cur_rx->dc_status) & DC_RXSTAT_OWN))
- break;
- DC_INC(pos, DC_RX_LIST_CNT);
- }
-
- /* If the ring really is empty, then just return. */
- if (i == DC_RX_LIST_CNT)
- return (0);
-
- /* We've fallen behing the chip: catch it. */
- sc->dc_cdata.dc_rx_prod = pos;
-
- return (EAGAIN);
-}
-
-/*
- * A frame has been uploaded: pass the resulting mbuf chain up to
- * the higher level protocols.
- */
-static void
-dc_rxeof(struct dc_softc *sc)
-{
- struct mbuf *m;
- struct ifnet *ifp;
- struct dc_desc *cur_rx;
- int i, total_len = 0;
- u_int32_t rxstat;
-
- DC_LOCK_ASSERT(sc);
-
- ifp = sc->dc_ifp;
- i = sc->dc_cdata.dc_rx_prod;
-
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap, BUS_DMASYNC_POSTREAD);
- while (!(le32toh(sc->dc_ldata->dc_rx_list[i].dc_status) &
- DC_RXSTAT_OWN)) {
-#ifdef DEVICE_POLLING
- if (ifp->if_capenable & IFCAP_POLLING) {
- if (sc->rxcycles <= 0)
- break;
- sc->rxcycles--;
- }
-#endif
- cur_rx = &sc->dc_ldata->dc_rx_list[i];
- rxstat = le32toh(cur_rx->dc_status);
- m = sc->dc_cdata.dc_rx_chain[i];
- bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_rx_map[i],
- BUS_DMASYNC_POSTREAD);
- total_len = DC_RXBYTES(rxstat);
-
- if (sc->dc_flags & DC_PNIC_RX_BUG_WAR) {
- if ((rxstat & DC_WHOLEFRAME) != DC_WHOLEFRAME) {
- if (rxstat & DC_RXSTAT_FIRSTFRAG)
- sc->dc_pnic_rx_bug_save = i;
- if ((rxstat & DC_RXSTAT_LASTFRAG) == 0) {
- DC_INC(i, DC_RX_LIST_CNT);
- continue;
- }
- dc_pnic_rx_bug_war(sc, i);
- rxstat = le32toh(cur_rx->dc_status);
- total_len = DC_RXBYTES(rxstat);
- }
- }
-
- /*
- * If an error occurs, update stats, clear the
- * status word and leave the mbuf cluster in place:
- * it should simply get re-used next time this descriptor
- * comes up in the ring. However, don't report long
- * frames as errors since they could be vlans.
- */
- if ((rxstat & DC_RXSTAT_RXERR)) {
- if (!(rxstat & DC_RXSTAT_GIANT) ||
- (rxstat & (DC_RXSTAT_CRCERR | DC_RXSTAT_DRIBBLE |
- DC_RXSTAT_MIIERE | DC_RXSTAT_COLLSEEN |
- DC_RXSTAT_RUNT | DC_RXSTAT_DE))) {
- ifp->if_ierrors++;
- if (rxstat & DC_RXSTAT_COLLSEEN)
- ifp->if_collisions++;
- dc_newbuf(sc, i, 0);
- if (rxstat & DC_RXSTAT_CRCERR) {
- DC_INC(i, DC_RX_LIST_CNT);
- continue;
- } else {
- dc_init_locked(sc);
- return;
- }
- }
- }
-
- /* No errors; receive the packet. */
- total_len -= ETHER_CRC_LEN;
-#ifdef __i386__
- /*
- * On the x86 we do not have alignment problems, so try to
- * allocate a new buffer for the receive ring, and pass up
- * the one where the packet is already, saving the expensive
- * copy done in m_devget().
- * If we are on an architecture with alignment problems, or
- * if the allocation fails, then use m_devget and leave the
- * existing buffer in the receive ring.
- */
- if (dc_quick && dc_newbuf(sc, i, 1) == 0) {
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = m->m_len = total_len;
- DC_INC(i, DC_RX_LIST_CNT);
- } else
-#endif
- {
- struct mbuf *m0;
-
- m0 = m_devget(mtod(m, char *), total_len,
- ETHER_ALIGN, ifp, NULL);
- dc_newbuf(sc, i, 0);
- DC_INC(i, DC_RX_LIST_CNT);
- if (m0 == NULL) {
- ifp->if_ierrors++;
- continue;
- }
- m = m0;
- }
-
- ifp->if_ipackets++;
- DC_UNLOCK(sc);
- (*ifp->if_input)(ifp, m);
- DC_LOCK(sc);
- }
-
- sc->dc_cdata.dc_rx_prod = i;
-}
-
-/*
- * A frame was downloaded to the chip. It's safe for us to clean up
- * the list buffers.
- */
-
-static void
-dc_txeof(struct dc_softc *sc)
-{
- struct dc_desc *cur_tx = NULL;
- struct ifnet *ifp;
- int idx;
- u_int32_t ctl, txstat;
-
- ifp = sc->dc_ifp;
-
- /*
- * Go through our tx list and free mbufs for those
- * frames that have been transmitted.
- */
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap, BUS_DMASYNC_POSTREAD);
- idx = sc->dc_cdata.dc_tx_cons;
- while (idx != sc->dc_cdata.dc_tx_prod) {
-
- cur_tx = &sc->dc_ldata->dc_tx_list[idx];
- txstat = le32toh(cur_tx->dc_status);
- ctl = le32toh(cur_tx->dc_ctl);
-
- if (txstat & DC_TXSTAT_OWN)
- break;
-
- if (!(ctl & DC_TXCTL_LASTFRAG) || ctl & DC_TXCTL_SETUP) {
- if (ctl & DC_TXCTL_SETUP) {
- /*
- * Yes, the PNIC is so brain damaged
- * that it will sometimes generate a TX
- * underrun error while DMAing the RX
- * filter setup frame. If we detect this,
- * we have to send the setup frame again,
- * or else the filter won't be programmed
- * correctly.
- */
- if (DC_IS_PNIC(sc)) {
- if (txstat & DC_TXSTAT_ERRSUM)
- dc_setfilt(sc);
- }
- sc->dc_cdata.dc_tx_chain[idx] = NULL;
- }
- sc->dc_cdata.dc_tx_cnt--;
- DC_INC(idx, DC_TX_LIST_CNT);
- continue;
- }
-
- if (DC_IS_XIRCOM(sc) || DC_IS_CONEXANT(sc)) {
- /*
- * XXX: Why does my Xircom taunt me so?
- * For some reason it likes setting the CARRLOST flag
- * even when the carrier is there. wtf?!?
- * Who knows, but Conexant chips have the
- * same problem. Maybe they took lessons
- * from Xircom.
- */
- if (/*sc->dc_type == DC_TYPE_21143 &&*/
- sc->dc_pmode == DC_PMODE_MII &&
- ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM |
- DC_TXSTAT_NOCARRIER)))
- txstat &= ~DC_TXSTAT_ERRSUM;
- } else {
- if (/*sc->dc_type == DC_TYPE_21143 &&*/
- sc->dc_pmode == DC_PMODE_MII &&
- ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM |
- DC_TXSTAT_NOCARRIER | DC_TXSTAT_CARRLOST)))
- txstat &= ~DC_TXSTAT_ERRSUM;
- }
-
- if (txstat & DC_TXSTAT_ERRSUM) {
- ifp->if_oerrors++;
- if (txstat & DC_TXSTAT_EXCESSCOLL)
- ifp->if_collisions++;
- if (txstat & DC_TXSTAT_LATECOLL)
- ifp->if_collisions++;
- if (!(txstat & DC_TXSTAT_UNDERRUN)) {
- dc_init_locked(sc);
- return;
- }
- }
-
- ifp->if_collisions += (txstat & DC_TXSTAT_COLLCNT) >> 3;
-
- ifp->if_opackets++;
- if (sc->dc_cdata.dc_tx_chain[idx] != NULL) {
- bus_dmamap_sync(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[idx],
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[idx]);
- m_freem(sc->dc_cdata.dc_tx_chain[idx]);
- sc->dc_cdata.dc_tx_chain[idx] = NULL;
- }
-
- sc->dc_cdata.dc_tx_cnt--;
- DC_INC(idx, DC_TX_LIST_CNT);
- }
-
- if (idx != sc->dc_cdata.dc_tx_cons) {
- /* Some buffers have been freed. */
- sc->dc_cdata.dc_tx_cons = idx;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- }
- ifp->if_timer = (sc->dc_cdata.dc_tx_cnt == 0) ? 0 : 5;
-}
-
-static void
-dc_tick(void *xsc)
-{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifnet *ifp;
- u_int32_t r;
-
- sc = xsc;
- DC_LOCK_ASSERT(sc);
- ifp = sc->dc_ifp;
- mii = device_get_softc(sc->dc_miibus);
-
- if (sc->dc_flags & DC_REDUCED_MII_POLL) {
- if (sc->dc_flags & DC_21143_NWAY) {
- r = CSR_READ_4(sc, DC_10BTSTAT);
- if (IFM_SUBTYPE(mii->mii_media_active) ==
- IFM_100_TX && (r & DC_TSTAT_LS100)) {
- sc->dc_link = 0;
- mii_mediachg(mii);
- }
- if (IFM_SUBTYPE(mii->mii_media_active) ==
- IFM_10_T && (r & DC_TSTAT_LS10)) {
- sc->dc_link = 0;
- mii_mediachg(mii);
- }
- if (sc->dc_link == 0)
- mii_tick(mii);
- } else {
- r = CSR_READ_4(sc, DC_ISR);
- if ((r & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT &&
- sc->dc_cdata.dc_tx_cnt == 0) {
- mii_tick(mii);
- if (!(mii->mii_media_status & IFM_ACTIVE))
- sc->dc_link = 0;
- }
- }
- } else
- mii_tick(mii);
-
- /*
- * When the init routine completes, we expect to be able to send
- * packets right away, and in fact the network code will send a
- * gratuitous ARP the moment the init routine marks the interface
- * as running. However, even though the MAC may have been initialized,
- * there may be a delay of a few seconds before the PHY completes
- * autonegotiation and the link is brought up. Any transmissions
- * made during that delay will be lost. Dealing with this is tricky:
- * we can't just pause in the init routine while waiting for the
- * PHY to come ready since that would bring the whole system to
- * a screeching halt for several seconds.
- *
- * What we do here is prevent the TX start routine from sending
- * any packets until a link has been established. After the
- * interface has been initialized, the tick routine will poll
- * the state of the PHY until the IFM_ACTIVE flag is set. Until
- * that time, packets will stay in the send queue, and once the
- * link comes up, they will be flushed out to the wire.
- */
- if (!sc->dc_link && mii->mii_media_status & IFM_ACTIVE &&
- IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
- sc->dc_link++;
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start_locked(ifp);
- }
-
- if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link)
- callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
- else
- callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
-}
-
-/*
- * A transmit underrun has occurred. Back off the transmit threshold,
- * or switch to store and forward mode if we have to.
- */
-static void
-dc_tx_underrun(struct dc_softc *sc)
-{
- u_int32_t isr;
- int i;
-
- if (DC_IS_DAVICOM(sc))
- dc_init_locked(sc);
-
- if (DC_IS_INTEL(sc)) {
- /*
- * The real 21143 requires that the transmitter be idle
- * in order to change the transmit threshold or store
- * and forward state.
- */
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
-
- for (i = 0; i < DC_TIMEOUT; i++) {
- isr = CSR_READ_4(sc, DC_ISR);
- if (isr & DC_ISR_TX_IDLE)
- break;
- DELAY(10);
- }
- if (i == DC_TIMEOUT) {
- if_printf(sc->dc_ifp,
- "failed to force tx to idle state\n");
- dc_init_locked(sc);
- }
- }
-
- if_printf(sc->dc_ifp, "TX underrun -- ");
- sc->dc_txthresh += DC_TXTHRESH_INC;
- if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
- printf("using store and forward mode\n");
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
- } else {
- printf("increasing TX threshold\n");
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
- DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
- }
-
- if (DC_IS_INTEL(sc))
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
-}
-
-#ifdef DEVICE_POLLING
-static poll_handler_t dc_poll;
-
-static void
-dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
-{
- struct dc_softc *sc = ifp->if_softc;
-
- DC_LOCK(sc);
-
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- DC_UNLOCK(sc);
- return;
- }
-
- sc->rxcycles = count;
- dc_rxeof(sc);
- dc_txeof(sc);
- if (!IFQ_IS_EMPTY(&ifp->if_snd) &&
- !(ifp->if_drv_flags & IFF_DRV_OACTIVE))
- dc_start_locked(ifp);
-
- if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
- u_int32_t status;
-
- status = CSR_READ_4(sc, DC_ISR);
- status &= (DC_ISR_RX_WATDOGTIMEO | DC_ISR_RX_NOBUF |
- DC_ISR_TX_NOBUF | DC_ISR_TX_IDLE | DC_ISR_TX_UNDERRUN |
- DC_ISR_BUS_ERR);
- if (!status) {
- DC_UNLOCK(sc);
- return;
- }
- /* ack what we have */
- CSR_WRITE_4(sc, DC_ISR, status);
-
- if (status & (DC_ISR_RX_WATDOGTIMEO | DC_ISR_RX_NOBUF)) {
- u_int32_t r = CSR_READ_4(sc, DC_FRAMESDISCARDED);
- ifp->if_ierrors += (r & 0xffff) + ((r >> 17) & 0x7ff);
-
- if (dc_rx_resync(sc))
- dc_rxeof(sc);
- }
- /* restart transmit unit if necessary */
- if (status & DC_ISR_TX_IDLE && sc->dc_cdata.dc_tx_cnt)
- CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
-
- if (status & DC_ISR_TX_UNDERRUN)
- dc_tx_underrun(sc);
-
- if (status & DC_ISR_BUS_ERR) {
- if_printf(ifp, "dc_poll: bus error\n");
- dc_reset(sc);
- dc_init_locked(sc);
- }
- }
- DC_UNLOCK(sc);
-}
-#endif /* DEVICE_POLLING */
-
-static void
-dc_intr(void *arg)
-{
- struct dc_softc *sc;
- struct ifnet *ifp;
- u_int32_t status;
-
- sc = arg;
-
- if (sc->suspended)
- return;
-
- if ((CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0)
- return;
-
- DC_LOCK(sc);
- ifp = sc->dc_ifp;
-#ifdef DEVICE_POLLING
- if (ifp->if_capenable & IFCAP_POLLING) {
- DC_UNLOCK(sc);
- return;
- }
-#endif
-
- /* Suppress unwanted interrupts */
- if (!(ifp->if_flags & IFF_UP)) {
- if (CSR_READ_4(sc, DC_ISR) & DC_INTRS)
- dc_stop(sc);
- DC_UNLOCK(sc);
- return;
- }
-
- /* Disable interrupts. */
- CSR_WRITE_4(sc, DC_IMR, 0x00000000);
-
- while (((status = CSR_READ_4(sc, DC_ISR)) & DC_INTRS)
- && status != 0xFFFFFFFF) {
-
- CSR_WRITE_4(sc, DC_ISR, status);
-
- if (status & DC_ISR_RX_OK) {
- int curpkts;
- curpkts = ifp->if_ipackets;
- dc_rxeof(sc);
- if (curpkts == ifp->if_ipackets) {
- while (dc_rx_resync(sc))
- dc_rxeof(sc);
- }
- }
-
- if (status & (DC_ISR_TX_OK | DC_ISR_TX_NOBUF))
- dc_txeof(sc);
-
- if (status & DC_ISR_TX_IDLE) {
- dc_txeof(sc);
- if (sc->dc_cdata.dc_tx_cnt) {
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
- CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
- }
- }
-
- if (status & DC_ISR_TX_UNDERRUN)
- dc_tx_underrun(sc);
-
- if ((status & DC_ISR_RX_WATDOGTIMEO)
- || (status & DC_ISR_RX_NOBUF)) {
- int curpkts;
- curpkts = ifp->if_ipackets;
- dc_rxeof(sc);
- if (curpkts == ifp->if_ipackets) {
- while (dc_rx_resync(sc))
- dc_rxeof(sc);
- }
- }
-
- if (status & DC_ISR_BUS_ERR) {
- dc_reset(sc);
- dc_init_locked(sc);
- }
- }
-
- /* Re-enable interrupts. */
- CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
-
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start_locked(ifp);
-
- DC_UNLOCK(sc);
-}
-
-static void
-dc_dma_map_txbuf(arg, segs, nseg, mapsize, error)
- void *arg;
- bus_dma_segment_t *segs;
- int nseg;
- bus_size_t mapsize;
- int error;
-{
- struct dc_softc *sc;
- struct dc_desc *f;
- int cur, first, frag, i;
-
- sc = arg;
- if (error) {
- sc->dc_cdata.dc_tx_err = error;
- return;
- }
-
- first = cur = frag = sc->dc_cdata.dc_tx_prod;
- for (i = 0; i < nseg; i++) {
- if ((sc->dc_flags & DC_TX_ADMTEK_WAR) &&
- (frag == (DC_TX_LIST_CNT - 1)) &&
- (first != sc->dc_cdata.dc_tx_first)) {
- bus_dmamap_unload(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[first]);
- sc->dc_cdata.dc_tx_err = ENOBUFS;
- return;
- }
-
- f = &sc->dc_ldata->dc_tx_list[frag];
- f->dc_ctl = htole32(DC_TXCTL_TLINK | segs[i].ds_len);
- if (i == 0) {
- f->dc_status = 0;
- f->dc_ctl |= htole32(DC_TXCTL_FIRSTFRAG);
- } else
- f->dc_status = htole32(DC_TXSTAT_OWN);
- f->dc_data = htole32(segs[i].ds_addr);
- cur = frag;
- DC_INC(frag, DC_TX_LIST_CNT);
- }
-
- sc->dc_cdata.dc_tx_err = 0;
- sc->dc_cdata.dc_tx_prod = frag;
- sc->dc_cdata.dc_tx_cnt += nseg;
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_LASTFRAG);
- sc->dc_cdata.dc_tx_chain[cur] = sc->dc_cdata.dc_tx_mapping;
- if (sc->dc_flags & DC_TX_INTR_FIRSTFRAG)
- sc->dc_ldata->dc_tx_list[first].dc_ctl |=
- htole32(DC_TXCTL_FINT);
- if (sc->dc_flags & DC_TX_INTR_ALWAYS)
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
- if (sc->dc_flags & DC_TX_USE_TX_INTR && sc->dc_cdata.dc_tx_cnt > 64)
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
- sc->dc_ldata->dc_tx_list[first].dc_status = htole32(DC_TXSTAT_OWN);
-}
-
-/*
- * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
- * pointers to the fragment pointers.
- */
-static int
-dc_encap(struct dc_softc *sc, struct mbuf **m_head)
-{
- struct mbuf *m;
- int error, idx, chainlen = 0;
-
- /*
- * If there's no way we can send any packets, return now.
- */
- if (DC_TX_LIST_CNT - sc->dc_cdata.dc_tx_cnt < 6)
- return (ENOBUFS);
-
- /*
- * Count the number of frags in this chain to see if
- * we need to m_defrag. Since the descriptor list is shared
- * by all packets, we'll m_defrag long chains so that they
- * do not use up the entire list, even if they would fit.
- */
- for (m = *m_head; m != NULL; m = m->m_next)
- chainlen++;
-
- if ((chainlen > DC_TX_LIST_CNT / 4) ||
- ((DC_TX_LIST_CNT - (chainlen + sc->dc_cdata.dc_tx_cnt)) < 6)) {
- m = m_defrag(*m_head, M_DONTWAIT);
- if (m == NULL)
- return (ENOBUFS);
- *m_head = m;
- }
-
- /*
- * Start packing the mbufs in this chain into
- * the fragment pointers. Stop when we run out
- * of fragments or hit the end of the mbuf chain.
- */
- idx = sc->dc_cdata.dc_tx_prod;
- sc->dc_cdata.dc_tx_mapping = *m_head;
- error = bus_dmamap_load_mbuf(sc->dc_mtag, sc->dc_cdata.dc_tx_map[idx],
- *m_head, dc_dma_map_txbuf, sc, 0);
- if (error)
- return (error);
- if (sc->dc_cdata.dc_tx_err != 0)
- return (sc->dc_cdata.dc_tx_err);
- bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_tx_map[idx],
- BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- return (0);
-}
-
-/*
- * Main transmit routine. To avoid having to do mbuf copies, we put pointers
- * to the mbuf data regions directly in the transmit lists. We also save a
- * copy of the pointers since the transmit list fragment pointers are
- * physical addresses.
- */
-
-static void
-dc_start(struct ifnet *ifp)
-{
- struct dc_softc *sc;
-
- sc = ifp->if_softc;
- DC_LOCK(sc);
- dc_start_locked(ifp);
- DC_UNLOCK(sc);
-}
-
-static void
-dc_start_locked(struct ifnet *ifp)
-{
- struct dc_softc *sc;
- struct mbuf *m_head = NULL, *m;
- unsigned int queued = 0;
- int idx;
-
- sc = ifp->if_softc;
-
- DC_LOCK_ASSERT(sc);
-
- if (!sc->dc_link && ifp->if_snd.ifq_len < 10)
- return;
-
- if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
- return;
-
- idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
-
- while (sc->dc_cdata.dc_tx_chain[idx] == NULL) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
- if (m_head == NULL)
- break;
-
- if (sc->dc_flags & DC_TX_COALESCE &&
- (m_head->m_next != NULL ||
- sc->dc_flags & DC_TX_ALIGN)) {
- m = m_defrag(m_head, M_DONTWAIT);
- if (m == NULL) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- } else {
- m_head = m;
- }
- }
-
- if (dc_encap(sc, &m_head)) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
- idx = sc->dc_cdata.dc_tx_prod;
-
- queued++;
- /*
- * If there's a BPF listener, bounce a copy of this frame
- * to him.
- */
- BPF_MTAP(ifp, m_head);
-
- if (sc->dc_flags & DC_TX_ONE) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
- }
-
- if (queued > 0) {
- /* Transmit */
- if (!(sc->dc_flags & DC_TX_POLL))
- CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
-
- /*
- * Set a timeout in case the chip goes out to lunch.
- */
- ifp->if_timer = 5;
- }
-}
-
-static void
-dc_init(void *xsc)
-{
- struct dc_softc *sc = xsc;
-
- DC_LOCK(sc);
- dc_init_locked(sc);
-#ifdef SRM_MEDIA
- if(sc->dc_srm_media) {
- struct ifreq ifr;
- struct mii_data *mii;
-
- ifr.ifr_media = sc->dc_srm_media;
- sc->dc_srm_media = 0;
- DC_UNLOCK(sc);
- mii = device_get_softc(sc->dc_miibus);
- ifmedia_ioctl(sc->dc_ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
- } else
-#endif
- DC_UNLOCK(sc);
-}
-
-static void
-dc_init_locked(struct dc_softc *sc)
-{
- struct ifnet *ifp = sc->dc_ifp;
- struct mii_data *mii;
-
- DC_LOCK_ASSERT(sc);
-
- mii = device_get_softc(sc->dc_miibus);
-
- /*
- * Cancel pending I/O and free all RX/TX buffers.
- */
- dc_stop(sc);
- dc_reset(sc);
-
- /*
- * Set cache alignment and burst length.
- */
- if (DC_IS_ASIX(sc) || DC_IS_DAVICOM(sc))
- CSR_WRITE_4(sc, DC_BUSCTL, 0);
- else
- CSR_WRITE_4(sc, DC_BUSCTL, DC_BUSCTL_MRME | DC_BUSCTL_MRLE);
- /*
- * Evenly share the bus between receive and transmit process.
- */
- if (DC_IS_INTEL(sc))
- DC_SETBIT(sc, DC_BUSCTL, DC_BUSCTL_ARBITRATION);
- if (DC_IS_DAVICOM(sc) || DC_IS_INTEL(sc)) {
- DC_SETBIT(sc, DC_BUSCTL, DC_BURSTLEN_USECA);
- } else {
- DC_SETBIT(sc, DC_BUSCTL, DC_BURSTLEN_16LONG);
- }
- if (sc->dc_flags & DC_TX_POLL)
- DC_SETBIT(sc, DC_BUSCTL, DC_TXPOLL_1);
- switch(sc->dc_cachesize) {
- case 32:
- DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_32LONG);
- break;
- case 16:
- DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_16LONG);
- break;
- case 8:
- DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_8LONG);
- break;
- case 0:
- default:
- DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_NONE);
- break;
- }
-
- if (sc->dc_flags & DC_TX_STORENFWD)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
- else {
- if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
- } else {
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
- DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
- }
- }
-
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_NO_RXCRC);
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_BACKOFF);
-
- if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
- /*
- * The app notes for the 98713 and 98715A say that
- * in order to have the chips operate properly, a magic
- * number must be written to CSR16. Macronix does not
- * document the meaning of these bits so there's no way
- * to know exactly what they do. The 98713 has a magic
- * number all its own; the rest all use a different one.
- */
- DC_CLRBIT(sc, DC_MX_MAGICPACKET, 0xFFFF0000);
- if (sc->dc_type == DC_TYPE_98713)
- DC_SETBIT(sc, DC_MX_MAGICPACKET, DC_MX_MAGIC_98713);
- else
- DC_SETBIT(sc, DC_MX_MAGICPACKET, DC_MX_MAGIC_98715);
- }
-
- if (DC_IS_XIRCOM(sc)) {
- /*
- * setup General Purpose Port mode and data so the tulip
- * can talk to the MII.
- */
- CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_WRITE_EN | DC_SIAGP_INT1_EN |
- DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT);
- DELAY(10);
- CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_INT1_EN |
- DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT);
- DELAY(10);
- }
-
- DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
- DC_SETBIT(sc, DC_NETCFG, DC_TXTHRESH_MIN);
-
- /* Init circular RX list. */
- if (dc_list_rx_init(sc) == ENOBUFS) {
- if_printf(ifp,
- "initialization failed: no memory for rx buffers\n");
- dc_stop(sc);
- return;
- }
-
- /*
- * Init TX descriptors.
- */
- dc_list_tx_init(sc);
-
- /*
- * Load the address of the RX list.
- */
- CSR_WRITE_4(sc, DC_RXADDR, DC_RXDESC(sc, 0));
- CSR_WRITE_4(sc, DC_TXADDR, DC_TXDESC(sc, 0));
-
- /*
- * Enable interrupts.
- */
-#ifdef DEVICE_POLLING
- /*
- * ... but only if we are not polling, and make sure they are off in
- * the case of polling. Some cards (e.g. fxp) turn interrupts on
- * after a reset.
- */
- if (ifp->if_capenable & IFCAP_POLLING)
- CSR_WRITE_4(sc, DC_IMR, 0x00000000);
- else
-#endif
- CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
- CSR_WRITE_4(sc, DC_ISR, 0xFFFFFFFF);
-
- /* Enable transmitter. */
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
-
- /*
- * If this is an Intel 21143 and we're not using the
- * MII port, program the LED control pins so we get
- * link and activity indications.
- */
- if (sc->dc_flags & DC_TULIP_LEDS) {
- CSR_WRITE_4(sc, DC_WATCHDOG,
- DC_WDOG_CTLWREN | DC_WDOG_LINK | DC_WDOG_ACTIVITY);
- CSR_WRITE_4(sc, DC_WATCHDOG, 0);
- }
-
- /*
- * Load the RX/multicast filter. We do this sort of late
- * because the filter programming scheme on the 21143 and
- * some clones requires DMAing a setup frame via the TX
- * engine, and we need the transmitter enabled for that.
- */
- dc_setfilt(sc);
-
- /* Enable receiver. */
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON);
- CSR_WRITE_4(sc, DC_RXSTART, 0xFFFFFFFF);
-
- mii_mediachg(mii);
- dc_setcfg(sc, sc->dc_if_media);
-
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
- /* Don't start the ticker if this is a homePNA link. */
- if (IFM_SUBTYPE(mii->mii_media.ifm_media) == IFM_HPNA_1)
- sc->dc_link = 1;
- else {
- if (sc->dc_flags & DC_21143_NWAY)
- callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
- else
- callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
- }
-}
-
-/*
- * Set media options.
- */
-static int
-dc_ifmedia_upd(struct ifnet *ifp)
-{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifmedia *ifm;
-
- sc = ifp->if_softc;
- mii = device_get_softc(sc->dc_miibus);
- DC_LOCK(sc);
- mii_mediachg(mii);
- ifm = &mii->mii_media;
-
- if (DC_IS_DAVICOM(sc) &&
- IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
- dc_setcfg(sc, ifm->ifm_media);
- else
- sc->dc_link = 0;
- DC_UNLOCK(sc);
-
- return (0);
-}
-
-/*
- * Report current media status.
- */
-static void
-dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
-{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifmedia *ifm;
-
- sc = ifp->if_softc;
- mii = device_get_softc(sc->dc_miibus);
- DC_LOCK(sc);
- mii_pollstat(mii);
- ifm = &mii->mii_media;
- if (DC_IS_DAVICOM(sc)) {
- if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) {
- ifmr->ifm_active = ifm->ifm_media;
- ifmr->ifm_status = 0;
- return;
- }
- }
- ifmr->ifm_active = mii->mii_media_active;
- ifmr->ifm_status = mii->mii_media_status;
- DC_UNLOCK(sc);
-}
-
-static int
-dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
-{
- struct dc_softc *sc = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *)data;
- struct mii_data *mii;
- int error = 0;
-
- switch (command) {
- case SIOCSIFFLAGS:
- DC_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) &
- (IFF_PROMISC | IFF_ALLMULTI);
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if (need_setfilt)
- dc_setfilt(sc);
- } else {
- sc->dc_txthresh = 0;
- dc_init_locked(sc);
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- dc_stop(sc);
- }
- sc->dc_if_flags = ifp->if_flags;
- DC_UNLOCK(sc);
- error = 0;
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- DC_LOCK(sc);
- dc_setfilt(sc);
- DC_UNLOCK(sc);
- error = 0;
- break;
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
- mii = device_get_softc(sc->dc_miibus);
- error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
-#ifdef SRM_MEDIA
- DC_LOCK(sc);
- if (sc->dc_srm_media)
- sc->dc_srm_media = 0;
- DC_UNLOCK(sc);
-#endif
- break;
- case SIOCSIFCAP:
-#ifdef DEVICE_POLLING
- if (ifr->ifr_reqcap & IFCAP_POLLING &&
- !(ifp->if_capenable & IFCAP_POLLING)) {
- error = ether_poll_register(dc_poll, ifp);
- if (error)
- return(error);
- DC_LOCK(sc);
- /* Disable interrupts */
- CSR_WRITE_4(sc, DC_IMR, 0x00000000);
- ifp->if_capenable |= IFCAP_POLLING;
- DC_UNLOCK(sc);
- return (error);
-
- }
- if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
- ifp->if_capenable & IFCAP_POLLING) {
- error = ether_poll_deregister(ifp);
- /* Enable interrupts. */
- DC_LOCK(sc);
- CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
- ifp->if_capenable &= ~IFCAP_POLLING;
- DC_UNLOCK(sc);
- return (error);
- }
-#endif /* DEVICE_POLLING */
- break;
- default:
- error = ether_ioctl(ifp, command, data);
- break;
- }
-
- return (error);
-}
-
-static void
-dc_watchdog(struct ifnet *ifp)
-{
- struct dc_softc *sc;
-
- sc = ifp->if_softc;
-
- DC_LOCK(sc);
-
- ifp->if_oerrors++;
- if_printf(ifp, "watchdog timeout\n");
-
- dc_stop(sc);
- dc_reset(sc);
- dc_init_locked(sc);
-
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start_locked(ifp);
-
- DC_UNLOCK(sc);
-}
-
-/*
- * Stop the adapter and free any mbufs allocated to the
- * RX and TX lists.
- */
-static void
-dc_stop(struct dc_softc *sc)
-{
- struct ifnet *ifp;
- struct dc_list_data *ld;
- struct dc_chain_data *cd;
- int i;
- u_int32_t ctl;
-
- DC_LOCK_ASSERT(sc);
-
- ifp = sc->dc_ifp;
- ifp->if_timer = 0;
- ld = sc->dc_ldata;
- cd = &sc->dc_cdata;
-
- callout_stop(&sc->dc_stat_ch);
-
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
- DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON));
- CSR_WRITE_4(sc, DC_IMR, 0x00000000);
- CSR_WRITE_4(sc, DC_TXADDR, 0x00000000);
- CSR_WRITE_4(sc, DC_RXADDR, 0x00000000);
- sc->dc_link = 0;
-
- /*
- * Free data in the RX lists.
- */
- for (i = 0; i < DC_RX_LIST_CNT; i++) {
- if (cd->dc_rx_chain[i] != NULL) {
- m_freem(cd->dc_rx_chain[i]);
- cd->dc_rx_chain[i] = NULL;
- }
- }
- bzero(&ld->dc_rx_list, sizeof(ld->dc_rx_list));
-
- /*
- * Free the TX list buffers.
- */
- for (i = 0; i < DC_TX_LIST_CNT; i++) {
- if (cd->dc_tx_chain[i] != NULL) {
- ctl = le32toh(ld->dc_tx_list[i].dc_ctl);
- if ((ctl & DC_TXCTL_SETUP) ||
- !(ctl & DC_TXCTL_LASTFRAG)) {
- cd->dc_tx_chain[i] = NULL;
- continue;
- }
- bus_dmamap_unload(sc->dc_mtag, cd->dc_tx_map[i]);
- m_freem(cd->dc_tx_chain[i]);
- cd->dc_tx_chain[i] = NULL;
- }
- }
- bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list));
-}
-
-/*
- * Device suspend routine. Stop the interface and save some PCI
- * settings in case the BIOS doesn't restore them properly on
- * resume.
- */
-static int
-dc_suspend(device_t dev)
-{
- struct dc_softc *sc;
-
- sc = device_get_softc(dev);
- DC_LOCK(sc);
- dc_stop(sc);
- sc->suspended = 1;
- DC_UNLOCK(sc);
-
- return (0);
-}
-
-/*
- * Device resume routine. Restore some PCI settings in case the BIOS
- * doesn't, re-enable busmastering, and restart the interface if
- * appropriate.
- */
-static int
-dc_resume(device_t dev)
-{
- struct dc_softc *sc;
- struct ifnet *ifp;
-
- sc = device_get_softc(dev);
- ifp = sc->dc_ifp;
-
- /* reinitialize interface if necessary */
- DC_LOCK(sc);
- if (ifp->if_flags & IFF_UP)
- dc_init_locked(sc);
-
- sc->suspended = 0;
- DC_UNLOCK(sc);
-
- return (0);
-}
-
-/*
- * Stop all chip I/O so that the kernel's probe routines don't
- * get confused by errant DMAs when rebooting.
- */
-static void
-dc_shutdown(device_t dev)
-{
- struct dc_softc *sc;
-
- sc = device_get_softc(dev);
-
- DC_LOCK(sc);
- dc_stop(sc);
- DC_UNLOCK(sc);
-}
diff --git a/sys/pci/if_dcreg.h b/sys/pci/if_dcreg.h
deleted file mode 100644
index ecf9962..0000000
--- a/sys/pci/if_dcreg.h
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*-
- * Copyright (c) 1997, 1998, 1999
- * Bill Paul <wpaul@ee.columbia.edu>. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Bill Paul.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
- * 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$
- */
-
-/*
- * 21143 and clone common register definitions.
- */
-
-#define DC_BUSCTL 0x00 /* bus control */
-#define DC_TXSTART 0x08 /* tx start demand */
-#define DC_RXSTART 0x10 /* rx start demand */
-#define DC_RXADDR 0x18 /* rx descriptor list start addr */
-#define DC_TXADDR 0x20 /* tx descriptor list start addr */
-#define DC_ISR 0x28 /* interrupt status register */
-#define DC_NETCFG 0x30 /* network config register */
-#define DC_IMR 0x38 /* interrupt mask */
-#define DC_FRAMESDISCARDED 0x40 /* # of discarded frames */
-#define DC_SIO 0x48 /* MII and ROM/EEPROM access */
-#define DC_ROM 0x50 /* ROM programming address */
-#define DC_TIMER 0x58 /* general timer */
-#define DC_10BTSTAT 0x60 /* SIA status */
-#define DC_SIARESET 0x68 /* SIA connectivity */
-#define DC_10BTCTRL 0x70 /* SIA transmit and receive */
-#define DC_WATCHDOG 0x78 /* SIA and general purpose port */
-#define DC_SIAGP 0x78 /* SIA and general purpose port (X3201) */
-
-/*
- * There are two general 'types' of MX chips that we need to be
- * concerned with. One is the original 98713, which has its internal
- * NWAY support controlled via the MDIO bits in the serial I/O
- * register. The other is everything else (from the 98713A on up),
- * which has its internal NWAY controlled via CSR13, CSR14 and CSR15,
- * just like the 21143. This type setting also governs which of the
- * 'magic' numbers we write to CSR16. The PNIC II falls into the
- * 98713A/98715/98715A/98725 category.
- */
-#define DC_TYPE_98713 0x1
-#define DC_TYPE_98713A 0x2
-#define DC_TYPE_987x5 0x3
-
-/* Other type of supported chips. */
-#define DC_TYPE_21143 0x4 /* Intel 21143 */
-#define DC_TYPE_ASIX 0x5 /* ASIX AX88140A/AX88141 */
-#define DC_TYPE_AL981 0x6 /* ADMtek AL981 Comet */
-#define DC_TYPE_AN985 0x7 /* ADMtek AN985 Centaur */
-#define DC_TYPE_DM9102 0x8 /* Davicom DM9102 */
-#define DC_TYPE_PNICII 0x9 /* 82c115 PNIC II */
-#define DC_TYPE_PNIC 0xA /* 82c168/82c169 PNIC I */
-#define DC_TYPE_XIRCOM 0xB /* Xircom X3201 */
-#define DC_TYPE_CONEXANT 0xC /* Conexant LANfinity RS7112 */
-
-#define DC_IS_MACRONIX(x) \
- (x->dc_type == DC_TYPE_98713 || \
- x->dc_type == DC_TYPE_98713A || \
- x->dc_type == DC_TYPE_987x5)
-
-#define DC_IS_ADMTEK(x) \
- (x->dc_type == DC_TYPE_AL981 || \
- x->dc_type == DC_TYPE_AN985)
-
-#define DC_IS_INTEL(x) (x->dc_type == DC_TYPE_21143)
-#define DC_IS_ASIX(x) (x->dc_type == DC_TYPE_ASIX)
-#define DC_IS_COMET(x) (x->dc_type == DC_TYPE_AL981)
-#define DC_IS_CENTAUR(x) (x->dc_type == DC_TYPE_AN985)
-#define DC_IS_DAVICOM(x) (x->dc_type == DC_TYPE_DM9102)
-#define DC_IS_PNICII(x) (x->dc_type == DC_TYPE_PNICII)
-#define DC_IS_PNIC(x) (x->dc_type == DC_TYPE_PNIC)
-#define DC_IS_XIRCOM(x) (x->dc_type == DC_TYPE_XIRCOM)
-#define DC_IS_CONEXANT(x) (x->dc_type == DC_TYPE_CONEXANT)
-
-/* MII/symbol mode port types */
-#define DC_PMODE_MII 0x1
-#define DC_PMODE_SYM 0x2
-#define DC_PMODE_SIA 0x3
-
-/*
- * Bus control bits.
- */
-#define DC_BUSCTL_RESET 0x00000001
-#define DC_BUSCTL_ARBITRATION 0x00000002
-#define DC_BUSCTL_SKIPLEN 0x0000007C
-#define DC_BUSCTL_BUF_BIGENDIAN 0x00000080
-#define DC_BUSCTL_BURSTLEN 0x00003F00
-#define DC_BUSCTL_CACHEALIGN 0x0000C000
-#define DC_BUSCTL_TXPOLL 0x000E0000
-#define DC_BUSCTL_DBO 0x00100000
-#define DC_BUSCTL_MRME 0x00200000
-#define DC_BUSCTL_MRLE 0x00800000
-#define DC_BUSCTL_MWIE 0x01000000
-#define DC_BUSCTL_ONNOW_ENB 0x04000000
-
-#define DC_SKIPLEN_1LONG 0x00000004
-#define DC_SKIPLEN_2LONG 0x00000008
-#define DC_SKIPLEN_3LONG 0x00000010
-#define DC_SKIPLEN_4LONG 0x00000020
-#define DC_SKIPLEN_5LONG 0x00000040
-
-#define DC_CACHEALIGN_NONE 0x00000000
-#define DC_CACHEALIGN_8LONG 0x00004000
-#define DC_CACHEALIGN_16LONG 0x00008000
-#define DC_CACHEALIGN_32LONG 0x0000C000
-
-#define DC_BURSTLEN_USECA 0x00000000
-#define DC_BURSTLEN_1LONG 0x00000100
-#define DC_BURSTLEN_2LONG 0x00000200
-#define DC_BURSTLEN_4LONG 0x00000400
-#define DC_BURSTLEN_8LONG 0x00000800
-#define DC_BURSTLEN_16LONG 0x00001000
-#define DC_BURSTLEN_32LONG 0x00002000
-
-#define DC_TXPOLL_OFF 0x00000000
-#define DC_TXPOLL_1 0x00020000
-#define DC_TXPOLL_2 0x00040000
-#define DC_TXPOLL_3 0x00060000
-#define DC_TXPOLL_4 0x00080000
-#define DC_TXPOLL_5 0x000A0000
-#define DC_TXPOLL_6 0x000C0000
-#define DC_TXPOLL_7 0x000E0000
-
-/*
- * Interrupt status bits.
- */
-#define DC_ISR_TX_OK 0x00000001
-#define DC_ISR_TX_IDLE 0x00000002
-#define DC_ISR_TX_NOBUF 0x00000004
-#define DC_ISR_TX_JABBERTIMEO 0x00000008
-#define DC_ISR_LINKGOOD 0x00000010
-#define DC_ISR_TX_UNDERRUN 0x00000020
-#define DC_ISR_RX_OK 0x00000040
-#define DC_ISR_RX_NOBUF 0x00000080
-#define DC_ISR_RX_READ 0x00000100
-#define DC_ISR_RX_WATDOGTIMEO 0x00000200
-#define DC_ISR_TX_EARLY 0x00000400
-#define DC_ISR_TIMER_EXPIRED 0x00000800
-#define DC_ISR_LINKFAIL 0x00001000
-#define DC_ISR_BUS_ERR 0x00002000
-#define DC_ISR_RX_EARLY 0x00004000
-#define DC_ISR_ABNORMAL 0x00008000
-#define DC_ISR_NORMAL 0x00010000
-#define DC_ISR_RX_STATE 0x000E0000
-#define DC_ISR_TX_STATE 0x00700000
-#define DC_ISR_BUSERRTYPE 0x03800000
-#define DC_ISR_100MBPSLINK 0x08000000
-#define DC_ISR_MAGICKPACK 0x10000000
-
-#define DC_RXSTATE_STOPPED 0x00000000 /* 000 - Stopped */
-#define DC_RXSTATE_FETCH 0x00020000 /* 001 - Fetching descriptor */
-#define DC_RXSTATE_ENDCHECK 0x00040000 /* 010 - check for rx end */
-#define DC_RXSTATE_WAIT 0x00060000 /* 011 - waiting for packet */
-#define DC_RXSTATE_SUSPEND 0x00080000 /* 100 - suspend rx */
-#define DC_RXSTATE_CLOSE 0x000A0000 /* 101 - close tx desc */
-#define DC_RXSTATE_FLUSH 0x000C0000 /* 110 - flush from FIFO */
-#define DC_RXSTATE_DEQUEUE 0x000E0000 /* 111 - dequeue from FIFO */
-
-#define DC_TXSTATE_RESET 0x00000000 /* 000 - reset */
-#define DC_TXSTATE_FETCH 0x00100000 /* 001 - fetching descriptor */
-#define DC_TXSTATE_WAITEND 0x00200000 /* 010 - wait for tx end */
-#define DC_TXSTATE_READING 0x00300000 /* 011 - read and enqueue */
-#define DC_TXSTATE_RSVD 0x00400000 /* 100 - reserved */
-#define DC_TXSTATE_SETUP 0x00500000 /* 101 - setup packet */
-#define DC_TXSTATE_SUSPEND 0x00600000 /* 110 - suspend tx */
-#define DC_TXSTATE_CLOSE 0x00700000 /* 111 - close tx desc */
-
-/*
- * Network config bits.
- */
-#define DC_NETCFG_RX_HASHPERF 0x00000001
-#define DC_NETCFG_RX_ON 0x00000002
-#define DC_NETCFG_RX_HASHONLY 0x00000004
-#define DC_NETCFG_RX_BADFRAMES 0x00000008
-#define DC_NETCFG_RX_INVFILT 0x00000010
-#define DC_NETCFG_BACKOFFCNT 0x00000020
-#define DC_NETCFG_RX_PROMISC 0x00000040
-#define DC_NETCFG_RX_ALLMULTI 0x00000080
-#define DC_NETCFG_FULLDUPLEX 0x00000200
-#define DC_NETCFG_LOOPBACK 0x00000C00
-#define DC_NETCFG_FORCECOLL 0x00001000
-#define DC_NETCFG_TX_ON 0x00002000
-#define DC_NETCFG_TX_THRESH 0x0000C000
-#define DC_NETCFG_TX_BACKOFF 0x00020000
-#define DC_NETCFG_PORTSEL 0x00040000 /* 0 == 10, 1 == 100 */
-#define DC_NETCFG_HEARTBEAT 0x00080000
-#define DC_NETCFG_STORENFWD 0x00200000
-#define DC_NETCFG_SPEEDSEL 0x00400000 /* 1 == 10, 0 == 100 */
-#define DC_NETCFG_PCS 0x00800000
-#define DC_NETCFG_SCRAMBLER 0x01000000
-#define DC_NETCFG_NO_RXCRC 0x02000000
-#define DC_NETCFG_RX_ALL 0x40000000
-#define DC_NETCFG_CAPEFFECT 0x80000000
-
-#define DC_OPMODE_NORM 0x00000000
-#define DC_OPMODE_INTLOOP 0x00000400
-#define DC_OPMODE_EXTLOOP 0x00000800
-
-#if 0
-#define DC_TXTHRESH_72BYTES 0x00000000
-#define DC_TXTHRESH_96BYTES 0x00004000
-#define DC_TXTHRESH_128BYTES 0x00008000
-#define DC_TXTHRESH_160BYTES 0x0000C000
-#endif
-
-#define DC_TXTHRESH_MIN 0x00000000
-#define DC_TXTHRESH_INC 0x00004000
-#define DC_TXTHRESH_MAX 0x0000C000
-
-
-/*
- * Interrupt mask bits.
- */
-#define DC_IMR_TX_OK 0x00000001
-#define DC_IMR_TX_IDLE 0x00000002
-#define DC_IMR_TX_NOBUF 0x00000004
-#define DC_IMR_TX_JABBERTIMEO 0x00000008
-#define DC_IMR_LINKGOOD 0x00000010
-#define DC_IMR_TX_UNDERRUN 0x00000020
-#define DC_IMR_RX_OK 0x00000040
-#define DC_IMR_RX_NOBUF 0x00000080
-#define DC_IMR_RX_READ 0x00000100
-#define DC_IMR_RX_WATDOGTIMEO 0x00000200
-#define DC_IMR_TX_EARLY 0x00000400
-#define DC_IMR_TIMER_EXPIRED 0x00000800
-#define DC_IMR_LINKFAIL 0x00001000
-#define DC_IMR_BUS_ERR 0x00002000
-#define DC_IMR_RX_EARLY 0x00004000
-#define DC_IMR_ABNORMAL 0x00008000
-#define DC_IMR_NORMAL 0x00010000
-#define DC_IMR_100MBPSLINK 0x08000000
-#define DC_IMR_MAGICKPACK 0x10000000
-
-#define DC_INTRS \
- (DC_IMR_RX_OK|DC_IMR_TX_OK|DC_IMR_RX_NOBUF|DC_IMR_RX_WATDOGTIMEO|\
- DC_IMR_TX_NOBUF|DC_IMR_TX_UNDERRUN|DC_IMR_BUS_ERR| \
- DC_IMR_ABNORMAL|DC_IMR_NORMAL/*|DC_IMR_TX_EARLY*/)
-/*
- * Serial I/O (EEPROM/ROM) bits.
- */
-#define DC_SIO_EE_CS 0x00000001 /* EEPROM chip select */
-#define DC_SIO_EE_CLK 0x00000002 /* EEPROM clock */
-#define DC_SIO_EE_DATAIN 0x00000004 /* EEPROM data output */
-#define DC_SIO_EE_DATAOUT 0x00000008 /* EEPROM data input */
-#define DC_SIO_ROMDATA4 0x00000010
-#define DC_SIO_ROMDATA5 0x00000020
-#define DC_SIO_ROMDATA6 0x00000040
-#define DC_SIO_ROMDATA7 0x00000080
-#define DC_SIO_EESEL 0x00000800
-#define DC_SIO_ROMSEL 0x00001000
-#define DC_SIO_ROMCTL_WRITE 0x00002000
-#define DC_SIO_ROMCTL_READ 0x00004000
-#define DC_SIO_MII_CLK 0x00010000 /* MDIO clock */
-#define DC_SIO_MII_DATAOUT 0x00020000 /* MDIO data out */
-#define DC_SIO_MII_DIR 0x00040000 /* MDIO dir */
-#define DC_SIO_MII_DATAIN 0x00080000 /* MDIO data in */
-
-#define DC_EECMD_WRITE 0x140
-#define DC_EECMD_READ 0x180
-#define DC_EECMD_ERASE 0x1c0
-
-#define DC_EE_NODEADDR_OFFSET 0x70
-#define DC_EE_NODEADDR 10
-
-/*
- * General purpose timer register
- */
-#define DC_TIMER_VALUE 0x0000FFFF
-#define DC_TIMER_CONTINUOUS 0x00010000
-
-/*
- * 10baseT status register
- */
-#define DC_TSTAT_MIIACT 0x00000001 /* MII port activity */
-#define DC_TSTAT_LS100 0x00000002 /* link status of 100baseTX */
-#define DC_TSTAT_LS10 0x00000004 /* link status of 10baseT */
-#define DC_TSTAT_AUTOPOLARITY 0x00000008
-#define DC_TSTAT_AUIACT 0x00000100 /* AUI activity */
-#define DC_TSTAT_10BTACT 0x00000200 /* 10baseT activity */
-#define DC_TSTAT_NSN 0x00000400 /* non-stable FLPs detected */
-#define DC_TSTAT_REMFAULT 0x00000800
-#define DC_TSTAT_ANEGSTAT 0x00007000
-#define DC_TSTAT_LP_CAN_NWAY 0x00008000 /* link partner supports NWAY */
-#define DC_TSTAT_LPCODEWORD 0xFFFF0000 /* link partner's code word */
-
-#define DC_ASTAT_DISABLE 0x00000000
-#define DC_ASTAT_TXDISABLE 0x00001000
-#define DC_ASTAT_ABDETECT 0x00002000
-#define DC_ASTAT_ACKDETECT 0x00003000
-#define DC_ASTAT_CMPACKDETECT 0x00004000
-#define DC_ASTAT_AUTONEGCMP 0x00005000
-#define DC_ASTAT_LINKCHECK 0x00006000
-
-/*
- * PHY reset register
- */
-#define DC_SIA_RESET 0x00000001
-#define DC_SIA_AUI 0x00000008 /* AUI or 10baseT */
-
-/*
- * 10baseT control register
- */
-#define DC_TCTL_ENCODER_ENB 0x00000001
-#define DC_TCTL_LOOPBACK 0x00000002
-#define DC_TCTL_DRIVER_ENB 0x00000004
-#define DC_TCTL_LNKPULSE_ENB 0x00000008
-#define DC_TCTL_HALFDUPLEX 0x00000040
-#define DC_TCTL_AUTONEGENBL 0x00000080
-#define DC_TCTL_RX_SQUELCH 0x00000100
-#define DC_TCTL_COLL_SQUELCH 0x00000200
-#define DC_TCTL_COLL_DETECT 0x00000400
-#define DC_TCTL_SQE_ENB 0x00000800
-#define DC_TCTL_LINKTEST 0x00001000
-#define DC_TCTL_AUTOPOLARITY 0x00002000
-#define DC_TCTL_SET_POL_PLUS 0x00004000
-#define DC_TCTL_AUTOSENSE 0x00008000 /* 10bt/AUI autosense */
-#define DC_TCTL_100BTXHALF 0x00010000
-#define DC_TCTL_100BTXFULL 0x00020000
-#define DC_TCTL_100BT4 0x00040000
-
-/*
- * Watchdog timer register
- */
-#define DC_WDOG_JABBERDIS 0x00000001
-#define DC_WDOG_HOSTUNJAB 0x00000002
-#define DC_WDOG_JABBERCLK 0x00000004
-#define DC_WDOG_RXWDOGDIS 0x00000010
-#define DC_WDOG_RXWDOGCLK 0x00000020
-#define DC_WDOG_MUSTBEZERO 0x00000100
-#define DC_WDOG_AUIBNC 0x00100000
-#define DC_WDOG_ACTIVITY 0x00200000
-#define DC_WDOG_RX_MATCH 0x00400000
-#define DC_WDOG_LINK 0x00800000
-#define DC_WDOG_CTLWREN 0x08000000
-
-/*
- * SIA and General Purpose Port register (X3201)
- */
-#define DC_SIAGP_RXMATCH 0x40000000
-#define DC_SIAGP_INT1 0x20000000
-#define DC_SIAGP_INT0 0x10000000
-#define DC_SIAGP_WRITE_EN 0x08000000
-#define DC_SIAGP_RXMATCH_EN 0x04000000
-#define DC_SIAGP_INT1_EN 0x02000000
-#define DC_SIAGP_INT0_EN 0x01000000
-#define DC_SIAGP_LED3 0x00800000
-#define DC_SIAGP_LED2 0x00400000
-#define DC_SIAGP_LED1 0x00200000
-#define DC_SIAGP_LED0 0x00100000
-#define DC_SIAGP_MD_GP3_OUTPUT 0x00080000
-#define DC_SIAGP_MD_GP2_OUTPUT 0x00040000
-#define DC_SIAGP_MD_GP1_OUTPUT 0x00020000
-#define DC_SIAGP_MD_GP0_OUTPUT 0x00010000
-
-/*
- * Size of a setup frame.
- */
-#define DC_SFRAME_LEN 192
-
-/*
- * 21x4x TX/RX list structure.
- */
-
-struct dc_desc {
- u_int32_t dc_status;
- u_int32_t dc_ctl;
- u_int32_t dc_ptr1;
- u_int32_t dc_ptr2;
-};
-
-#define dc_data dc_ptr1
-#define dc_next dc_ptr2
-
-#define DC_RXSTAT_FIFOOFLOW 0x00000001
-#define DC_RXSTAT_CRCERR 0x00000002
-#define DC_RXSTAT_DRIBBLE 0x00000004
-#define DC_RXSTAT_MIIERE 0x00000008
-#define DC_RXSTAT_WATCHDOG 0x00000010
-#define DC_RXSTAT_FRAMETYPE 0x00000020 /* 0 == IEEE 802.3 */
-#define DC_RXSTAT_COLLSEEN 0x00000040
-#define DC_RXSTAT_GIANT 0x00000080
-#define DC_RXSTAT_LASTFRAG 0x00000100
-#define DC_RXSTAT_FIRSTFRAG 0x00000200
-#define DC_RXSTAT_MULTICAST 0x00000400
-#define DC_RXSTAT_RUNT 0x00000800
-#define DC_RXSTAT_RXTYPE 0x00003000
-#define DC_RXSTAT_DE 0x00004000
-#define DC_RXSTAT_RXERR 0x00008000
-#define DC_RXSTAT_RXLEN 0x3FFF0000
-#define DC_RXSTAT_OWN 0x80000000
-
-#define DC_RXBYTES(x) ((x & DC_RXSTAT_RXLEN) >> 16)
-#define DC_RXSTAT (DC_RXSTAT_FIRSTFRAG|DC_RXSTAT_LASTFRAG|DC_RXSTAT_OWN)
-
-#define DC_RXCTL_BUFLEN1 0x00000FFF
-#define DC_RXCTL_BUFLEN2 0x00FFF000
-#define DC_RXCTL_RLINK 0x01000000
-#define DC_RXCTL_RLAST 0x02000000
-
-#define DC_TXSTAT_DEFER 0x00000001
-#define DC_TXSTAT_UNDERRUN 0x00000002
-#define DC_TXSTAT_LINKFAIL 0x00000003
-#define DC_TXSTAT_COLLCNT 0x00000078
-#define DC_TXSTAT_SQE 0x00000080
-#define DC_TXSTAT_EXCESSCOLL 0x00000100
-#define DC_TXSTAT_LATECOLL 0x00000200
-#define DC_TXSTAT_NOCARRIER 0x00000400
-#define DC_TXSTAT_CARRLOST 0x00000800
-#define DC_TXSTAT_JABTIMEO 0x00004000
-#define DC_TXSTAT_ERRSUM 0x00008000
-#define DC_TXSTAT_OWN 0x80000000
-
-#define DC_TXCTL_BUFLEN1 0x000007FF
-#define DC_TXCTL_BUFLEN2 0x003FF800
-#define DC_TXCTL_FILTTYPE0 0x00400000
-#define DC_TXCTL_PAD 0x00800000
-#define DC_TXCTL_TLINK 0x01000000
-#define DC_TXCTL_TLAST 0x02000000
-#define DC_TXCTL_NOCRC 0x04000000
-#define DC_TXCTL_SETUP 0x08000000
-#define DC_TXCTL_FILTTYPE1 0x10000000
-#define DC_TXCTL_FIRSTFRAG 0x20000000
-#define DC_TXCTL_LASTFRAG 0x40000000
-#define DC_TXCTL_FINT 0x80000000
-
-#define DC_FILTER_PERFECT 0x00000000
-#define DC_FILTER_HASHPERF 0x00400000
-#define DC_FILTER_INVERSE 0x10000000
-#define DC_FILTER_HASHONLY 0x10400000
-
-#define DC_MAXFRAGS 16
-#ifdef DEVICE_POLLING
-#define DC_RX_LIST_CNT 192
-#else
-#define DC_RX_LIST_CNT 64
-#endif
-#define DC_TX_LIST_CNT 256
-#define DC_MIN_FRAMELEN 60
-#define DC_RXLEN 1536
-
-#define DC_INC(x, y) (x) = (x + 1) % y
-
-/* Macros to easily get the DMA address of a descriptor. */
-#define DC_RXDESC(sc, i) (sc->dc_laddr + \
- (uintptr_t)(sc->dc_ldata->dc_rx_list + i) - (uintptr_t)sc->dc_ldata)
-#define DC_TXDESC(sc, i) (sc->dc_laddr + \
- (uintptr_t)(sc->dc_ldata->dc_tx_list + i) - (uintptr_t)sc->dc_ldata)
-
-#if BYTE_ORDER == BIG_ENDIAN
-#define DC_SP_MAC(x) ((x) << 16)
-#else
-#define DC_SP_MAC(x) (x)
-#endif
-
-struct dc_list_data {
- struct dc_desc dc_rx_list[DC_RX_LIST_CNT];
- struct dc_desc dc_tx_list[DC_TX_LIST_CNT];
-};
-
-struct dc_chain_data {
- struct mbuf *dc_rx_chain[DC_RX_LIST_CNT];
- struct mbuf *dc_tx_chain[DC_TX_LIST_CNT];
- struct mbuf *dc_tx_mapping;
- bus_dmamap_t dc_rx_map[DC_RX_LIST_CNT];
- bus_dmamap_t dc_tx_map[DC_TX_LIST_CNT];
- u_int32_t *dc_sbuf;
- u_int8_t dc_pad[DC_MIN_FRAMELEN];
- int dc_tx_err;
- int dc_tx_first;
- int dc_tx_prod;
- int dc_tx_cons;
- int dc_tx_cnt;
- int dc_rx_err;
- int dc_rx_cur;
- int dc_rx_prod;
-};
-
-struct dc_mediainfo {
- int dc_media;
- u_int8_t *dc_gp_ptr;
- u_int8_t dc_gp_len;
- u_int8_t *dc_reset_ptr;
- u_int8_t dc_reset_len;
- struct dc_mediainfo *dc_next;
-};
-
-
-struct dc_type {
- u_int16_t dc_vid;
- u_int16_t dc_did;
- char *dc_name;
-};
-
-struct dc_mii_frame {
- u_int8_t mii_stdelim;
- u_int8_t mii_opcode;
- u_int8_t mii_phyaddr;
- u_int8_t mii_regaddr;
- u_int8_t mii_turnaround;
- u_int16_t mii_data;
-};
-
-/*
- * MII constants
- */
-#define DC_MII_STARTDELIM 0x01
-#define DC_MII_READOP 0x02
-#define DC_MII_WRITEOP 0x01
-#define DC_MII_TURNAROUND 0x02
-
-
-/*
- * Registers specific to clone devices.
- * This mainly relates to RX filter programming: not all 21x4x clones
- * use the standard DEC filter programming mechanism.
- */
-
-/*
- * ADMtek specific registers and constants for the AL981 and AN985.
- * The AN985 doesn't use the magic PHY registers.
- */
-#define DC_AL_CR 0x88 /* command register */
-#define DC_AL_PAR0 0xA4 /* station address */
-#define DC_AL_PAR1 0xA8 /* station address */
-#define DC_AL_MAR0 0xAC /* multicast hash filter */
-#define DC_AL_MAR1 0xB0 /* multicast hash filter */
-#define DC_AL_BMCR 0xB4 /* built in PHY control */
-#define DC_AL_BMSR 0xB8 /* built in PHY status */
-#define DC_AL_VENID 0xBC /* built in PHY ID0 */
-#define DC_AL_DEVID 0xC0 /* built in PHY ID1 */
-#define DC_AL_ANAR 0xC4 /* built in PHY autoneg advert */
-#define DC_AL_LPAR 0xC8 /* bnilt in PHY link part. ability */
-#define DC_AL_ANER 0xCC /* built in PHY autoneg expansion */
-
-#define DC_AL_CR_ATUR 0x00000001 /* automatic TX underrun recovery */
-#define DC_ADMTEK_PHYADDR 0x1
-#define DC_AL_EE_NODEADDR 4
-/* End of ADMtek specific registers */
-
-/*
- * ASIX specific registers.
- */
-#define DC_AX_FILTIDX 0x68 /* RX filter index */
-#define DC_AX_FILTDATA 0x70 /* RX filter data */
-
-/*
- * Special ASIX-specific bits in the ASIX NETCFG register (CSR6).
- */
-#define DC_AX_NETCFG_RX_BROAD 0x00000100
-
-/*
- * RX Filter Index Register values
- */
-#define DC_AX_FILTIDX_PAR0 0x00000000
-#define DC_AX_FILTIDX_PAR1 0x00000001
-#define DC_AX_FILTIDX_MAR0 0x00000002
-#define DC_AX_FILTIDX_MAR1 0x00000003
-/* End of ASIX specific registers */
-
-/*
- * Macronix specific registers. The Macronix chips have a special
- * register for reading the NWAY status, which we don't use, plus
- * a magic packet register, which we need to tweak a bit per the
- * Macronix application notes.
- */
-#define DC_MX_MAGICPACKET 0x80
-#define DC_MX_NWAYSTAT 0xA0
-
-/*
- * Magic packet register
- */
-#define DC_MX_MPACK_DISABLE 0x00400000
-
-/*
- * NWAY status register.
- */
-#define DC_MX_NWAY_10BTHALF 0x08000000
-#define DC_MX_NWAY_10BTFULL 0x10000000
-#define DC_MX_NWAY_100BTHALF 0x20000000
-#define DC_MX_NWAY_100BTFULL 0x40000000
-#define DC_MX_NWAY_100BT4 0x80000000
-
-/*
- * These are magic values that must be written into CSR16
- * (DC_MX_MAGICPACKET) in order to put the chip into proper
- * operating mode. The magic numbers are documented in the
- * Macronix 98715 application notes.
- */
-#define DC_MX_MAGIC_98713 0x0F370000
-#define DC_MX_MAGIC_98713A 0x0B3C0000
-#define DC_MX_MAGIC_98715 0x0B3C0000
-#define DC_MX_MAGIC_98725 0x0B3C0000
-/* End of Macronix specific registers */
-
-/*
- * PNIC 82c168/82c169 specific registers.
- * The PNIC has its own special NWAY support, which doesn't work,
- * and shortcut ways of reading the EEPROM and MII bus.
- */
-#define DC_PN_GPIO 0x60 /* general purpose pins control */
-#define DC_PN_PWRUP_CFG 0x90 /* config register, set by EEPROM */
-#define DC_PN_SIOCTL 0x98 /* serial EEPROM control register */
-#define DC_PN_MII 0xA0 /* MII access register */
-#define DC_PN_NWAY 0xB8 /* Internal NWAY register */
-
-/* Serial I/O EEPROM register */
-#define DC_PN_SIOCTL_DATA 0x0000003F
-#define DC_PN_SIOCTL_OPCODE 0x00000300
-#define DC_PN_SIOCTL_BUSY 0x80000000
-
-#define DC_PN_EEOPCODE_ERASE 0x00000300
-#define DC_PN_EEOPCODE_READ 0x00000600
-#define DC_PN_EEOPCODE_WRITE 0x00000100
-
-/*
- * The first two general purpose pins control speed selection and
- * 100Mbps loopback on the 82c168 chip. The control bits should always
- * be set (to make the data pins outputs) and the speed selction and
- * loopback bits set accordingly when changing media. Physically, this
- * will set the state of a relay mounted on the card.
- */
-#define DC_PN_GPIO_DATA0 0x000000001
-#define DC_PN_GPIO_DATA1 0x000000002
-#define DC_PN_GPIO_DATA2 0x000000004
-#define DC_PN_GPIO_DATA3 0x000000008
-#define DC_PN_GPIO_CTL0 0x000000010
-#define DC_PN_GPIO_CTL1 0x000000020
-#define DC_PN_GPIO_CTL2 0x000000040
-#define DC_PN_GPIO_CTL3 0x000000080
-#define DC_PN_GPIO_SPEEDSEL DC_PN_GPIO_DATA0/* 1 == 100Mbps, 0 == 10Mbps */
-#define DC_PN_GPIO_100TX_LOOP DC_PN_GPIO_DATA1/* 1 == normal, 0 == loop */
-#define DC_PN_GPIO_BNC_ENB DC_PN_GPIO_DATA2
-#define DC_PN_GPIO_100TX_LNK DC_PN_GPIO_DATA3
-#define DC_PN_GPIO_SETBIT(sc, r) \
- DC_SETBIT(sc, DC_PN_GPIO, ((r) | (r << 4)))
-#define DC_PN_GPIO_CLRBIT(sc, r) \
- { \
- DC_SETBIT(sc, DC_PN_GPIO, ((r) << 4)); \
- DC_CLRBIT(sc, DC_PN_GPIO, (r)); \
- }
-
-/* shortcut MII access register */
-#define DC_PN_MII_DATA 0x0000FFFF
-#define DC_PN_MII_RESERVER 0x00020000
-#define DC_PN_MII_REGADDR 0x007C0000
-#define DC_PN_MII_PHYADDR 0x0F800000
-#define DC_PN_MII_OPCODE 0x30000000
-#define DC_PN_MII_BUSY 0x80000000
-
-#define DC_PN_MIIOPCODE_READ 0x60020000
-#define DC_PN_MIIOPCODE_WRITE 0x50020000
-
-/* Internal NWAY bits */
-#define DC_PN_NWAY_RESET 0x00000001 /* reset */
-#define DC_PN_NWAY_PDOWN 0x00000002 /* power down */
-#define DC_PN_NWAY_BYPASS 0x00000004 /* bypass */
-#define DC_PN_NWAY_AUILOWCUR 0x00000008 /* AUI low current */
-#define DC_PN_NWAY_TPEXTEND 0x00000010 /* low squelch voltage */
-#define DC_PN_NWAY_POLARITY 0x00000020 /* 0 == on, 1 == off */
-#define DC_PN_NWAY_TP 0x00000040 /* 1 == tp, 0 == AUI */
-#define DC_PN_NWAY_AUIVOLT 0x00000080 /* 1 == full, 0 == half */
-#define DC_PN_NWAY_DUPLEX 0x00000100 /* LED, 1 == full, 0 == half */
-#define DC_PN_NWAY_LINKTEST 0x00000200 /* 0 == on, 1 == off */
-#define DC_PN_NWAY_AUTODETECT 0x00000400 /* 1 == off, 0 == on */
-#define DC_PN_NWAY_SPEEDSEL 0x00000800 /* LED, 0 = 10, 1 == 100 */
-#define DC_PN_NWAY_NWAY_ENB 0x00001000 /* 0 == off, 1 == on */
-#define DC_PN_NWAY_CAP10HDX 0x00002000
-#define DC_PN_NWAY_CAP10FDX 0x00004000
-#define DC_PN_NWAY_CAP100FDX 0x00008000
-#define DC_PN_NWAY_CAP100HDX 0x00010000
-#define DC_PN_NWAY_CAP100T4 0x00020000
-#define DC_PN_NWAY_ANEGRESTART 0x02000000 /* resets when aneg done */
-#define DC_PN_NWAY_REMFAULT 0x04000000
-#define DC_PN_NWAY_LPAR10HDX 0x08000000
-#define DC_PN_NWAY_LPAR10FDX 0x10000000
-#define DC_PN_NWAY_LPAR100FDX 0x20000000
-#define DC_PN_NWAY_LPAR100HDX 0x40000000
-#define DC_PN_NWAY_LPAR100T4 0x80000000
-
-/* End of PNIC specific registers */
-
-/*
- * CONEXANT specific registers.
- */
-
-#define DC_CONEXANT_PHYADDR 0x1
-#define DC_CONEXANT_EE_NODEADDR 0x19A
-
-/* End of CONEXANT specific registers */
-
-
-struct dc_softc {
- struct ifnet *dc_ifp; /* interface info */
- bus_space_handle_t dc_bhandle; /* bus space handle */
- bus_space_tag_t dc_btag; /* bus space tag */
- bus_dma_tag_t dc_ltag; /* tag for descriptor ring */
- bus_dmamap_t dc_lmap; /* map for descriptor ring */
- u_int32_t dc_laddr; /* DMA address of dc_ldata */
- bus_dma_tag_t dc_mtag; /* tag for mbufs */
- bus_dmamap_t dc_sparemap;
- bus_dma_tag_t dc_stag; /* tag for the setup frame */
- bus_dmamap_t dc_smap; /* map for the setup frame */
- u_int32_t dc_saddr; /* DMA address of setup frame */
- void *dc_intrhand;
- struct resource *dc_irq;
- struct resource *dc_res;
- struct dc_type *dc_info; /* adapter info */
- device_t dc_miibus;
- u_int8_t dc_type;
- u_int8_t dc_pmode;
- u_int8_t dc_link;
- u_int8_t dc_cachesize;
- int dc_romwidth;
- int dc_pnic_rx_bug_save;
- unsigned char *dc_pnic_rx_buf;
- int dc_if_flags;
- int dc_if_media;
- u_int32_t dc_flags;
- u_int32_t dc_txthresh;
- u_int8_t *dc_srom;
- struct dc_mediainfo *dc_mi;
- struct dc_list_data *dc_ldata;
- struct dc_chain_data dc_cdata;
- struct callout dc_stat_ch;
-#ifdef SRM_MEDIA
- int dc_srm_media;
-#endif
- struct mtx dc_mtx;
-#ifdef DEVICE_POLLING
- int rxcycles; /* ... when polling */
-#endif
- int suspended; /* 0 = normal 1 = suspended */
-};
-
-
-#define DC_LOCK(_sc) mtx_lock(&(_sc)->dc_mtx)
-#define DC_UNLOCK(_sc) mtx_unlock(&(_sc)->dc_mtx)
-#define DC_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->dc_mtx, MA_OWNED)
-
-#define DC_TX_POLL 0x00000001
-#define DC_TX_COALESCE 0x00000002
-#define DC_TX_ADMTEK_WAR 0x00000004
-#define DC_TX_USE_TX_INTR 0x00000008
-#define DC_RX_FILTER_TULIP 0x00000010
-#define DC_TX_INTR_FIRSTFRAG 0x00000020
-#define DC_PNIC_RX_BUG_WAR 0x00000040
-#define DC_TX_FIXED_RING 0x00000080
-#define DC_TX_STORENFWD 0x00000100
-#define DC_REDUCED_MII_POLL 0x00000200
-#define DC_TX_INTR_ALWAYS 0x00000400
-#define DC_21143_NWAY 0x00000800
-#define DC_128BIT_HASH 0x00001000
-#define DC_64BIT_HASH 0x00002000
-#define DC_TULIP_LEDS 0x00004000
-#define DC_TX_ONE 0x00008000
-#define DC_TX_ALIGN 0x00010000 /* align mbuf on tx */
-
-/*
- * register space access macros
- */
-#define CSR_WRITE_4(sc, reg, val) \
- bus_space_write_4(sc->dc_btag, sc->dc_bhandle, reg, val)
-
-#define CSR_READ_4(sc, reg) \
- bus_space_read_4(sc->dc_btag, sc->dc_bhandle, reg)
-
-#define DC_TIMEOUT 1000
-#define ETHER_ALIGN 2
-
-/*
- * General constants that are fun to know.
- */
-
-/*
- * DEC PCI vendor ID
- */
-#define DC_VENDORID_DEC 0x1011
-
-/*
- * DEC/Intel 21143 PCI device ID
- */
-#define DC_DEVICEID_21143 0x0019
-
-/*
- * Macronix PCI vendor ID
- */
-#define DC_VENDORID_MX 0x10D9
-
-/*
- * Macronix PMAC device IDs.
- */
-#define DC_DEVICEID_98713 0x0512
-#define DC_DEVICEID_987x5 0x0531
-#define DC_DEVICEID_98727 0x0532
-#define DC_DEVICEID_98732 0x0532
-
-/* Macronix PCI revision codes. */
-#define DC_REVISION_98713 0x00
-#define DC_REVISION_98713A 0x10
-#define DC_REVISION_98715 0x20
-#define DC_REVISION_98715AEC_C 0x25
-#define DC_REVISION_98725 0x30
-
-/*
- * Compex PCI vendor ID.
- */
-#define DC_VENDORID_CP 0x11F6
-
-/*
- * Compex PMAC PCI device IDs.
- */
-#define DC_DEVICEID_98713_CP 0x9881
-
-/*
- * Lite-On PNIC PCI vendor ID
- */
-#define DC_VENDORID_LO 0x11AD
-
-/*
- * 82c168/82c169 PNIC device IDs. Both chips have the same device
- * ID but different revisions. Revision 0x10 is the 82c168, and
- * 0x20 is the 82c169.
- */
-#define DC_DEVICEID_82C168 0x0002
-
-#define DC_REVISION_82C168 0x10
-#define DC_REVISION_82C169 0x20
-
-/*
- * Lite-On PNIC II device ID. Note: this is actually a Macronix 98715A
- * with wake on lan/magic packet support.
- */
-#define DC_DEVICEID_82C115 0xc115
-
-/*
- * Davicom vendor ID.
- */
-#define DC_VENDORID_DAVICOM 0x1282
-
-/*
- * Davicom device IDs.
- */
-#define DC_DEVICEID_DM9009 0x9009
-#define DC_DEVICEID_DM9100 0x9100
-#define DC_DEVICEID_DM9102 0x9102
-
-/*
- * The DM9102A has the same PCI device ID as the DM9102,
- * but a higher revision code.
- */
-#define DC_REVISION_DM9102 0x10
-#define DC_REVISION_DM9102A 0x30
-
-/*
- * ADMtek vendor ID.
- */
-#define DC_VENDORID_ADMTEK 0x1317
-
-/*
- * ADMtek device IDs.
- */
-#define DC_DEVICEID_AL981 0x0981
-#define DC_DEVICEID_AN985 0x0985
-#define DC_DEVICEID_FA511 0x1985
-#define DC_DEVICEID_ADM9511 0x9511
-#define DC_DEVICEID_ADM9513 0x9513
-
-/*
- * 3COM PCI vendor ID
- */
-#define DC_VENDORID_3COM 0x10b7
-
-/*
- * 3COM OfficeConnect 10/100B (3CSOHO100B-TX)
- */
-#define DC_DEVICEID_3CSOHOB 0x9300
-
-/*
- * ASIX vendor ID.
- */
-#define DC_VENDORID_ASIX 0x125B
-
-/*
- * ASIX device IDs.
- */
-#define DC_DEVICEID_AX88140A 0x1400
-
-/*
- * The ASIX AX88140 and ASIX AX88141 have the same vendor and
- * device IDs but different revision values.
- */
-#define DC_REVISION_88140 0x00
-#define DC_REVISION_88141 0x10
-
-/*
- * Accton vendor ID.
- */
-#define DC_VENDORID_ACCTON 0x1113
-
-/*
- * Accton device IDs.
- */
-#define DC_DEVICEID_EN1217 0x1217
-#define DC_DEVICEID_EN2242 0x1216
-
-/*
- * Xircom vendor ID
- */
-#define DC_VENDORID_XIRCOM 0x115d
-
-/*
- * Xircom device IDs.
- */
-#define DC_DEVICEID_X3201 0x0003
-
-/*
- * Abocom vendor ID
- */
-#define DC_VENDORID_ABOCOM 0x13d1
-
-/*
- * Abocom device IDs.
- */
-#define DC_DEVICEID_FE2500 0xAB02
-#define DC_DEVICEID_FE2500MX 0xab08
-
-/*
- * Conexant vendor ID.
- */
-#define DC_VENDORID_CONEXANT 0x14f1
-
-/*
- * Conexant device IDs.
- */
-#define DC_DEVICEID_RS7112 0x1803
-
-/*
- * Planex vendor ID
- */
-#define DC_VENDORID_PLANEX 0x14ea
-
-/*
- * Planex device IDs.
- */
-#define DC_DEVICEID_FNW3602T 0xab08
-
-/*
- * Not sure who this vendor should be, so we'll go with HAWKING until
- * I can locate the right one.
- */
-#define DC_VENDORID_HAWKING 0x17b3
-
-/*
- * Sure looks like an abocom device ID, but it found on my hawking PN672TX
- * card. Use that for now, and upgrade later.
- */
-#define DC_DEVICEID_HAWKING_PN672TX 0xab08
-
-/*
- * Microsoft device ID.
- */
-#define DC_VENDORID_MICROSOFT 0x1414
-
-/*
- * Supported Microsoft PCI and cardbus NICs. These are really
- * ADMtek parts in disguise.
- */
-
-#define DC_DEVICEID_MSMN120 0x0001
-#define DC_DEVICEID_MSMN130 0x0002
-#define DC_DEVICEID_MSMN130_FAKE 0xFFF2
-
-/*
- * PCI low memory base and low I/O base register, and
- * other PCI registers.
- */
-
-#define DC_PCI_CFID 0x00 /* Id */
-#define DC_PCI_CFCS 0x04 /* Command and status */
-#define DC_PCI_CFRV 0x08 /* Revision */
-#define DC_PCI_CFLT 0x0C /* Latency timer */
-#define DC_PCI_CFBIO 0x10 /* Base I/O address */
-#define DC_PCI_CFBMA 0x14 /* Base memory address */
-#define DC_PCI_CCIS 0x28 /* Card info struct */
-#define DC_PCI_CSID 0x2C /* Subsystem ID */
-#define DC_PCI_CBER 0x30 /* Expansion ROM base address */
-#define DC_PCI_CCAP 0x34 /* Caps pointer - PD/TD chip only */
-#define DC_PCI_CFIT 0x3C /* Interrupt */
-#define DC_PCI_CFDD 0x40 /* Device and driver area */
-#define DC_PCI_CWUA0 0x44 /* Wake-Up LAN addr 0 */
-#define DC_PCI_CWUA1 0x48 /* Wake-Up LAN addr 1 */
-#define DC_PCI_SOP0 0x4C /* SecureON passwd 0 */
-#define DC_PCI_SOP1 0x50 /* SecureON passwd 1 */
-#define DC_PCI_CWUC 0x54 /* Configuration Wake-Up cmd */
-#define DC_PCI_CCID 0xDC /* Capability ID - PD/TD only */
-#define DC_PCI_CPMC 0xE0 /* Pwrmgmt ctl & sts - PD/TD only */
-
-/* PCI ID register */
-#define DC_CFID_VENDOR 0x0000FFFF
-#define DC_CFID_DEVICE 0xFFFF0000
-
-/* PCI command/status register */
-#define DC_CFCS_IOSPACE 0x00000001 /* I/O space enable */
-#define DC_CFCS_MEMSPACE 0x00000002 /* memory space enable */
-#define DC_CFCS_BUSMASTER 0x00000004 /* bus master enable */
-#define DC_CFCS_MWI_ENB 0x00000010 /* mem write and inval enable */
-#define DC_CFCS_PARITYERR_ENB 0x00000040 /* parity error enable */
-#define DC_CFCS_SYSERR_ENB 0x00000100 /* system error enable */
-#define DC_CFCS_NEWCAPS 0x00100000 /* new capabilities */
-#define DC_CFCS_FAST_B2B 0x00800000 /* fast back-to-back capable */
-#define DC_CFCS_DATAPARITY 0x01000000 /* Parity error report */
-#define DC_CFCS_DEVSELTIM 0x06000000 /* devsel timing */
-#define DC_CFCS_TGTABRT 0x10000000 /* received target abort */
-#define DC_CFCS_MASTERABRT 0x20000000 /* received master abort */
-#define DC_CFCS_SYSERR 0x40000000 /* asserted system error */
-#define DC_CFCS_PARITYERR 0x80000000 /* asserted parity error */
-
-/* PCI revision register */
-#define DC_CFRV_STEPPING 0x0000000F
-#define DC_CFRV_REVISION 0x000000F0
-#define DC_CFRV_SUBCLASS 0x00FF0000
-#define DC_CFRV_BASECLASS 0xFF000000
-
-#define DC_21143_PB_REV 0x00000030
-#define DC_21143_TB_REV 0x00000030
-#define DC_21143_PC_REV 0x00000030
-#define DC_21143_TC_REV 0x00000030
-#define DC_21143_PD_REV 0x00000041
-#define DC_21143_TD_REV 0x00000041
-
-/* PCI latency timer register */
-#define DC_CFLT_CACHELINESIZE 0x000000FF
-#define DC_CFLT_LATENCYTIMER 0x0000FF00
-
-/* PCI subsystem ID register */
-#define DC_CSID_VENDOR 0x0000FFFF
-#define DC_CSID_DEVICE 0xFFFF0000
-
-/* PCI cababilities pointer */
-#define DC_CCAP_OFFSET 0x000000FF
-
-/* PCI interrupt config register */
-#define DC_CFIT_INTLINE 0x000000FF
-#define DC_CFIT_INTPIN 0x0000FF00
-#define DC_CFIT_MIN_GNT 0x00FF0000
-#define DC_CFIT_MAX_LAT 0xFF000000
-
-/* PCI capability register */
-#define DC_CCID_CAPID 0x000000FF
-#define DC_CCID_NEXTPTR 0x0000FF00
-#define DC_CCID_PM_VERS 0x00070000
-#define DC_CCID_PME_CLK 0x00080000
-#define DC_CCID_DVSPEC_INT 0x00200000
-#define DC_CCID_STATE_D1 0x02000000
-#define DC_CCID_STATE_D2 0x04000000
-#define DC_CCID_PME_D0 0x08000000
-#define DC_CCID_PME_D1 0x10000000
-#define DC_CCID_PME_D2 0x20000000
-#define DC_CCID_PME_D3HOT 0x40000000
-#define DC_CCID_PME_D3COLD 0x80000000
-
-/* PCI power management control/status register */
-#define DC_CPMC_STATE 0x00000003
-#define DC_CPMC_PME_ENB 0x00000100
-#define DC_CPMC_PME_STS 0x00008000
-
-#define DC_PSTATE_D0 0x0
-#define DC_PSTATE_D1 0x1
-#define DC_PSTATE_D2 0x2
-#define DC_PSTATE_D3 0x3
-
-/* Device specific region */
-/* Configuration and driver area */
-#define DC_CFDD_DRVUSE 0x0000FFFF
-#define DC_CFDD_SNOOZE_MODE 0x40000000
-#define DC_CFDD_SLEEP_MODE 0x80000000
-
-/* Configuration wake-up command register */
-#define DC_CWUC_MUST_BE_ZERO 0x00000001
-#define DC_CWUC_SECUREON_ENB 0x00000002
-#define DC_CWUC_FORCE_WUL 0x00000004
-#define DC_CWUC_BNC_ABILITY 0x00000008
-#define DC_CWUC_AUI_ABILITY 0x00000010
-#define DC_CWUC_TP10_ABILITY 0x00000020
-#define DC_CWUC_MII_ABILITY 0x00000040
-#define DC_CWUC_SYM_ABILITY 0x00000080
-#define DC_CWUC_LOCK 0x00000100
-
-/*
- * SROM nonsense.
- */
-
-#define DC_IB_CTLRCNT 0x13
-#define DC_IB_LEAF0_CNUM 0x1A
-#define DC_IB_LEAF0_OFFSET 0x1B
-
-struct dc_info_leaf {
- u_int16_t dc_conntype;
- u_int8_t dc_blkcnt;
- u_int8_t dc_rsvd;
- u_int16_t dc_infoblk;
-};
-
-#define DC_CTYPE_10BT 0x0000
-#define DC_CTYPE_10BT_NWAY 0x0100
-#define DC_CTYPE_10BT_FDX 0x0204
-#define DC_CTYPE_10B2 0x0001
-#define DC_CTYPE_10B5 0x0002
-#define DC_CTYPE_100BT 0x0003
-#define DC_CTYPE_100BT_FDX 0x0205
-#define DC_CTYPE_100T4 0x0006
-#define DC_CTYPE_100FX 0x0007
-#define DC_CTYPE_100FX_FDX 0x0208
-#define DC_CTYPE_MII_10BT 0x0009
-#define DC_CTYPE_MII_10BT_FDX 0x020A
-#define DC_CTYPE_MII_100BT 0x000D
-#define DC_CTYPE_MII_100BT_FDX 0x020E
-#define DC_CTYPE_MII_100T4 0x000F
-#define DC_CTYPE_MII_100FX 0x0010
-#define DC_CTYPE_MII_100FX_FDX 0x0211
-#define DC_CTYPE_DYN_PUP_AUTOSENSE 0x0800
-#define DC_CTYPE_PUP_AUTOSENSE 0x8800
-#define DC_CTYPE_NOMEDIA 0xFFFF
-
-#define DC_EBLOCK_SIA 0x0002
-#define DC_EBLOCK_MII 0x0003
-#define DC_EBLOCK_SYM 0x0004
-#define DC_EBLOCK_RESET 0x0005
-#define DC_EBLOCK_PHY_SHUTDOWN 0x0006
-
-struct dc_leaf_hdr {
- u_int16_t dc_mtype;
- u_int8_t dc_mcnt;
- u_int8_t dc_rsvd;
-};
-
-struct dc_eblock_hdr {
- u_int8_t dc_len;
- u_int8_t dc_type;
-};
-
-struct dc_eblock_sia {
- struct dc_eblock_hdr dc_sia_hdr;
- u_int8_t dc_sia_code;
- union {
- struct dc_sia_ext { /* if (dc_sia_code & DC_SIA_CODE_EXT) */
- u_int8_t dc_sia_mediaspec[6]; /* CSR13, CSR14, CSR15 */
- u_int8_t dc_sia_gpio_ctl[2];
- u_int8_t dc_sia_gpio_dat[2];
- } dc_sia_ext;
- struct dc_sia_noext {
- u_int8_t dc_sia_gpio_ctl[2];
- u_int8_t dc_sia_gpio_dat[2];
- } dc_sia_noext;
- } dc_un;
-};
-
-#define DC_SIA_CODE_10BT 0x00
-#define DC_SIA_CODE_10B2 0x01
-#define DC_SIA_CODE_10B5 0x02
-#define DC_SIA_CODE_10BT_FDX 0x04
-#define DC_SIA_CODE_EXT 0x40
-
-/*
- * Note that the first word in the gpr and reset
- * sequences is always a control word.
- */
-struct dc_eblock_mii {
- struct dc_eblock_hdr dc_mii_hdr;
- u_int8_t dc_mii_phynum;
- u_int8_t dc_gpr_len;
-/* u_int16_t dc_gpr_dat[n]; */
-/* u_int8_t dc_reset_len; */
-/* u_int16_t dc_reset_dat[n]; */
-/* There are other fields after these, but we don't
- * care about them since they can be determined by looking
- * at the PHY.
- */
-};
-
-struct dc_eblock_sym {
- struct dc_eblock_hdr dc_sym_hdr;
- u_int8_t dc_sym_code;
- u_int8_t dc_sym_gpio_ctl[2];
- u_int8_t dc_sym_gpio_dat[2];
- u_int8_t dc_sym_cmd[2];
-};
-
-#define DC_SYM_CODE_100BT 0x03
-#define DC_SYM_CODE_100BT_FDX 0x05
-#define DC_SYM_CODE_100T4 0x06
-#define DC_SYM_CODE_100FX 0x07
-#define DC_SYM_CODE_100FX_FDX 0x08
-
-struct dc_eblock_reset {
- struct dc_eblock_hdr dc_reset_hdr;
- u_int8_t dc_reset_len;
-/* u_int16_t dc_reset_dat[n]; */
-};
OpenPOWER on IntegriCloud