dc(4) sync
Joerg Sonnenberger
joerg at britannica.bec.de
Tue Feb 1 14:08:54 PST 2005
Hi all,
if you have a dc(4) device, please test the attached diff.
It does a full sync with FreeBSD current, adds some more
hardware support and the like. It does remove some of the
code which is in the pci layer in FreeBSD, which we lack.
This shouldn't be a problem, since resume / suspend is not
supported.
I'd like to commit this at the end of the week.
Joerg
- sync with FreeBSD 1.153 / 1.43
- use BUS_DMA_WAITOK for allocations in dc_attach, 0 for dus_dmamap_load
- no sparc code, no SRM_MEDIA
- classic splimp locking kept
Index: Makefile
===================================================================
RCS file: /home/joerg/wd/repository/dragonflybsd/src/sys/dev/netif/dc/Makefile,v
retrieving revision 1.2
diff -u -r1.2 Makefile
--- Makefile 17 Jun 2003 04:28:43 -0000 1.2
+++ Makefile 1 Feb 2005 19:23:02 -0000
@@ -1,7 +1,6 @@
# $FreeBSD: src/sys/modules/dc/Makefile,v 1.2 2000/01/28 11:26:28 bde Exp $
# $DragonFly: src/sys/dev/netif/dc/Makefile,v 1.2 2003/06/17 04:28:43 dillon Exp $
-.PATH: ${.CURDIR}/../../pci
KMOD = if_dc
SRCS = if_dc.c opt_bdg.h device_if.h bus_if.h pci_if.h
SRCS += miibus_if.h
Index: if_dc.c
===================================================================
RCS file: /home/joerg/wd/repository/dragonflybsd/src/sys/dev/netif/dc/if_dc.c,v
retrieving revision 1.18
diff -u -r1.18 if_dc.c
--- if_dc.c 23 Jan 2005 20:21:30 -0000 1.18
+++ if_dc.c 1 Feb 2005 20:07:29 -0000
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul at xxxxxxxxxxxxxxx>. All rights reserved.
*
@@ -29,10 +29,8 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/if_dc.c,v 1.9.2.45 2003/06/08 14:31:53 mux Exp $
- * $DragonFly: src/sys/dev/netif/dc/if_dc.c,v 1.18 2005/01/23 20:21:30 joerg Exp $
- *
- * $FreeBSD: src/sys/pci/if_dc.c,v 1.9.2.45 2003/06/08 14:31:53 mux Exp $
+ * $FreeBSD: src/sys/pci/if_dc.c,v 1.153 2005/01/07 02:29:18 imp Exp $
+ * $DragonFly$
*/
/*
@@ -46,9 +44,13 @@
* 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.
@@ -91,11 +93,13 @@
*/
#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>
@@ -109,9 +113,6 @@
#include <net/bpf.h>
-#include <vm/vm.h> /* for vtophys */
-#include <vm/pmap.h> /* for vtophys */
-#include <machine/clock.h> /* for DELAY */
#include <machine/bus_pio.h>
#include <machine/bus_memio.h>
#include <machine/bus.h>
@@ -119,18 +120,15 @@
#include <sys/bus.h>
#include <sys/rman.h>
-#include "../mii_layer/mii.h"
-#include "../mii_layer/miivar.h"
+#include <dev/netif/mii_layer/mii.h>
+#include <dev/netif/mii_layer/miivar.h>
#include <bus/pci/pcireg.h>
#include <bus/pci/pcivar.h>
#define DC_USEIOSPACE
-#ifdef __alpha__
-#define SRM_MEDIA
-#endif
-#include "if_dcreg.h"
+#include <dev/netif/dc/if_dcreg.h>
/* "controller miibus0" required. See GENERIC if you get errors here. */
#include "miibus_if.h"
@@ -153,6 +151,12 @@
"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,
@@ -183,10 +187,26 @@
"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 }
};
@@ -195,12 +215,9 @@
static int dc_detach (device_t);
static int dc_suspend (device_t);
static int dc_resume (device_t);
-static void dc_acpi (device_t);
static struct dc_type *dc_devtype (device_t);
-static int dc_newbuf (struct dc_softc *, int, struct mbuf *);
-static int dc_encap (struct dc_softc *, struct mbuf *,
- u_int32_t *);
-static int dc_coal (struct dc_softc *, struct mbuf **);
+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 *);
@@ -209,8 +226,7 @@
static void dc_tx_underrun (struct dc_softc *);
static void dc_intr (void *);
static void dc_start (struct ifnet *);
-static int dc_ioctl (struct ifnet *, u_long, caddr_t,
- struct ucred *);
+static int dc_ioctl (struct ifnet *, u_long, caddr_t, struct ucred *);
static void dc_init (void *);
static void dc_stop (struct dc_softc *);
static void dc_watchdog (struct ifnet *);
@@ -224,9 +240,10 @@
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_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 *);
@@ -240,11 +257,12 @@
static void dc_miibus_mediainit (device_t);
static void dc_setcfg (struct dc_softc *, int);
-static u_int32_t dc_crc_le (struct dc_softc *, caddr_t);
-static u_int32_t dc_crc_be (caddr_t);
+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 *);
@@ -254,14 +272,16 @@
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_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
@@ -299,14 +319,14 @@
};
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 mdevget in dc driver");
+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
DECLARE_DUMMY_MODULE(if_dc);
+DRIVER_MODULE(if_dc, cardbus, dc_driver, dc_devclass, 0, 0);
DRIVER_MODULE(if_dc, pci, dc_driver, dc_devclass, 0, 0);
DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0);
@@ -319,17 +339,17 @@
#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
-static void dc_delay(sc)
- struct dc_softc *sc;
+static void
+dc_delay(struct dc_softc *sc)
{
- int idx;
+ int idx;
for (idx = (300 / 33) + 1; idx > 0; idx--)
CSR_READ_4(sc, DC_BUSCTL);
}
-static void dc_eeprom_width(sc)
- struct dc_softc *sc;
+static void
+dc_eeprom_width(struct dc_softc *sc)
{
int i;
@@ -392,10 +412,10 @@
dc_eeprom_idle(sc);
}
-static void dc_eeprom_idle(sc)
- struct dc_softc *sc;
+static void
+dc_eeprom_idle(struct dc_softc *sc)
{
- int i;
+ int i;
CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
dc_delay(sc);
@@ -418,18 +438,15 @@
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CS);
dc_delay(sc);
CSR_WRITE_4(sc, DC_SIO, 0x00000000);
-
- return;
}
/*
* Send a read command and address to the EEPROM, check for ACK.
*/
-static void dc_eeprom_putbyte(sc, addr)
- struct dc_softc *sc;
- int addr;
+static void
+dc_eeprom_putbyte(struct dc_softc *sc, int addr)
{
- int d, i;
+ int d, i;
d = DC_EECMD_READ >> 6;
for (i = 3; i--; ) {
@@ -459,8 +476,6 @@
SIO_CLR(DC_SIO_EE_CLK);
dc_delay(sc);
}
-
- return;
}
/*
@@ -468,15 +483,13 @@
* The PNIC 82c168/82c169 has its own non-standard way to read
* the EEPROM.
*/
-static void dc_eeprom_getword_pnic(sc, addr, dest)
- struct dc_softc *sc;
- int addr;
- u_int16_t *dest;
+static void
+dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, u_int16_t *dest)
{
- int i;
- u_int32_t r;
+ int i;
+ u_int32_t r;
- CSR_WRITE_4(sc, DC_PN_SIOCTL, DC_PN_EEOPCODE_READ|addr);
+ CSR_WRITE_4(sc, DC_PN_SIOCTL, DC_PN_EEOPCODE_READ | addr);
for (i = 0; i < DC_TIMEOUT; i++) {
DELAY(1);
@@ -486,20 +499,37 @@
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);
- return;
+ 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(sc, addr, dest)
- struct dc_softc *sc;
- int addr;
- u_int16_t *dest;
+static void
+dc_eeprom_getword(struct dc_softc *sc, int addr, u_int16_t *dest)
{
- int i;
- u_int16_t word = 0;
+ int i;
+ u_int16_t word = 0;
/* Force EEPROM to idle state. */
dc_eeprom_idle(sc);
@@ -536,36 +566,30 @@
dc_eeprom_idle(sc);
*dest = word;
-
- return;
}
/*
* Read a sequence of words from the EEPROM.
*/
-static void dc_read_eeprom(sc, dest, off, cnt, swap)
- struct dc_softc *sc;
- caddr_t dest;
- int off;
- int cnt;
- int swap;
+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;
+ 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 (swap)
- *ptr = ntohs(word);
+ if (be)
+ *ptr = be16toh(word);
else
- *ptr = word;
+ *ptr = le16toh(word);
}
-
- return;
}
/*
@@ -575,29 +599,26 @@
/*
* Write a bit to the MII bus.
*/
-static void dc_mii_writebit(sc, bit)
- struct dc_softc *sc;
- int bit;
+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);
+ 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);
-
- return;
}
/*
* Read a bit from the MII bus.
*/
-static int dc_mii_readbit(sc)
- struct dc_softc *sc;
+static int
+dc_mii_readbit(struct dc_softc *sc)
{
- CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_READ|DC_SIO_MII_DIR);
+ 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);
@@ -610,28 +631,24 @@
/*
* Sync the PHYs by setting data bit and strobing the clock 32 times.
*/
-static void dc_mii_sync(sc)
- struct dc_softc *sc;
+static void
+dc_mii_sync(struct dc_softc *sc)
{
- int i;
+ int i;
CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
for (i = 0; i < 32; i++)
dc_mii_writebit(sc, 1);
-
- return;
}
/*
* Clock a series of bits through the MII.
*/
-static void dc_mii_send(sc, bits, cnt)
- struct dc_softc *sc;
- u_int32_t bits;
- int cnt;
+static void
+dc_mii_send(struct dc_softc *sc, u_int32_t bits, int cnt)
{
- int i;
+ int i;
for (i = (0x1 << (cnt - 1)); i; i >>= 1)
dc_mii_writebit(sc, bits & i);
@@ -640,12 +657,10 @@
/*
* Read an PHY register through the MII.
*/
-static int dc_mii_readreg(sc, frame)
- struct dc_softc *sc;
- struct dc_mii_frame *frame;
-
+static int
+dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
- int i, ack, s;
+ int i, ack, s;
s = splimp();
@@ -656,7 +671,7 @@
frame->mii_opcode = DC_MII_READOP;
frame->mii_turnaround = 0;
frame->mii_data = 0;
-
+
/*
* Sync the PHYs.
*/
@@ -676,7 +691,7 @@
dc_mii_writebit(sc, 0);
#endif
- /* Check for ack */
+ /* Check for ack. */
ack = dc_mii_readbit(sc);
/*
@@ -684,9 +699,8 @@
* need to clock through 16 cycles to keep the PHY(s) in sync.
*/
if (ack) {
- for(i = 0; i < 16; i++) {
+ for (i = 0; i < 16; i++)
dc_mii_readbit(sc);
- }
goto fail;
}
@@ -712,12 +726,10 @@
/*
* Write to a PHY register through the MII.
*/
-static int dc_mii_writereg(sc, frame)
- struct dc_softc *sc;
- struct dc_mii_frame *frame;
-
+static int
+dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
- int s;
+ int s;
s = splimp();
/*
@@ -730,7 +742,7 @@
/*
* Sync the PHYs.
- */
+ */
dc_mii_sync(sc);
dc_mii_send(sc, frame->mii_stdelim, 2);
@@ -749,16 +761,15 @@
return(0);
}
-static int dc_miibus_readreg(dev, phy, reg)
- device_t dev;
- int phy, reg;
-{
- struct dc_mii_frame frame;
- struct dc_softc *sc;
- int i, rval, phy_reg = 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((char *)&frame, sizeof(frame));
+ bzero(&frame, sizeof(frame));
/*
* Note: both the AL981 and AN985 have internal PHYs,
@@ -782,7 +793,7 @@
if (sc->dc_pmode != DC_PMODE_MII) {
if (phy == (MII_NPHY - 1)) {
- switch(reg) {
+ switch (reg) {
case MII_BMSR:
/*
* Fake something to make the probe
@@ -823,7 +834,7 @@
}
if (DC_IS_COMET(sc)) {
- switch(reg) {
+ switch (reg) {
case MII_BMCR:
phy_reg = DC_AL_BMCR;
break;
@@ -872,16 +883,15 @@
return(frame.mii_data);
}
-static int dc_miibus_writereg(dev, phy, reg, data)
- device_t dev;
- int phy, reg, data;
-{
- struct dc_softc *sc;
- struct dc_mii_frame frame;
- int i, phy_reg = 0;
+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((char *)&frame, sizeof(frame));
+ bzero(&frame, sizeof(frame));
if (DC_IS_ADMTEK(sc) && phy != DC_ADMTEK_PHYADDR)
return(0);
@@ -900,7 +910,7 @@
}
if (DC_IS_COMET(sc)) {
- switch(reg) {
+ switch (reg) {
case MII_BMCR:
phy_reg = DC_AL_BMCR;
break;
@@ -948,12 +958,12 @@
return(0);
}
-static void dc_miibus_statchg(dev)
- device_t dev;
+static void
+dc_miibus_statchg(device_t dev)
{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifmedia *ifm;
+ struct dc_softc *sc;
+ struct mii_data *mii;
+ struct ifmedia *ifm;
sc = device_get_softc(dev);
if (DC_IS_ADMTEK(sc))
@@ -969,8 +979,6 @@
dc_setcfg(sc, mii->mii_media_active);
sc->dc_if_media = mii->mii_media_active;
}
-
- return;
}
/*
@@ -981,13 +989,13 @@
* the driver has to just 'know' about the additional mode and deal
* with it itself. *sigh*
*/
-static void dc_miibus_mediainit(dev)
- device_t dev;
+static void
+dc_miibus_mediainit(device_t dev)
{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifmedia *ifm;
- int rev;
+ struct dc_softc *sc;
+ struct mii_data *mii;
+ struct ifmedia *ifm;
+ int rev;
rev = pci_read_config(dev, DC_PCI_CFRV, 4) & 0xFF;
@@ -996,69 +1004,57 @@
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc) && rev >= DC_REVISION_DM9102A)
- ifmedia_add(ifm, IFM_ETHER|IFM_homePNA, 0, NULL);
-
- return;
+ ifmedia_add(ifm, IFM_ETHER | IFM_homePNA, 0, NULL);
}
-#define DC_POLY 0xEDB88320
#define DC_BITS_512 9
#define DC_BITS_128 7
#define DC_BITS_64 6
-static u_int32_t dc_crc_le(sc, addr)
- struct dc_softc *sc;
- caddr_t addr;
+static uint32_t
+dc_mchash_le(struct dc_softc *sc, const uint8_t *addr)
{
- u_int32_t idx, bit, data, crc;
+ uint32_t crc;
/* Compute CRC for the address value. */
- crc = 0xFFFFFFFF; /* initial value */
-
- for (idx = 0; idx < 6; idx++) {
- for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1)
- crc = (crc >> 1) ^ (((crc ^ data) & 1) ? DC_POLY : 0);
- }
+ 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));
+ 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));
+ return(crc & ((1 << DC_BITS_64) - 1));
- return (crc & ((1 << DC_BITS_512) - 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 u_int32_t dc_crc_be(addr)
- caddr_t addr;
+static uint32_t
+dc_mchash_be(const uint8_t *addr)
{
- u_int32_t crc, carry;
- int i, j;
- u_int8_t c;
+ uint32_t crc;
/* Compute CRC for the address value. */
- crc = 0xFFFFFFFF; /* initial value */
-
- for (i = 0; i < 6; i++) {
- c = *(addr + i);
- for (j = 0; j < 8; j++) {
- carry = ((crc & 0x80000000) ? 1 : 0) ^ (c & 0x01);
- crc <<= 1;
- c >>= 1;
- if (carry)
- crc = (crc ^ 0x04c11db6) | carry;
- }
- }
+ crc = ether_crc32_be(addr, ETHER_ADDR_LEN);
- /* return the filter bit position */
+ /* Return the filter bit position. */
return((crc >> 26) & 0x0000003F);
}
@@ -1072,14 +1068,14 @@
* frames. We also sneak the broadcast address into the hash filter since
* we need that too.
*/
-void dc_setfilt_21143(sc)
- struct dc_softc *sc;
+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;
+ struct dc_desc *sframe;
+ u_int32_t h, *sp;
+ struct ifmultiaddr *ifma;
+ struct ifnet *ifp;
+ int i;
ifp = &sc->arpcom.ac_if;
@@ -1087,14 +1083,14 @@
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 = (u_int32_t *)&sc->dc_cdata.dc_sbuf;
- bzero((char *)sp, DC_SFRAME_LEN);
+ sp = sc->dc_cdata.dc_sbuf;
+ bzero(sp, DC_SFRAME_LEN);
- sframe->dc_data = vtophys(&sc->dc_cdata.dc_sbuf);
- sframe->dc_ctl = DC_SFRAME_LEN | DC_TXCTL_SETUP | DC_TXCTL_TLINK |
- DC_FILTER_HASHPERF | DC_TXCTL_FINT;
+ 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;
+ 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)
@@ -1107,26 +1103,25 @@
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
- for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
- ifma = ifma->ifma_link.le_next) {
+ LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
- h = dc_crc_le(sc,
+ h = dc_mchash_le(sc,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- sp[h >> 4] |= 1 << (h & 0xF);
+ sp[h >> 4] |= htole32(1 << (h & 0xF));
}
if (ifp->if_flags & IFF_BROADCAST) {
- h = dc_crc_le(sc, ifp->if_broadcastaddr);
- sp[h >> 4] |= 1 << (h & 0xF);
+ h = dc_mchash_le(sc, ifp->if_broadcastaddr);
+ sp[h >> 4] |= htole32(1 << (h & 0xF));
}
/* Set our MAC address */
- sp[39] = ((u_int16_t *)sc->arpcom.ac_enaddr)[0];
- sp[40] = ((u_int16_t *)sc->arpcom.ac_enaddr)[1];
- sp[41] = ((u_int16_t *)sc->arpcom.ac_enaddr)[2];
+ sp[39] = DC_SP_MAC(((u_int16_t *)sc->arpcom.ac_enaddr)[0]);
+ sp[40] = DC_SP_MAC(((u_int16_t *)sc->arpcom.ac_enaddr)[1]);
+ sp[41] = DC_SP_MAC(((u_int16_t *)sc->arpcom.ac_enaddr)[2]);
- sframe->dc_status = DC_TXSTAT_OWN;
+ sframe->dc_status = htole32(DC_TXSTAT_OWN);
CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
/*
@@ -1138,21 +1133,19 @@
DELAY(10000);
ifp->if_timer = 5;
-
- return;
}
-void dc_setfilt_admtek(sc)
- struct dc_softc *sc;
+static void
+dc_setfilt_admtek(struct dc_softc *sc)
{
- struct ifnet *ifp;
- int h = 0;
- u_int32_t hashes[2] = { 0, 0 };
- struct ifmultiaddr *ifma;
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ int h = 0;
+ u_int32_t hashes[2] = { 0, 0 };
ifp = &sc->arpcom.ac_if;
- /* Init our MAC address */
+ /* Init our MAC address. */
CSR_WRITE_4(sc, DC_AL_PAR0, *(u_int32_t *)(&sc->arpcom.ac_enaddr[0]));
CSR_WRITE_4(sc, DC_AL_PAR1, *(u_int32_t *)(&sc->arpcom.ac_enaddr[4]));
@@ -1167,7 +1160,7 @@
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
- /* first, zot all the existing hash bits */
+ /* First, zot all the existing hash bits. */
CSR_WRITE_4(sc, DC_AL_MAR0, 0);
CSR_WRITE_4(sc, DC_AL_MAR1, 0);
@@ -1175,18 +1168,19 @@
* 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))
+ if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))
return;
- /* now program new ones */
- for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
- ifma = ifma->ifma_link.le_next) {
+ /* Now program new ones. */
+ LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
if (DC_IS_CENTAUR(sc))
- h = dc_crc_le(sc, LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ h = dc_mchash_le(sc,
+ LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
else
- h = dc_crc_be(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ h = dc_mchash_be(
+ LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
if (h < 32)
hashes[0] |= (1 << h);
else
@@ -1195,26 +1189,24 @@
CSR_WRITE_4(sc, DC_AL_MAR0, hashes[0]);
CSR_WRITE_4(sc, DC_AL_MAR1, hashes[1]);
-
- return;
}
-void dc_setfilt_asix(sc)
- struct dc_softc *sc;
+static void
+dc_setfilt_asix(struct dc_softc *sc)
{
- struct ifnet *ifp;
- int h = 0;
- u_int32_t hashes[2] = { 0, 0 };
- struct ifmultiaddr *ifma;
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ int h = 0;
+ u_int32_t hashes[2] = { 0, 0 };
- /* Init our MAC address */
- CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR0);
- CSR_WRITE_4(sc, DC_AX_FILTDATA,
+ /* 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 *)(&sc->arpcom.ac_enaddr[0]));
- CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR1);
- CSR_WRITE_4(sc, DC_AX_FILTDATA,
+ CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR1);
+ CSR_WRITE_4(sc, DC_AX_FILTDATA,
*(u_int32_t *)(&sc->arpcom.ac_enaddr[4]));
/* If we want promiscuous mode, set the allframes bit. */
@@ -1247,15 +1239,14 @@
* 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))
+ if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))
return;
/* now program new ones */
- for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
- ifma = ifma->ifma_link.le_next) {
+ LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
- h = dc_crc_be(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ h = dc_mchash_be(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
if (h < 32)
hashes[0] |= (1 << h);
else
@@ -1266,12 +1257,78 @@
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->arpcom.ac_if;
+ 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);
+
+ LIST_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));
+ }
- return;
+ 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 *)sc->arpcom.ac_enaddr)[0]);
+ sp[1] = DC_SP_MAC(((u_int16_t *)sc->arpcom.ac_enaddr)[1]);
+ sp[2] = DC_SP_MAC(((u_int16_t *)sc->arpcom.ac_enaddr)[2]);
+
+ DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
+ DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON);
+ ifp->if_flags |= IFF_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(sc)
- struct dc_softc *sc;
+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))
@@ -1283,32 +1340,33 @@
if (DC_IS_ADMTEK(sc))
dc_setfilt_admtek(sc);
- return;
+ 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.
+ * 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(sc, media)
- struct dc_softc *sc;
- int media;
+static void
+dc_setcfg(struct dc_softc *sc, int media)
{
- int i, restart = 0;
- u_int32_t isr;
+ 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)) {
+ 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));
+ 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)
+ 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);
}
@@ -1322,10 +1380,8 @@
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT);
if (sc->dc_pmode == DC_PMODE_MII) {
- int watchdogreg;
-
if (DC_IS_INTEL(sc)) {
- /* there's a write enable bit here that reads as 1 */
+ /* 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;
@@ -1333,10 +1389,10 @@
} else {
DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS);
}
- DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS|
- DC_NETCFG_PORTSEL|DC_NETCFG_SCRAMBLER));
+ 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_SETBIT(sc, DC_NETCFG, (DC_NETCFG_PCS |
DC_NETCFG_SCRAMBLER));
if (!DC_IS_DAVICOM(sc))
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
@@ -1355,7 +1411,7 @@
if (DC_IS_INTEL(sc))
dc_apply_fixup(sc,
(media & IFM_GMASK) == IFM_FDX ?
- IFM_100_TX|IFM_FDX : IFM_100_TX);
+ IFM_100_TX | IFM_FDX : IFM_100_TX);
}
}
@@ -1363,9 +1419,7 @@
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL);
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT);
if (sc->dc_pmode == DC_PMODE_MII) {
- int watchdogreg;
-
- /* there's a write enable bit here that reads as 1 */
+ /* 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;
@@ -1374,8 +1428,8 @@
} else {
DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS);
}
- DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS|
- DC_NETCFG_PORTSEL|DC_NETCFG_SCRAMBLER));
+ 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))
@@ -1404,7 +1458,7 @@
DC_TCTL_AUTONEGENBL);
dc_apply_fixup(sc,
(media & IFM_GMASK) == IFM_FDX ?
- IFM_10_T|IFM_FDX : IFM_10_T);
+ IFM_10_T | IFM_FDX : IFM_10_T);
DELAY(20000);
}
}
@@ -1435,15 +1489,13 @@
}
if (restart)
- DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON|DC_NETCFG_RX_ON);
-
- return;
+ DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON | DC_NETCFG_RX_ON);
}
-static void dc_reset(sc)
- struct dc_softc *sc;
+static void
+dc_reset(struct dc_softc *sc)
{
- int i;
+ int i;
DC_SETBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET);
@@ -1453,7 +1505,8 @@
break;
}
- if (DC_IS_ASIX(sc) || DC_IS_ADMTEK(sc) || DC_IS_CONEXANT(sc)) {
+ 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;
@@ -1480,19 +1533,17 @@
CSR_WRITE_4(sc, DC_10BTCTRL, 0);
CSR_WRITE_4(sc, DC_WATCHDOG, 0);
}
-
- return;
}
-static struct dc_type *dc_devtype(dev)
- device_t dev;
+static struct dc_type *
+dc_devtype(device_t dev)
{
- struct dc_type *t;
- u_int32_t rev;
+ struct dc_type *t;
+ u_int32_t rev;
t = dc_devs;
- while(t->dc_name != NULL) {
+ while (t->dc_name != NULL) {
if ((pci_get_vendor(dev) == t->dc_vid) &&
(pci_get_device(dev) == t->dc_did)) {
/* Check the PCI revision */
@@ -1518,6 +1569,18 @@
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++;
@@ -1535,10 +1598,10 @@
* 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(dev)
- device_t dev;
+static int
+dc_probe(device_t dev)
{
- struct dc_type *t;
+ struct dc_type *t;
t = dc_devtype(dev);
@@ -1550,52 +1613,13 @@
return(ENXIO);
}
-static void dc_acpi(dev)
- device_t dev;
-{
- u_int32_t r, cptr;
- int unit;
-
- unit = device_get_unit(dev);
-
- /* Find the location of the capabilities block */
- cptr = pci_read_config(dev, DC_PCI_CCAP, 4) & 0xFF;
-
- r = pci_read_config(dev, cptr, 4) & 0xFF;
- if (r == 0x01) {
-
- r = pci_read_config(dev, cptr + 4, 4);
- if (r & DC_PSTATE_D3) {
- u_int32_t iobase, membase, irq;
-
- /* Save important PCI config data. */
- iobase = pci_read_config(dev, DC_PCI_CFBIO, 4);
- membase = pci_read_config(dev, DC_PCI_CFBMA, 4);
- irq = pci_read_config(dev, DC_PCI_CFIT, 4);
-
- /* Reset the power state. */
- printf("dc%d: chip is in D%d power mode "
- "-- setting to D0\n", unit, r & DC_PSTATE_D3);
- r &= 0xFFFFFFFC;
- pci_write_config(dev, cptr + 4, r, 4);
-
- /* Restore PCI config data. */
- pci_write_config(dev, DC_PCI_CFBIO, iobase, 4);
- pci_write_config(dev, DC_PCI_CFBMA, membase, 4);
- pci_write_config(dev, DC_PCI_CFIT, irq, 4);
- }
- }
- return;
-}
-
-static void dc_apply_fixup(sc, media)
- struct dc_softc *sc;
- int media;
+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;
+ struct dc_mediainfo *m;
+ u_int8_t *p;
+ int i;
+ u_int32_t reg;
m = sc->dc_mi;
@@ -1617,52 +1641,63 @@
reg = (p[0] | (p[1] << 8)) << 16;
CSR_WRITE_4(sc, DC_WATCHDOG, reg);
}
-
- return;
}
-static void dc_decode_leaf_sia(sc, l)
- struct dc_softc *sc;
- struct dc_eblock_sia *l;
+static void
+dc_decode_leaf_sia(struct dc_softc *sc, struct dc_eblock_sia *l)
{
- struct dc_mediainfo *m;
+ struct dc_mediainfo *m;
m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_INTWAIT | M_ZERO);
- if (l->dc_sia_code == DC_SIA_CODE_10BT)
+ switch (l->dc_sia_code & ~DC_SIA_CODE_EXT) {
+ case DC_SIA_CODE_10BT:
m->dc_media = IFM_10_T;
-
- if (l->dc_sia_code == DC_SIA_CODE_10BT_FDX)
- m->dc_media = IFM_10_T|IFM_FDX;
-
- if (l->dc_sia_code == DC_SIA_CODE_10B2)
+ 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;
-
- if (l->dc_sia_code == DC_SIA_CODE_10B5)
+ break;
+ case DC_SIA_CODE_10B5:
m->dc_media = IFM_10_5;
+ break;
+ default:
+ break;
+ }
- m->dc_gp_len = 2;
- m->dc_gp_ptr = (u_int8_t *)&l->dc_sia_gpio_ctl;
+ /*
+ * 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;
-
- return;
}
-static void dc_decode_leaf_sym(sc, l)
- struct dc_softc *sc;
- struct dc_eblock_sym *l;
+static void
+dc_decode_leaf_sym(struct dc_softc *sc, struct dc_eblock_sym *l)
{
- struct dc_mediainfo *m;
+ struct dc_mediainfo *m;
m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_INTWAIT | 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_media = IFM_100_TX | IFM_FDX;
m->dc_gp_len = 2;
m->dc_gp_ptr = (u_int8_t *)&l->dc_sym_gpio_ctl;
@@ -1671,16 +1706,13 @@
sc->dc_mi = m;
sc->dc_pmode = DC_PMODE_SYM;
-
- return;
}
-static void dc_decode_leaf_mii(sc, l)
- struct dc_softc *sc;
- struct dc_eblock_mii *l;
+static void
+dc_decode_leaf_mii(struct dc_softc *sc, struct dc_eblock_mii *l)
{
- u_int8_t *p;
- struct dc_mediainfo *m;
+ struct dc_mediainfo *m;
+ u_int8_t *p;
m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_INTWAIT | M_ZERO);
/* We abuse IFM_AUTO to represent MII. */
@@ -1697,13 +1729,10 @@
m->dc_next = sc->dc_mi;
sc->dc_mi = m;
-
- return;
}
-static void dc_read_srom(sc, bits)
- struct dc_softc *sc;
- int bits;
+static void
+dc_read_srom(struct dc_softc *sc, int bits)
{
int size;
@@ -1712,14 +1741,13 @@
dc_read_eeprom(sc, (caddr_t)sc->dc_srom, 0, (size / 2), 0);
}
-static void dc_parse_21143_srom(sc)
- struct dc_softc *sc;
+static void
+dc_parse_21143_srom(struct dc_softc *sc)
{
- struct dc_leaf_hdr *lhdr;
- struct dc_eblock_hdr *hdr;
- int i, loff;
- char *ptr;
- int have_mii;
+ 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];
@@ -1747,7 +1775,7 @@
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) {
+ switch (hdr->dc_type) {
case DC_EBLOCK_MII:
dc_decode_leaf_mii(sc, (struct dc_eblock_mii *)hdr);
break;
@@ -1768,62 +1796,45 @@
ptr += (hdr->dc_len & 0x7F);
ptr++;
}
+}
- return;
+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(dev)
- device_t dev;
+static int
+dc_attach(device_t dev)
{
- int s, tmp = 0;
- u_char eaddr[ETHER_ADDR_LEN];
- u_int32_t command;
- struct dc_softc *sc;
- struct ifnet *ifp;
- u_int32_t revision;
- int unit, error = 0, rid, mac_offset;
-
- s = splimp();
+ 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 unit, error = 0, rid, mac_offset;
+ int i;
+ u_int8_t *mac;
sc = device_get_softc(dev);
unit = device_get_unit(dev);
- bzero(sc, sizeof(struct dc_softc));
- callout_init(&sc->dc_stat_timer);
-
- /*
- * Handle power management nonsense.
- */
- dc_acpi(dev);
/*
* Map control/status registers.
*/
- command = pci_read_config(dev, PCIR_COMMAND, 4);
- command |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
- pci_write_config(dev, PCIR_COMMAND, command, 4);
- command = pci_read_config(dev, PCIR_COMMAND, 4);
-
-#ifdef DC_USEIOSPACE
- if (!(command & PCIM_CMD_PORTEN)) {
- printf("dc%d: failed to enable I/O ports!\n", unit);
- error = ENXIO;
- goto fail;
- }
-#else
- if (!(command & PCIM_CMD_MEMEN)) {
- printf("dc%d: failed to enable memory mapping!\n", unit);
- error = ENXIO;
- goto fail;
- }
-#endif
+ pci_enable_busmaster(dev);
rid = DC_RID;
- sc->dc_res = bus_alloc_resource(dev, DC_RES, &rid,
- 0, ~0, 1, RF_ACTIVE);
+ sc->dc_res = bus_alloc_resource_any(dev, DC_RES, &rid, RF_ACTIVE);
if (sc->dc_res == NULL) {
printf("dc%d: couldn't map ports/memory\n", unit);
@@ -1834,40 +1845,30 @@
sc->dc_btag = rman_get_bustag(sc->dc_res);
sc->dc_bhandle = rman_get_bushandle(sc->dc_res);
- /* Allocate interrupt */
+ /* Allocate interrupt. */
rid = 0;
- sc->dc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ sc->dc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE);
if (sc->dc_irq == NULL) {
printf("dc%d: couldn't map interrupt\n", unit);
- bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res);
error = ENXIO;
goto fail;
}
- error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET,
- dc_intr, sc, &sc->dc_intrhand);
-
- if (error) {
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq);
- bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res);
- printf("dc%d: couldn't set up irq\n", unit);
- 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 has diff eeprom */
- if (sc->dc_info->dc_did != DC_DEVICEID_82C168)
+ /* 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) {
+ 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_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);
@@ -1876,8 +1877,9 @@
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_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);
@@ -1893,14 +1895,21 @@
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;
- dc_read_srom(sc, sc->dc_romwidth);
+ /* Don't read SROM for - auto-loaded on reset */
break;
case DC_DEVICEID_98713:
case DC_DEVICEID_98713_CP:
@@ -1912,7 +1921,7 @@
sc->dc_flags |= DC_21143_NWAY;
}
sc->dc_flags |= DC_REDUCED_MII_POLL;
- sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
+ sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
break;
case DC_DEVICEID_987x5:
case DC_DEVICEID_EN1217:
@@ -1927,22 +1936,22 @@
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;
+ 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;
+ 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;
+ 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_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_WAITOK);
if (revision < DC_REVISION_82C169)
@@ -1950,10 +1959,21 @@
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_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;
@@ -1978,9 +1998,9 @@
dc_reset(sc);
/* Take 21143 out of snooze mode */
- if (DC_IS_INTEL(sc)) {
+ 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);
+ command &= ~(DC_CFDD_SNOOZE_MODE | DC_CFDD_SLEEP_MODE);
pci_write_config(dev, DC_PCI_CFDD, command, 4);
}
@@ -2017,18 +2037,30 @@
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);
+ 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:
- bcopy(&sc->dc_srom[DC_AL_EE_NODEADDR], (caddr_t)&eaddr,
- ETHER_ADDR_LEN);
- dc_read_eeprom(sc, (caddr_t)&eaddr, DC_AL_EE_NODEADDR, 3, 0);
+ *(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, 6);
+ 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);
@@ -2037,25 +2069,97 @@
sc->dc_unit = unit;
- sc->dc_ldata = contigmalloc(sizeof(struct dc_list_data), M_DEVBUF,
- M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0);
+ /* 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, &sc->dc_ltag);
+ if (error) {
+ printf("dc%d: failed to allocate busdma tag\n", unit);
+ error = ENXIO;
+ goto fail;
+ }
+ error = bus_dmamem_alloc(sc->dc_ltag, (void **)&sc->dc_ldata,
+ BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->dc_lmap);
+ if (error) {
+ printf("dc%d: failed to allocate DMA safe memory\n", unit);
+ 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, 0);
+ if (error) {
+ printf("dc%d: cannot get address of the descriptors\n", unit);
+ error = ENXIO;
+ goto fail;
+ }
- if (sc->dc_ldata == NULL) {
- printf("dc%d: no memory for list buffers!\n", unit);
- if (sc->dc_pnic_rx_buf != NULL)
- free(sc->dc_pnic_rx_buf, M_DEVBUF);
- bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq);
- bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res);
+ /*
+ * 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, &sc->dc_stag);
+ if (error) {
+ printf("dc%d: failed to allocate busdma tag\n", unit);
+ error = ENXIO;
+ goto fail;
+ }
+ error = bus_dmamem_alloc(sc->dc_stag, (void **)&sc->dc_cdata.dc_sbuf,
+ BUS_DMA_WAITOK, &sc->dc_smap);
+ if (error) {
+ printf("dc%d: failed to allocate DMA safe memory\n", unit);
+ 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, 0);
+ if (error) {
+ printf("dc%d: cannot get address of the descriptors\n", unit);
error = ENXIO;
goto fail;
}
- bzero(sc->dc_ldata, sizeof(struct dc_list_data));
+ /* Allocate a busdma tag for mbufs. */
+ error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES * DC_TX_LIST_CNT,
+ DC_TX_LIST_CNT, MCLBYTES, 0, &sc->dc_mtag);
+ if (error) {
+ printf("dc%d: failed to allocate busdma tag\n", unit);
+ 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) {
+ printf("dc%d: failed to init TX ring\n", unit);
+ 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) {
+ printf("dc%d: failed to init RX ring\n", unit);
+ error = ENXIO;
+ goto fail;
+ }
+ }
+ error = bus_dmamap_create(sc->dc_mtag, 0, &sc->dc_sparemap);
+ if (error) {
+ printf("dc%d: failed to init RX ring\n", unit);
+ error = ENXIO;
+ goto fail;
+ }
ifp = &sc->arpcom.ac_if;
ifp->if_softc = sc;
- if_initname(ifp, "dc", unit);
+ 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;
@@ -2063,7 +2167,9 @@
ifp->if_watchdog = dc_watchdog;
ifp->if_init = dc_init;
ifp->if_baudrate = 10000000;
- ifp->if_snd.ifq_maxlen = DC_TX_LIST_CNT - 1;
+ IFQ_SET_MAXLEN(&ifp->if_snd, DC_TX_LIST_CNT - 1);
+ IFQ_SET_DRV_MAXLEN(&ifp->if_snd, 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
@@ -2102,21 +2208,21 @@
if (error) {
printf("dc%d: MII without any PHY!\n", sc->dc_unit);
- contigfree(sc->dc_ldata, sizeof(struct dc_list_data),
- M_DEVBUF);
- if (sc->dc_pnic_rx_buf != NULL)
- free(sc->dc_pnic_rx_buf, M_DEVBUF);
- bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq);
- bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res);
- error = ENXIO;
goto fail;
}
- /*
- * Call MI attach routine.
- */
- ether_ifattach(ifp, eaddr);
+ 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);
+ }
if (DC_IS_ADMTEK(sc)) {
/*
@@ -2129,68 +2235,91 @@
* 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;
+#ifdef DEVICE_POLLING
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif
+ ifp->if_capenable = ifp->if_capabilities;
-#ifdef SRM_MEDIA
- sc->dc_srm_media = 0;
+ callout_init(&sc->dc_stat_ch);
- /* 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,
+ dc_intr, sc, &sc->dc_intrhand);
-fail:
- splx(s);
+ if (error) {
+ printf("dc%d: couldn't set up irq\n", unit);
+ ether_ifdetach(ifp);
+ goto fail;
+ }
+fail:
+ if (error)
+ dc_detach(dev);
return(error);
}
-static int dc_detach(dev)
- device_t dev;
-{
- struct dc_softc *sc;
- struct ifnet *ifp;
- int s;
- struct dc_mediainfo *m;
-
- s = splimp();
+/*
+ * 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 ,s;
sc = device_get_softc(dev);
+
ifp = &sc->arpcom.ac_if;
- dc_stop(sc);
- ether_ifdetach(ifp);
+ s = splimp();
+ /* These should only be active if attach succeeded */
+ if (device_is_attached(dev)) {
+ dc_stop(sc);
+ ether_ifdetach(ifp);
+ }
+ if (sc->dc_miibus)
+ device_delete_child(dev, sc->dc_miibus);
bus_generic_detach(dev);
- device_delete_child(dev, sc->dc_miibus);
- bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq);
- bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res);
+ 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 (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);
+ for (i = 0; i < DC_TX_LIST_CNT; i++)
+ bus_dmamap_destroy(sc->dc_mtag, sc->dc_cdata.dc_tx_map[i]);
+ for (i = 0; i < DC_RX_LIST_CNT; i++)
+ 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);
- contigfree(sc->dc_ldata, sizeof(struct dc_list_data), M_DEVBUF);
- if (sc->dc_pnic_rx_buf != NULL)
- free(sc->dc_pnic_rx_buf, M_DEVBUF);
+ free(sc->dc_pnic_rx_buf, M_DEVBUF);
- while(sc->dc_mi != NULL) {
+ while (sc->dc_mi != NULL) {
m = sc->dc_mi->dc_next;
free(sc->dc_mi, M_DEVBUF);
sc->dc_mi = m;
@@ -2205,30 +2334,29 @@
/*
* Initialize the transmit descriptors.
*/
-static int dc_list_tx_init(sc)
- struct dc_softc *sc;
+static int
+dc_list_tx_init(struct dc_softc *sc)
{
- struct dc_chain_data *cd;
- struct dc_list_data *ld;
- int i;
+ 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)) {
- ld->dc_tx_list[i].dc_next =
- vtophys(&ld->dc_tx_list[0]);
- } else {
- ld->dc_tx_list[i].dc_next =
- vtophys(&ld->dc_tx_list[i + 1]);
- }
+ 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);
}
@@ -2238,63 +2366,74 @@
* we arrange the descriptors in a closed ring, so that the last descriptor
* points back to the first.
*/
-static int dc_list_rx_init(sc)
- struct dc_softc *sc;
+static int
+dc_list_rx_init(struct dc_softc *sc)
{
- struct dc_chain_data *cd;
- struct dc_list_data *ld;
- int i;
+ 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)) {
- ld->dc_rx_list[i].dc_next =
- vtophys(&ld->dc_rx_list[0]);
- } else {
- ld->dc_rx_list[i].dc_next =
- vtophys(&ld->dc_rx_list[i + 1]);
- }
+ 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(sc, i, m)
- struct dc_softc *sc;
- int i;
- struct mbuf *m;
+static int
+dc_newbuf(struct dc_softc *sc, int i, int alloc)
{
- struct mbuf *m_new = NULL;
- struct dc_desc *c;
+ struct mbuf *m_new;
+ bus_dmamap_t tmp;
+ int error;
- c = &sc->dc_ldata->dc_rx_list[i];
-
- if (m == NULL) {
- MGETHDR(m_new, MB_DONTWAIT, MT_DATA);
+ if (alloc) {
+ m_new = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
if (m_new == NULL)
return(ENOBUFS);
-
- MCLGET(m_new, MB_DONTWAIT);
- if (!(m_new->m_flags & M_EXT)) {
- m_freem(m_new);
- return(ENOBUFS);
- }
- m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
} else {
- m_new = m;
- m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+ 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));
/*
@@ -2303,13 +2442,34 @@
* 82c169 chips.
*/
if (sc->dc_flags & DC_PNIC_RX_BUG_WAR)
- bzero((char *)mtod(m_new, char *), m_new->m_len);
+ bzero(mtod(m_new, char *), m_new->m_len);
- sc->dc_cdata.dc_rx_chain[i] = m_new;
- c->dc_data = vtophys(mtod(m_new, caddr_t));
- c->dc_ctl = DC_RXCTL_RLINK | DC_RXLEN;
- c->dc_status = DC_RXSTAT_OWN;
+ /* 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);
}
@@ -2365,17 +2525,16 @@
* the time.
*/
-#define DC_WHOLEFRAME (DC_RXSTAT_FIRSTFRAG|DC_RXSTAT_LASTFRAG)
-static void dc_pnic_rx_bug_war(sc, idx)
- 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;
+#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];
@@ -2385,14 +2544,14 @@
/* Copy all the bytes from the bogus buffers. */
while (1) {
c = &sc->dc_ldata->dc_rx_list[i];
- rxstat = c->dc_status;
+ 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, m);
+ dc_newbuf(sc, i, 0);
DC_INC(i, DC_RX_LIST_CNT);
}
@@ -2400,7 +2559,7 @@
total_len = DC_RXBYTES(rxstat);
/* Scan backwards until we hit a non-zero byte. */
- while(*ptr == 0x00)
+ while (*ptr == 0x00)
ptr--;
/* Round off. */
@@ -2415,13 +2574,11 @@
/*
* Now copy the salvaged frame to the last mbuf and fake up
* the status word to make it look like a successful
- * frame reception.
+ * frame reception.
*/
- dc_newbuf(sc, i, m);
- bcopy(ptr, mtod(m, char *), total_len);
- cur_rx->dc_status = rxstat | DC_RXSTAT_FIRSTFRAG;
-
- return;
+ dc_newbuf(sc, i, 0);
+ bcopy(ptr, mtod(m, char *), total_len);
+ cur_rx->dc_status = htole32(rxstat | DC_RXSTAT_FIRSTFRAG);
}
/*
@@ -2435,17 +2592,17 @@
* 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(sc)
- struct dc_softc *sc;
+static int
+dc_rx_resync(struct dc_softc *sc)
{
- int i, pos;
- struct dc_desc *cur_rx;
+ 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 (!(cur_rx->dc_status & DC_RXSTAT_OWN))
+ if (!(le32toh(cur_rx->dc_status) & DC_RXSTAT_OWN))
break;
DC_INC(pos, DC_RX_LIST_CNT);
}
@@ -2464,30 +2621,33 @@
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
*/
-static void dc_rxeof(sc)
- struct dc_softc *sc;
+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;
+ struct mbuf *m;
+ struct ifnet *ifp;
+ struct dc_desc *cur_rx;
+ int i, total_len = 0;
+ u_int32_t rxstat;
ifp = &sc->arpcom.ac_if;
i = sc->dc_cdata.dc_rx_prod;
- while(!(sc->dc_ldata->dc_rx_list[i].dc_status & DC_RXSTAT_OWN)) {
-
+ 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_flags & IFF_POLLING) {
if (sc->rxcycles <= 0)
break;
sc->rxcycles--;
}
-#endif /* DEVICE_POLLING */
+#endif
cur_rx = &sc->dc_ldata->dc_rx_list[i];
- rxstat = cur_rx->dc_status;
+ 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) {
@@ -2499,21 +2659,19 @@
continue;
}
dc_pnic_rx_bug_war(sc, i);
- rxstat = cur_rx->dc_status;
+ rxstat = le32toh(cur_rx->dc_status);
total_len = DC_RXBYTES(rxstat);
}
}
- sc->dc_cdata.dc_rx_chain[i] = NULL;
-
/*
* 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
+ * frames as errors since they could be vlans.
*/
- if ((rxstat & DC_RXSTAT_RXERR)){
+ if ((rxstat & DC_RXSTAT_RXERR)) {
if (!(rxstat & DC_RXSTAT_GIANT) ||
(rxstat & (DC_RXSTAT_CRCERR | DC_RXSTAT_DRIBBLE |
DC_RXSTAT_MIIERE | DC_RXSTAT_COLLSEEN |
@@ -2521,7 +2679,7 @@
ifp->if_ierrors++;
if (rxstat & DC_RXSTAT_COLLSEEN)
ifp->if_collisions++;
- dc_newbuf(sc, i, m);
+ dc_newbuf(sc, i, 0);
if (rxstat & DC_RXSTAT_CRCERR) {
DC_INC(i, DC_RX_LIST_CNT);
continue;
@@ -2532,9 +2690,8 @@
}
}
- /* No errors; receive the packet. */
+ /* No errors; receive the packet. */
total_len -= ETHER_CRC_LEN;
-
#ifdef __i386__
/*
* On the x86 we do not have alignment problems, so try to
@@ -2545,7 +2702,7 @@
* if the allocation fails, then use m_devget and leave the
* existing buffer in the receive ring.
*/
- if (dc_quick && dc_newbuf(sc, i, NULL) == 0) {
+ 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);
@@ -2556,7 +2713,7 @@
m0 = m_devget(mtod(m, char *) - ETHER_ALIGN,
total_len + ETHER_ALIGN, 0, ifp, NULL);
- dc_newbuf(sc, i, m);
+ dc_newbuf(sc, i, 0);
DC_INC(i, DC_RX_LIST_CNT);
if (m0 == NULL) {
ifp->if_ierrors++;
@@ -2579,12 +2736,12 @@
*/
static void
-dc_txeof(sc)
- struct dc_softc *sc;
+dc_txeof(struct dc_softc *sc)
{
- struct dc_desc *cur_tx = NULL;
- struct ifnet *ifp;
- int idx;
+ struct dc_desc *cur_tx = NULL;
+ struct ifnet *ifp;
+ int idx;
+ u_int32_t ctl, txstat;
ifp = &sc->arpcom.ac_if;
@@ -2592,19 +2749,19 @@
* 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) {
- u_int32_t txstat;
+ while (idx != sc->dc_cdata.dc_tx_prod) {
cur_tx = &sc->dc_ldata->dc_tx_list[idx];
- txstat = cur_tx->dc_status;
+ txstat = le32toh(cur_tx->dc_status);
+ ctl = le32toh(cur_tx->dc_ctl);
if (txstat & DC_TXSTAT_OWN)
break;
- if (!(cur_tx->dc_ctl & DC_TXCTL_LASTFRAG) ||
- cur_tx->dc_ctl & DC_TXCTL_SETUP) {
- if (cur_tx->dc_ctl & DC_TXCTL_SETUP) {
+ 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
@@ -2625,24 +2782,25 @@
continue;
}
- if (DC_IS_CONEXANT(sc)) {
+ if (DC_IS_XIRCOM(sc) || DC_IS_CONEXANT(sc)) {
/*
- * For some reason Conexant chips like
- * setting the CARRLOST flag even when
- * the carrier is there. In CURRENT we
- * have the same problem for Xircom
- * cards !
+ * 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|
+ ((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 & 0xFFFF) & ~(DC_TXSTAT_ERRSUM |
+ DC_TXSTAT_NOCARRIER | DC_TXSTAT_CARRLOST)))
txstat &= ~DC_TXSTAT_ERRSUM;
}
@@ -2662,6 +2820,11 @@
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;
}
@@ -2671,27 +2834,24 @@
}
if (idx != sc->dc_cdata.dc_tx_cons) {
- /* some buffers have been freed */
+ /* Some buffers have been freed. */
sc->dc_cdata.dc_tx_cons = idx;
ifp->if_flags &= ~IFF_OACTIVE;
}
ifp->if_timer = (sc->dc_cdata.dc_tx_cnt == 0) ? 0 : 5;
-
- return;
}
-static void dc_tick(xsc)
- void *xsc;
+static void
+dc_tick(void *xsc)
{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifnet *ifp;
- int s;
- u_int32_t r;
-
- s = splimp();
+ struct dc_softc *sc;
+ struct mii_data *mii;
+ struct ifnet *ifp;
+ u_int32_t r;
+ int s;
sc = xsc;
+ s = splimp();
ifp = &sc->arpcom.ac_if;
mii = device_get_softc(sc->dc_miibus);
@@ -2713,10 +2873,11 @@
} else {
r = CSR_READ_4(sc, DC_ISR);
if ((r & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT &&
- sc->dc_cdata.dc_tx_cnt == 0)
+ 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);
@@ -2740,35 +2901,30 @@
* 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_pollstat(mii);
- if (mii->mii_media_status & IFM_ACTIVE &&
- IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
- sc->dc_link++;
- if (ifp->if_snd.ifq_head != NULL)
- dc_start(ifp);
- }
+ 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(ifp);
}
if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link)
- callout_reset(&sc->dc_stat_timer, hz / 10, dc_tick, sc);
+ callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
else
- callout_reset(&sc->dc_stat_timer, hz, dc_tick, sc);
+ callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
splx(s);
-
- return;
}
/*
* 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(sc)
- struct dc_softc *sc;
+static void
+dc_tx_underrun(struct dc_softc *sc)
{
- u_int32_t isr;
- int i;
+ u_int32_t isr;
+ int i;
if (DC_IS_DAVICOM(sc))
dc_init(sc);
@@ -2807,8 +2963,6 @@
if (DC_IS_INTEL(sc))
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
-
- return;
}
#ifdef DEVICE_POLLING
@@ -2817,8 +2971,12 @@
static void
dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
- struct dc_softc *sc = ifp->if_softc;
+ struct dc_softc *sc = ifp->if_softc;
+ if (!(ifp->if_capenable & IFCAP_POLLING)) {
+ ether_poll_deregister(ifp);
+ cmd = POLL_DEREGISTER;
+ }
if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
/* Re-enable interrupts. */
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
@@ -2827,22 +2985,22 @@
sc->rxcycles = count;
dc_rxeof(sc);
dc_txeof(sc);
- if (ifp->if_snd.ifq_head != NULL && !(ifp->if_flags & IFF_OACTIVE))
+ if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE))
dc_start(ifp);
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
- u_int32_t status;
+ 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|
+ 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)
- return ;
+ return;
/* ack what we have */
CSR_WRITE_4(sc, DC_ISR, status);
- if (status & (DC_ISR_RX_WATDOGTIMEO|DC_ISR_RX_NOBUF) ) {
+ 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);
@@ -2865,32 +3023,31 @@
}
#endif /* DEVICE_POLLING */
-static void dc_intr(arg)
- void *arg;
+static void
+dc_intr(void *arg)
{
- struct dc_softc *sc;
- struct ifnet *ifp;
- u_int32_t status;
+ struct dc_softc *sc;
+ struct ifnet *ifp;
+ u_int32_t status;
sc = arg;
- if (sc->suspended) {
+ if (sc->suspended)
return;
- }
- ifp = &sc->arpcom.ac_if;
+ if ((CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0)
+ return;
+ ifp = &sc->arpcom.ac_if;
#ifdef DEVICE_POLLING
if (ifp->if_flags & IFF_POLLING)
return;
- if (ether_poll_register(dc_poll, ifp)) { /* ok, disable interrupts */
+ if ((ifp->if_capenable & IFCAP_POLLING) &&
+ ether_poll_register(dc_poll, ifp)) { /* ok, disable interrupts */
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
return;
}
-#endif /* DEVICE_POLLING */
-
- if ( (CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0)
- return ;
+#endif
/* Suppress unwanted interrupts */
if (!(ifp->if_flags & IFF_UP)) {
@@ -2902,7 +3059,8 @@
/* Disable interrupts. */
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
- while((status = CSR_READ_4(sc, DC_ISR)) & DC_INTRS) {
+ while (((status = CSR_READ_4(sc, DC_ISR)) & DC_INTRS)
+ && status != 0xFFFFFFFF) {
CSR_WRITE_4(sc, DC_ISR, status);
@@ -2911,12 +3069,12 @@
curpkts = ifp->if_ipackets;
dc_rxeof(sc);
if (curpkts == ifp->if_ipackets) {
- while(dc_rx_resync(sc))
+ while (dc_rx_resync(sc))
dc_rxeof(sc);
}
}
- if (status & (DC_ISR_TX_OK|DC_ISR_TX_NOBUF))
+ if (status & (DC_ISR_TX_OK | DC_ISR_TX_NOBUF))
dc_txeof(sc);
if (status & DC_ISR_TX_IDLE) {
@@ -2936,7 +3094,7 @@
curpkts = ifp->if_ipackets;
dc_rxeof(sc);
if (curpkts == ifp->if_ipackets) {
- while(dc_rx_resync(sc))
+ while (dc_rx_resync(sc))
dc_rxeof(sc);
}
}
@@ -2950,103 +3108,116 @@
/* Re-enable interrupts. */
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
- if (ifp->if_snd.ifq_head != NULL)
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start(ifp);
-
- return;
}
-/*
- * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
- * pointers to the fragment pointers.
- */
-static int dc_encap(sc, m_head, txidx)
- struct dc_softc *sc;
- struct mbuf *m_head;
- u_int32_t *txidx;
-{
- struct dc_desc *f = NULL;
- struct mbuf *m;
- int frag, cur, cnt = 0;
+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;
- /*
- * 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.
- */
- m = m_head;
- cur = frag = *txidx;
+ sc = arg;
+ if (error) {
+ sc->dc_cdata.dc_tx_err = error;
+ return;
+ }
- for (m = m_head; m != NULL; m = m->m_next) {
- if (m->m_len != 0) {
- if (sc->dc_flags & DC_TX_ADMTEK_WAR) {
- if (*txidx != sc->dc_cdata.dc_tx_prod &&
- frag == (DC_TX_LIST_CNT - 1))
- return(ENOBUFS);
- }
- if ((DC_TX_LIST_CNT -
- (sc->dc_cdata.dc_tx_cnt + cnt)) < 5)
- return(ENOBUFS);
-
- f = &sc->dc_ldata->dc_tx_list[frag];
- f->dc_ctl = DC_TXCTL_TLINK | m->m_len;
- if (cnt == 0) {
- f->dc_status = 0;
- f->dc_ctl |= DC_TXCTL_FIRSTFRAG;
- } else
- f->dc_status = DC_TXSTAT_OWN;
- f->dc_data = vtophys(mtod(m, vm_offset_t));
- cur = frag;
- DC_INC(frag, DC_TX_LIST_CNT);
- cnt++;
+ 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;
}
- }
- if (m != NULL)
- return(ENOBUFS);
+ 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_cnt += cnt;
- sc->dc_cdata.dc_tx_chain[cur] = m_head;
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_LASTFRAG;
+ 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[*txidx].dc_ctl |= DC_TXCTL_FINT;
+ 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 |= DC_TXCTL_FINT;
+ 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 |= DC_TXCTL_FINT;
- sc->dc_ldata->dc_tx_list[*txidx].dc_status = DC_TXSTAT_OWN;
- *txidx = frag;
-
- return(0);
+ 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);
}
/*
- * Coalesce an mbuf chain into a single mbuf cluster buffer.
- * Needed for some really badly behaved chips that just can't
- * do scatter/gather correctly.
- */
-static int dc_coal(sc, m_head)
- struct dc_softc *sc;
- struct mbuf **m_head;
-{
- struct mbuf *m_new, *m;
-
- m = *m_head;
- MGETHDR(m_new, MB_DONTWAIT, MT_DATA);
- if (m_new == NULL)
+ * 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);
- if (m->m_pkthdr.len > MHLEN) {
- MCLGET(m_new, MB_DONTWAIT);
- if (!(m_new->m_flags & M_EXT)) {
- m_freem(m_new);
+
+ /*
+ * 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, MB_DONTWAIT);
+ if (m == NULL)
return(ENOBUFS);
- }
+ *m_head = m;
}
- m_copydata(m, 0, m->m_pkthdr.len, mtod(m_new, caddr_t));
- m_new->m_pkthdr.len = m_new->m_len = m->m_pkthdr.len;
- m_freem(m);
- *m_head = m_new;
+ /*
+ * 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);
}
@@ -3057,12 +3228,13 @@
* physical addresses.
*/
-static void dc_start(ifp)
- struct ifnet *ifp;
+static void
+dc_start(struct ifnet *ifp)
{
- struct dc_softc *sc;
- struct mbuf *m_head = NULL;
- int idx;
+ struct dc_softc *sc;
+ struct mbuf *m_head = NULL, *m;
+ unsigned int queued = 0;
+ int idx;
sc = ifp->if_softc;
@@ -3072,29 +3244,34 @@
if (ifp->if_flags & IFF_OACTIVE)
return;
- idx = sc->dc_cdata.dc_tx_prod;
+ idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
- while(sc->dc_cdata.dc_tx_chain[idx] == NULL) {
- IF_DEQUEUE(&ifp->if_snd, m_head);
+ 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) {
- /* only coalesce if have >1 mbufs */
- if (dc_coal(sc, &m_head)) {
- IF_PREPEND(&ifp->if_snd, m_head);
+ (m_head->m_next != NULL ||
+ sc->dc_flags & DC_TX_ALIGN)) {
+ m = m_defrag(m_head, MB_DONTWAIT);
+ if (m == NULL) {
+ IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
ifp->if_flags |= IFF_OACTIVE;
break;
+ } else {
+ m_head = m;
}
}
- if (dc_encap(sc, m_head, &idx)) {
- IF_PREPEND(&ifp->if_snd, m_head);
+ if (dc_encap(sc, &m_head)) {
+ IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
ifp->if_flags |= IFF_OACTIVE;
break;
}
+ idx = sc->dc_cdata.dc_tx_prod;
+ queued++;
/*
* If there's a BPF listener, bounce a copy of this frame
* to him.
@@ -3107,26 +3284,25 @@
}
}
- /* Transmit */
- sc->dc_cdata.dc_tx_prod = idx;
- 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;
+ if (queued > 0) {
+ /* Transmit */
+ if (!(sc->dc_flags & DC_TX_POLL))
+ CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
- return;
+ /*
+ * Set a timeout in case the chip goes out to lunch.
+ */
+ ifp->if_timer = 5;
+ }
}
-static void dc_init(xsc)
- void *xsc;
+static void
+dc_init(void *xsc)
{
- struct dc_softc *sc = xsc;
- struct ifnet *ifp = &sc->arpcom.ac_if;
- struct mii_data *mii;
- int s;
+ struct dc_softc *sc = xsc;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct mii_data *mii;
+ int s;
s = splimp();
@@ -3144,7 +3320,7 @@
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);
+ CSR_WRITE_4(sc, DC_BUSCTL, DC_BUSCTL_MRME | DC_BUSCTL_MRLE);
/*
* Evenly share the bus between receive and transmit process.
*/
@@ -3163,10 +3339,10 @@
break;
case 16:
DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_16LONG);
- break;
+ break;
case 8:
DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_8LONG);
- break;
+ break;
case 0:
default:
DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_NONE);
@@ -3203,6 +3379,19 @@
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);
@@ -3211,20 +3400,20 @@
printf("dc%d: initialization failed: no "
"memory for rx buffers\n", sc->dc_unit);
dc_stop(sc);
- (void)splx(s);
+ splx(s);
return;
}
/*
- * Init tx descriptors.
+ * Init TX descriptors.
*/
dc_list_tx_init(sc);
/*
* Load the address of the RX list.
*/
- CSR_WRITE_4(sc, DC_RXADDR, vtophys(&sc->dc_ldata->dc_rx_list[0]));
- CSR_WRITE_4(sc, DC_TXADDR, vtophys(&sc->dc_ldata->dc_tx_list[0]));
+ CSR_WRITE_4(sc, DC_RXADDR, DC_RXDESC(sc, 0));
+ CSR_WRITE_4(sc, DC_TXADDR, DC_TXDESC(sc, 0));
/*
* Enable interrupts.
@@ -3252,7 +3441,7 @@
*/
if (sc->dc_flags & DC_TULIP_LEDS) {
CSR_WRITE_4(sc, DC_WATCHDOG,
- DC_WDOG_CTLWREN|DC_WDOG_LINK|DC_WDOG_ACTIVITY);
+ DC_WDOG_CTLWREN | DC_WDOG_LINK | DC_WDOG_ACTIVITY);
CSR_WRITE_4(sc, DC_WATCHDOG, 0);
}
@@ -3274,39 +3463,28 @@
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
- (void)splx(s);
-
/* Don't start the ticker if this is a homePNA link. */
if (IFM_SUBTYPE(mii->mii_media.ifm_media) == IFM_homePNA)
sc->dc_link = 1;
else {
if (sc->dc_flags & DC_21143_NWAY)
- callout_reset(&sc->dc_stat_timer, hz/10, dc_tick, sc);
+ callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
else
- callout_reset(&sc->dc_stat_timer, hz, dc_tick, sc);
+ callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
}
-#ifdef SRM_MEDIA
- if(sc->dc_srm_media) {
- struct ifreq ifr;
-
- ifr.ifr_media = sc->dc_srm_media;
- ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
- sc->dc_srm_media = 0;
- }
-#endif
- return;
+ splx(s);
}
/*
* Set media options.
*/
-static int dc_ifmedia_upd(ifp)
- struct ifnet *ifp;
+static int
+dc_ifmedia_upd(struct ifnet *ifp)
{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifmedia *ifm;
+ struct dc_softc *sc;
+ struct mii_data *mii;
+ struct ifmedia *ifm;
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
@@ -3325,13 +3503,12 @@
/*
* Report current media status.
*/
-static void dc_ifmedia_sts(ifp, ifmr)
- struct ifnet *ifp;
- struct ifmediareq *ifmr;
-{
- struct dc_softc *sc;
- struct mii_data *mii;
- struct ifmedia *ifm;
+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);
@@ -3346,33 +3523,24 @@
}
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
-
- return;
}
-static int dc_ioctl(ifp, command, data, cr)
- struct ifnet *ifp;
- u_long command;
- caddr_t data;
- struct ucred *cr;
-{
- struct dc_softc *sc = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *) data;
- struct mii_data *mii;
- int s, error = 0;
+static int
+dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
+{
+ struct dc_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct mii_data *mii;
+ int error = 0, s;
s = splimp();
- switch(command) {
- case SIOCSIFADDR:
- case SIOCGIFADDR:
- case SIOCSIFMTU:
- error = ether_ioctl(ifp, command, data);
- break;
+ switch (command) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) &
(IFF_PROMISC | IFF_ALLMULTI);
+
if (ifp->if_flags & IFF_RUNNING) {
if (need_setfilt)
dc_setfilt(sc);
@@ -3396,28 +3564,31 @@
case SIOCSIFMEDIA:
mii = device_get_softc(sc->dc_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
-#ifdef SRM_MEDIA
- if (sc->dc_srm_media)
- sc->dc_srm_media = 0;
-#endif
+ break;
+ case SIOCSIFCAP:
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
break;
default:
- error = EINVAL;
+ error = ether_ioctl(ifp, command, data);
break;
}
- (void)splx(s);
+ splx(s);
return(error);
}
-static void dc_watchdog(ifp)
- struct ifnet *ifp;
+static void
+dc_watchdog(struct ifnet *ifp)
- struct dc_softc *sc;
+ struct dc_softc *sc;
+ int s;
sc = ifp->if_softc;
+ s = splimp();
+
ifp->if_oerrors++;
printf("dc%d: watchdog timeout\n", sc->dc_unit);
@@ -3425,33 +3596,38 @@
dc_reset(sc);
dc_init(sc);
- if (ifp->if_snd.ifq_head != NULL)
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start(ifp);
- return;
+ splx(s);
}
/*
* Stop the adapter and free any mbufs allocated to the
* RX and TX lists.
*/
-static void dc_stop(sc)
- struct dc_softc *sc;
+static void
+dc_stop(struct dc_softc *sc)
{
- int i;
- struct ifnet *ifp;
+ struct ifnet *ifp;
+ struct dc_list_data *ld;
+ struct dc_chain_data *cd;
+ int i;
+ u_int32_t ctl;
ifp = &sc->arpcom.ac_if;
ifp->if_timer = 0;
+ ld = sc->dc_ldata;
+ cd = &sc->dc_cdata;
- callout_stop(&sc->dc_stat_timer);
+ callout_stop(&sc->dc_stat_ch);
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
#ifdef DEVICE_POLLING
ether_poll_deregister(ifp);
#endif
- DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON|DC_NETCFG_TX_ON));
+ 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);
@@ -3461,51 +3637,30 @@
* Free data in the RX lists.
*/
for (i = 0; i < DC_RX_LIST_CNT; i++) {
- if (sc->dc_cdata.dc_rx_chain[i] != NULL) {
- m_freem(sc->dc_cdata.dc_rx_chain[i]);
- sc->dc_cdata.dc_rx_chain[i] = NULL;
+ if (cd->dc_rx_chain[i] != NULL) {
+ m_freem(cd->dc_rx_chain[i]);
+ cd->dc_rx_chain[i] = NULL;
}
}
- bzero((char *)&sc->dc_ldata->dc_rx_list,
- sizeof(sc->dc_ldata->dc_rx_list));
+ 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 (sc->dc_cdata.dc_tx_chain[i] != NULL) {
- if ((sc->dc_ldata->dc_tx_list[i].dc_ctl &
- DC_TXCTL_SETUP) ||
- !(sc->dc_ldata->dc_tx_list[i].dc_ctl &
- DC_TXCTL_LASTFRAG)) {
- sc->dc_cdata.dc_tx_chain[i] = NULL;
+ 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;
}
- m_freem(sc->dc_cdata.dc_tx_chain[i]);
- sc->dc_cdata.dc_tx_chain[i] = NULL;
+ 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((char *)&sc->dc_ldata->dc_tx_list,
- sizeof(sc->dc_ldata->dc_tx_list));
-
- return;
-}
-
-/*
- * 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(dev)
- device_t dev;
-{
- struct dc_softc *sc;
-
- sc = device_get_softc(dev);
-
- dc_stop(sc);
-
- return;
+ bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list));
}
/*
@@ -3513,30 +3668,20 @@
* settings in case the BIOS doesn't restore them properly on
* resume.
*/
-static int dc_suspend(dev)
- device_t dev;
+static int
+dc_suspend(device_t dev)
{
- int i;
- int s;
- struct dc_softc *sc;
+ struct dc_softc *sc;
+ int s;
s = splimp();
sc = device_get_softc(dev);
-
dc_stop(sc);
-
- for (i = 0; i < 5; i++)
- sc->saved_maps[i] = pci_read_config(dev, PCIR_MAPS + i * 4, 4);
- sc->saved_biosaddr = pci_read_config(dev, PCIR_BIOS, 4);
- sc->saved_intline = pci_read_config(dev, PCIR_INTLINE, 1);
- sc->saved_cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1);
- sc->saved_lattimer = pci_read_config(dev, PCIR_LATTIMER, 1);
-
sc->suspended = 1;
splx(s);
- return (0);
+ return(0);
}
/*
@@ -3544,39 +3689,38 @@
* doesn't, re-enable busmastering, and restart the interface if
* appropriate.
*/
-static int dc_resume(dev)
- device_t dev;
+static int
+dc_resume(device_t dev)
{
- int i;
- int s;
- struct dc_softc *sc;
- struct ifnet *ifp;
+ struct dc_softc *sc;
+ struct ifnet *ifp;
+ int s;
s = splimp();
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
- dc_acpi(dev);
+ /* reinitialize interface if necessary */
+ if (ifp->if_flags & IFF_UP)
+ dc_init(sc);
- /* better way to do this? */
- for (i = 0; i < 5; i++)
- pci_write_config(dev, PCIR_MAPS + i * 4, sc->saved_maps[i], 4);
- pci_write_config(dev, PCIR_BIOS, sc->saved_biosaddr, 4);
- pci_write_config(dev, PCIR_INTLINE, sc->saved_intline, 1);
- pci_write_config(dev, PCIR_CACHELNSZ, sc->saved_cachelnsz, 1);
- pci_write_config(dev, PCIR_LATTIMER, sc->saved_lattimer, 1);
+ sc->suspended = 0;
- /* reenable busmastering */
- pci_enable_busmaster(dev);
- pci_enable_io(dev, DC_RES);
+ splx(s);
+ return(0);
+}
- /* reinitialize interface if necessary */
- if (ifp->if_flags & IFF_UP)
- dc_init(sc);
+/*
+ * 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->suspended = 0;
+ sc = device_get_softc(dev);
- splx(s);
- return (0);
+ dc_stop(sc);
}
Index: if_dcreg.h
===================================================================
RCS file: /home/joerg/wd/repository/dragonflybsd/src/sys/dev/netif/dc/if_dcreg.h,v
retrieving revision 1.3
diff -u -r1.3 if_dcreg.h
--- if_dcreg.h 14 Sep 2004 22:44:46 -0000 1.3
+++ if_dcreg.h 1 Feb 2005 19:50:20 -0000
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul at xxxxxxxxxxxxxxx>. All rights reserved.
*
@@ -29,8 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/if_dcreg.h,v 1.4.2.22 2003/06/07 16:55:35 mbr Exp $
- * $DragonFly: src/sys/dev/netif/dc/if_dcreg.h,v 1.3 2004/09/14 22:44:46 joerg Exp $
+ * $FreeBSD: src/sys/pci/if_dcreg.h,v 1.43 2005/01/07 02:29:18 imp Exp $
*/
/*
@@ -53,6 +52,7 @@
#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
@@ -76,7 +76,8 @@
#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_CONEXANT 0xC /* Conexant LANfinity RS7112 */
+#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 || \
@@ -94,6 +95,7 @@
#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 */
@@ -358,6 +360,25 @@
#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
@@ -443,7 +464,19 @@
#define DC_MIN_FRAMELEN 60
#define DC_RXLEN 1536
-#define DC_INC(x, y) (x) = (x + 1) % y
+#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];
@@ -453,11 +486,18 @@
struct dc_chain_data {
struct mbuf *dc_rx_chain[DC_RX_LIST_CNT];
struct mbuf *dc_tx_chain[DC_TX_LIST_CNT];
- u_int32_t dc_sbuf[DC_SFRAME_LEN/sizeof(u_int32_t)];
+ 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;
};
@@ -679,6 +719,14 @@
struct arpcom arpcom; /* 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;
@@ -700,20 +748,11 @@
struct dc_mediainfo *dc_mi;
struct dc_list_data *dc_ldata;
struct dc_chain_data dc_cdata;
- struct callout dc_stat_timer;
-#ifdef __alpha__
- int dc_srm_media;
-#endif
-#ifdef DEVICE_POLLING
+ struct callout dc_stat_ch;
+#ifdef DEVICE_POLLING
int rxcycles; /* ... when polling */
#endif
int suspended; /* 0 = normal 1 = suspended */
-
- u_int32_t saved_maps[5]; /* pci data */
- u_int32_t saved_biosaddr;
- u_int8_t saved_intline;
- u_int8_t saved_cachelnsz;
- u_int8_t saved_lattimer;
};
#define DC_TX_POLL 0x00000001
@@ -732,6 +771,7 @@
#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
@@ -839,7 +879,9 @@
*/
#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
@@ -880,6 +922,27 @@
#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
@@ -890,6 +953,42 @@
#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.
*/
@@ -1061,9 +1160,17 @@
struct dc_eblock_sia {
struct dc_eblock_hdr dc_sia_hdr;
u_int8_t dc_sia_code;
- 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];
+ 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
@@ -1108,8 +1215,3 @@
u_int8_t dc_reset_len;
/* u_int16_t dc_reset_dat[n]; */
};
-
-#ifdef __alpha__
-#undef vtophys
-#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va)
-#endif
More information about the Submit
mailing list