Subject: Re: ohare interrupt problem (Re: HEADS UP: merging the newlock2 branch)
To: None <port-macppc@NetBSD.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-macppc
Date: 02/11/2007 15:33:11
I wrote:
> NetBSD-3.1_RC4 (well, I have its bootable CD) kernel
> with the latest re(4) driver (with some modification to
> make it compile on netbsd-3)
Just FYI, here is a patch for NetBSD-3.1:
---
Index: arch/macppc/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/conf/GENERIC,v
retrieving revision 1.194.4.7
diff -u -r1.194.4.7 GENERIC
--- arch/macppc/conf/GENERIC 5 Nov 2005 00:39:47 -0000 1.194.4.7
+++ arch/macppc/conf/GENERIC 11 Feb 2007 03:41:55 -0000
@@ -292,6 +292,8 @@
nsphyter* at mii? phy ? # NS83843 PHYs
pnaphy* at mii? phy ? # generic HomePNA PHYs
qsphy* at mii? phy ? # Quality Semiconductor QS6612 PHYs
+rgephy* at mii? phy ? # Realtek 8169S/8110S internal PHYs
+rlphy* at mii? phy ? # Realtek 8139/8201L PHYs
sqphy* at mii? phy ? # Seeq 80220/80221/80223 PHYs
tlphy* at mii? phy ? # ThunderLAN PHYs
tqphy* at mii? phy ? # TDK Semiconductor PHYs
Index: arch/macppc/conf/INSTALL
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/conf/INSTALL,v
retrieving revision 1.87.4.3
diff -u -r1.87.4.3 INSTALL
--- arch/macppc/conf/INSTALL 18 Jun 2005 05:25:51 -0000 1.87.4.3
+++ arch/macppc/conf/INSTALL 11 Feb 2007 03:53:46 -0000
@@ -123,6 +123,8 @@
nsphy* at mii? phy ? # NS83840 PHYs
nsphyter* at mii? phy ? # NS83843 PHYs
qsphy* at mii? phy ? # Quality Semiconductor QS6612 PHYs
+rgephy* at mii? phy ? # Realtek 8169S/8110S internal PHYs
+rlphy* at mii? phy ? # Realtek 8139/8201L PHYs
sqphy* at mii? phy ? # Seeq 80220/80221/80223 PHYs
tqphy* at mii? phy ? # TDK Semiconductor PHYs
ukphy* at mii? phy ? # generic unknown PHYs
Index: dev/cardbus/if_re_cardbus.c
===================================================================
RCS file: /cvsroot/src/sys/dev/cardbus/if_re_cardbus.c,v
retrieving revision 1.5
diff -u -r1.5 if_re_cardbus.c
--- dev/cardbus/if_re_cardbus.c 27 Feb 2005 00:26:59 -0000 1.5
+++ dev/cardbus/if_re_cardbus.c 11 Feb 2007 03:42:00 -0000
@@ -294,7 +294,7 @@
PCI_CAP_PWRMGMT, &pmreg, 0)) {
command = cardbus_conf_read(cc, cf, csc->sc_tag,
pmreg + PCI_PMCSR);
- if (command & RTK_PSTATE_MASK) {
+ if (command & PCI_PMCSR_STATE_MASK) {
pcireg_t iobase, membase, irq;
/* Save important PCI config data. */
@@ -308,8 +308,8 @@
/* Reset the power state. */
aprint_normal("%s: chip is in D%d power mode "
"-- setting to D0\n", sc->sc_dev.dv_xname,
- command & RTK_PSTATE_MASK);
- command &= ~RTK_PSTATE_MASK;
+ command & PCI_PMCSR_STATE_MASK);
+ command &= ~PCI_PMCSR_STATE_MASK;
cardbus_conf_write(cc, cf, csc->sc_tag,
pmreg + PCI_PMCSR, command);
@@ -402,7 +402,7 @@
}
void
-re_cardbus_power(struct rtk_softc *sc, int why)
+re_cardbus_power(struct rtk_softc *sc, int why)
{
struct re_cardbus_softc *csc = (void *) sc;
Index: dev/cardbus/if_rtk_cardbus.c
===================================================================
RCS file: /cvsroot/src/sys/dev/cardbus/if_rtk_cardbus.c,v
retrieving revision 1.25
diff -u -r1.25 if_rtk_cardbus.c
--- dev/cardbus/if_rtk_cardbus.c 27 Feb 2005 00:26:59 -0000 1.25
+++ dev/cardbus/if_rtk_cardbus.c 11 Feb 2007 03:42:00 -0000
@@ -171,10 +171,8 @@
}
int
-rtk_cardbus_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+rtk_cardbus_match(struct device *parent, struct cfdata *match,
+ void *aux)
{
struct cardbus_attach_args *ca = aux;
@@ -186,9 +184,8 @@
void
-rtk_cardbus_attach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+rtk_cardbus_attach(struct device *parent, struct device *self,
+ void *aux)
{
struct rtk_cardbus_softc *csc = (struct rtk_cardbus_softc *)self;
struct rtk_softc *sc = &csc->sc_rtk;
@@ -266,9 +263,7 @@
}
int
-rtk_cardbus_detach(self, flags)
- struct device *self;
- int flags;
+rtk_cardbus_detach(struct device *self, int flags)
{
struct rtk_cardbus_softc *csc = (void *) self;
struct rtk_softc *sc = &csc->sc_rtk;
@@ -316,7 +311,7 @@
PCI_CAP_PWRMGMT, &pmreg, 0)) {
command = cardbus_conf_read(cc, cf, csc->sc_tag,
pmreg + PCI_PMCSR);
- if (command & RTK_PSTATE_MASK) {
+ if (command & PCI_PMCSR_STATE_MASK) {
pcireg_t iobase, membase, irq;
/* Save important PCI config data. */
@@ -330,8 +325,8 @@
/* Reset the power state. */
printf("%s: chip is in D%d power mode "
"-- setting to D0\n", sc->sc_dev.dv_xname,
- command & RTK_PSTATE_MASK);
- command &= ~RTK_PSTATE_MASK;
+ command & PCI_PMCSR_STATE_MASK);
+ command &= ~PCI_PMCSR_STATE_MASK;
cardbus_conf_write(cc, cf, csc->sc_tag,
pmreg + PCI_PMCSR, command);
Index: dev/ic/rtl8169.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/rtl8169.c,v
retrieving revision 1.14.2.5
diff -u -r1.14.2.5 rtl8169.c
--- dev/ic/rtl8169.c 31 May 2006 21:32:56 -0000 1.14.2.5
+++ dev/ic/rtl8169.c 11 Feb 2007 03:42:01 -0000
@@ -143,17 +143,12 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-#include <dev/pci/pcidevs.h>
-
#include <dev/ic/rtl81x9reg.h>
#include <dev/ic/rtl81x9var.h>
#include <dev/ic/rtl8169var.h>
-
-static int re_encap(struct rtk_softc *, struct mbuf *, int *);
+static inline void re_set_bufaddr(struct re_desc *, bus_addr_t);
static int re_newbuf(struct rtk_softc *, int, struct mbuf *);
static int re_rx_list_init(struct rtk_softc *);
@@ -184,11 +179,22 @@
static void re_reset(struct rtk_softc *);
+static inline void
+re_set_bufaddr(struct re_desc *d, bus_addr_t addr)
+{
+
+ d->re_bufaddr_lo = htole32((uint32_t)addr);
+ if (sizeof(bus_addr_t) == sizeof(uint64_t))
+ d->re_bufaddr_hi = htole32((uint64_t)addr >> 32);
+ else
+ d->re_bufaddr_hi = 0;
+}
+
static int
re_gmii_readreg(struct device *self, int phy, int reg)
{
struct rtk_softc *sc = (void *)self;
- u_int32_t rval;
+ uint32_t rval;
int i;
if (phy != 7)
@@ -223,7 +229,7 @@
re_gmii_writereg(struct device *dev, int phy, int reg, int data)
{
struct rtk_softc *sc = (void *)dev;
- u_int32_t rval;
+ uint32_t rval;
int i;
CSR_WRITE_4(sc, RTK_PHYAR, (reg << 16) |
@@ -240,18 +246,15 @@
if (i == RTK_TIMEOUT) {
aprint_error("%s: PHY write reg %x <- %x failed\n",
sc->sc_dev.dv_xname, reg, data);
- return;
}
-
- return;
}
static int
re_miibus_readreg(struct device *dev, int phy, int reg)
{
struct rtk_softc *sc = (void *)dev;
- u_int16_t rval = 0;
- u_int16_t re8139_reg = 0;
+ uint16_t rval = 0;
+ uint16_t re8139_reg = 0;
int s;
s = splnet();
@@ -303,6 +306,10 @@
return 0;
}
rval = CSR_READ_2(sc, re8139_reg);
+ if (sc->rtk_type == RTK_8139CPLUS && re8139_reg == RTK_BMCR) {
+ /* 8139C+ has different bit layout. */
+ rval &= ~(BMCR_LOOP | BMCR_ISO);
+ }
splx(s);
return rval;
}
@@ -311,7 +318,7 @@
re_miibus_writereg(struct device *dev, int phy, int reg, int data)
{
struct rtk_softc *sc = (void *)dev;
- u_int16_t re8139_reg = 0;
+ uint16_t re8139_reg = 0;
int s;
s = splnet();
@@ -330,6 +337,10 @@
switch (reg) {
case MII_BMCR:
re8139_reg = RTK_BMCR;
+ if (sc->rtk_type == RTK_8139CPLUS) {
+ /* 8139C+ has different bit layout. */
+ data &= ~(BMCR_LOOP | BMCR_ISO);
+ }
break;
case MII_BMSR:
re8139_reg = RTK_BMSR;
@@ -368,13 +379,13 @@
static void
re_reset(struct rtk_softc *sc)
{
- register int i;
+ int i;
CSR_WRITE_1(sc, RTK_COMMAND, RTK_CMD_RESET);
for (i = 0; i < RTK_TIMEOUT; i++) {
DELAY(10);
- if (!(CSR_READ_1(sc, RTK_COMMAND) & RTK_CMD_RESET))
+ if ((CSR_READ_1(sc, RTK_COMMAND) & RTK_CMD_RESET) == 0)
break;
}
if (i == RTK_TIMEOUT)
@@ -386,7 +397,7 @@
* MCFG_METHOD_2, which corresponds to sc->sc_rev == 2.
*/
if (1) /* XXX check softc flag for 8169s version */
- CSR_WRITE_1(sc, 0x82, 1);
+ CSR_WRITE_1(sc, RTK_LDPS, 1);
return;
}
@@ -417,13 +428,14 @@
struct ifnet *ifp = &sc->ethercom.ec_if;
struct mbuf *m0;
struct ether_header *eh;
- struct rtk_desc *cur_rx;
+ struct re_rxsoft *rxs;
+ struct re_desc *cur_rx;
bus_dmamap_t dmamap;
- u_int16_t status;
- u_int32_t rxstat;
+ uint16_t status;
+ uint32_t rxstat;
int total_len, i, s, error = 0;
- u_int8_t dst[] = { 0x00, 'h', 'e', 'l', 'l', 'o' };
- u_int8_t src[] = { 0x00, 'w', 'o', 'r', 'l', 'd' };
+ static const uint8_t dst[] = { 0x00, 'h', 'e', 'l', 'l', 'o' };
+ static const uint8_t src[] = { 0x00, 'w', 'o', 'r', 'l', 'd' };
/* Allocate a single mbuf */
@@ -441,7 +453,7 @@
*/
ifp->if_flags |= IFF_PROMISC;
- sc->rtk_testmode = 1;
+ sc->re_testmode = 1;
re_init(ifp);
re_stop(ifp, 0);
DELAY(100000);
@@ -450,8 +462,8 @@
/* Put some data in the mbuf */
eh = mtod(m0, struct ether_header *);
- bcopy((char *)&dst, eh->ether_dhost, ETHER_ADDR_LEN);
- bcopy((char *)&src, eh->ether_shost, ETHER_ADDR_LEN);
+ memcpy(eh->ether_dhost, (char *)&dst, ETHER_ADDR_LEN);
+ memcpy(eh->ether_shost, (char *)&src, ETHER_ADDR_LEN);
eh->ether_type = htons(ETHERTYPE_IP);
m0->m_pkthdr.len = m0->m_len = ETHER_MIN_LEN - ETHER_CRC_LEN;
@@ -488,22 +500,20 @@
* entry in the RX DMA ring. Grab it from there.
*/
- dmamap = sc->rtk_ldata.rtk_rx_list_map;
- bus_dmamap_sync(sc->sc_dmat,
- dmamap, 0, dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
- dmamap = sc->rtk_ldata.rtk_rx_dmamap[0];
+ rxs = &sc->re_ldata.re_rxsoft[0];
+ dmamap = rxs->rxs_dmamap;
bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_dmamap[0]);
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmat, dmamap);
- m0 = sc->rtk_ldata.rtk_rx_mbuf[0];
- sc->rtk_ldata.rtk_rx_mbuf[0] = NULL;
+ m0 = rxs->rxs_mbuf;
+ rxs->rxs_mbuf = NULL;
eh = mtod(m0, struct ether_header *);
- cur_rx = &sc->rtk_ldata.rtk_rx_list[0];
- total_len = RTK_RXBYTES(cur_rx);
- rxstat = le32toh(cur_rx->rtk_cmdstat);
+ RE_RXDESCSYNC(sc, 0, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ cur_rx = &sc->re_ldata.re_rx_list[0];
+ rxstat = le32toh(cur_rx->re_cmdstat);
+ total_len = rxstat & sc->re_rxlenmask;
if (total_len != ETHER_MIN_LEN) {
aprint_error("%s: diagnostic failed, received short packet\n",
@@ -514,8 +524,8 @@
/* Test that the received packet data matches what we sent. */
- if (bcmp((char *)&eh->ether_dhost, (char *)&dst, ETHER_ADDR_LEN) ||
- bcmp((char *)&eh->ether_shost, (char *)&src, ETHER_ADDR_LEN) ||
+ if (memcmp((char *)&eh->ether_dhost, (char *)&dst, ETHER_ADDR_LEN) ||
+ memcmp((char *)&eh->ether_shost, (char *)&src, ETHER_ADDR_LEN) ||
ntohs(eh->ether_type) != ETHERTYPE_IP) {
aprint_error("%s: WARNING, DMA FAILURE!\n",
sc->sc_dev.dv_xname);
@@ -536,10 +546,10 @@
error = EIO;
}
-done:
+ done:
/* Turn interface off, release resources */
- sc->rtk_testmode = 0;
+ sc->re_testmode = 0;
ifp->if_flags &= ~IFF_PROMISC;
re_stop(ifp, 0);
if (m0 != NULL)
@@ -557,108 +567,99 @@
re_attach(struct rtk_softc *sc)
{
u_char eaddr[ETHER_ADDR_LEN];
- u_int16_t val;
+ uint16_t val;
struct ifnet *ifp;
int error = 0, i, addr_len;
-
- /* XXX JRS: bus-attach-independent code begins approximately here */
-
/* Reset the adapter. */
re_reset(sc);
+ if (rtk_read_eeprom(sc, RTK_EE_ID, RTK_EEADDR_LEN1) == 0x8129)
+ addr_len = RTK_EEADDR_LEN1;
+ else
+ addr_len = RTK_EEADDR_LEN0;
+
+ /*
+ * Get station address from the EEPROM.
+ */
+ for (i = 0; i < 3; i++) {
+ val = rtk_read_eeprom(sc, RTK_EE_EADDR0 + i, addr_len);
+ eaddr[(i * 2) + 0] = val & 0xff;
+ eaddr[(i * 2) + 1] = val >> 8;
+ }
+
if (sc->rtk_type == RTK_8169) {
uint32_t hwrev;
/* Revision of 8169/8169S/8110s in bits 30..26, 23 */
- hwrev = CSR_READ_4(sc, RTK_TXCFG) & 0x7c800000;
- if (hwrev == (0x1 << 28)) {
+ hwrev = CSR_READ_4(sc, RTK_TXCFG) & RTK_TXCFG_HWREV;
+ /* These rev numbers are taken from Realtek's driver */
+ if (hwrev == 0x38800000 /* XXX */) {
+ sc->sc_rev = 15;
+ } else if (hwrev == RTK_HWREV_8100E) {
+ sc->sc_rev = 14;
+ } else if (hwrev == RTK_HWREV_8101E) {
+ sc->sc_rev = 13;
+ } else if (hwrev == RTK_HWREV_8168_SPIN2) {
+ sc->sc_rev = 12;
+ } else if (hwrev == RTK_HWREV_8168_SPIN1) {
+ sc->sc_rev = 11;
+ } else if (hwrev == RTK_HWREV_8169_8110SC) {
+ sc->sc_rev = 5;
+ } else if (hwrev == RTK_HWREV_8169_8110SB) {
sc->sc_rev = 4;
- } else if (hwrev == (0x1 << 26)) {
+ } else if (hwrev == RTK_HWREV_8169S) {
sc->sc_rev = 3;
- } else if (hwrev == (0x1 << 23)) {
+ } else if (hwrev == RTK_HWREV_8110S) {
sc->sc_rev = 2;
- } else
+ } else /* RTK_HWREV_8169 */
sc->sc_rev = 1;
/* Set RX length mask */
-
- sc->rtk_rxlenmask = RTK_RDESC_STAT_GFRAGLEN;
-
- /* Force station address autoload from the EEPROM */
-
- CSR_WRITE_1(sc, RTK_EECMD, RTK_EEMODE_AUTOLOAD);
- for (i = 0; i < RTK_TIMEOUT; i++) {
- if (!(CSR_READ_1(sc, RTK_EECMD) & RTK_EEMODE_AUTOLOAD))
- break;
- DELAY(100);
- }
- if (i == RTK_TIMEOUT)
- aprint_error("%s: eeprom autoload timed out\n",
- sc->sc_dev.dv_xname);
-
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- eaddr[i] = CSR_READ_1(sc, RTK_IDR0 + i);
-
- sc->rtk_ldata.rtk_tx_desc_cnt = RTK_TX_DESC_CNT_8169;
+ sc->re_rxlenmask = RE_RDESC_STAT_GFRAGLEN;
+ sc->re_ldata.re_tx_desc_cnt = RE_TX_DESC_CNT_8169;
} else {
-
/* Set RX length mask */
-
- sc->rtk_rxlenmask = RTK_RDESC_STAT_FRAGLEN;
-
- if (rtk_read_eeprom(sc, RTK_EE_ID, RTK_EEADDR_LEN1) == 0x8129)
- addr_len = RTK_EEADDR_LEN1;
- else
- addr_len = RTK_EEADDR_LEN0;
-
- /*
- * Get station address from the EEPROM.
- */
- for (i = 0; i < 3; i++) {
- val = rtk_read_eeprom(sc, RTK_EE_EADDR0 + i, addr_len);
- eaddr[(i * 2) + 0] = val & 0xff;
- eaddr[(i * 2) + 1] = val >> 8;
- }
-
- sc->rtk_ldata.rtk_tx_desc_cnt = RTK_TX_DESC_CNT_8139;
+ sc->re_rxlenmask = RE_RDESC_STAT_FRAGLEN;
+ sc->re_ldata.re_tx_desc_cnt = RE_TX_DESC_CNT_8139;
}
aprint_normal("%s: Ethernet address %s\n",
sc->sc_dev.dv_xname, ether_sprintf(eaddr));
- if (sc->rtk_ldata.rtk_tx_desc_cnt >
- PAGE_SIZE / sizeof(struct rtk_desc)) {
- sc->rtk_ldata.rtk_tx_desc_cnt =
- PAGE_SIZE / sizeof(struct rtk_desc);
+ if (sc->re_ldata.re_tx_desc_cnt >
+ PAGE_SIZE / sizeof(struct re_desc)) {
+ sc->re_ldata.re_tx_desc_cnt =
+ PAGE_SIZE / sizeof(struct re_desc);
}
aprint_verbose("%s: using %d tx descriptors\n",
- sc->sc_dev.dv_xname, sc->rtk_ldata.rtk_tx_desc_cnt);
+ sc->sc_dev.dv_xname, sc->re_ldata.re_tx_desc_cnt);
+ KASSERT(RE_NEXT_TX_DESC(sc, RE_TX_DESC_CNT(sc) - 1) == 0);
/* Allocate DMA'able memory for the TX ring */
- if ((error = bus_dmamem_alloc(sc->sc_dmat, RTK_TX_LIST_SZ(sc),
- RTK_ETHER_ALIGN, 0, &sc->rtk_ldata.rtk_tx_listseg,
- 1, &sc->rtk_ldata.rtk_tx_listnseg, BUS_DMA_NOWAIT)) != 0) {
+ if ((error = bus_dmamem_alloc(sc->sc_dmat, RE_TX_LIST_SZ(sc),
+ RE_RING_ALIGN, 0, &sc->re_ldata.re_tx_listseg, 1,
+ &sc->re_ldata.re_tx_listnseg, BUS_DMA_NOWAIT)) != 0) {
aprint_error("%s: can't allocate tx listseg, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_0;
}
/* Load the map for the TX ring. */
- if ((error = bus_dmamem_map(sc->sc_dmat, &sc->rtk_ldata.rtk_tx_listseg,
- sc->rtk_ldata.rtk_tx_listnseg, RTK_TX_LIST_SZ(sc),
- (caddr_t *)&sc->rtk_ldata.rtk_tx_list,
- BUS_DMA_NOWAIT)) != 0) {
+ if ((error = bus_dmamem_map(sc->sc_dmat, &sc->re_ldata.re_tx_listseg,
+ sc->re_ldata.re_tx_listnseg, RE_TX_LIST_SZ(sc),
+ (caddr_t *)&sc->re_ldata.re_tx_list,
+ BUS_DMA_COHERENT | BUS_DMA_NOWAIT)) != 0) {
aprint_error("%s: can't map tx list, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_1;
}
- memset(sc->rtk_ldata.rtk_tx_list, 0, RTK_TX_LIST_SZ(sc));
+ memset(sc->re_ldata.re_tx_list, 0, RE_TX_LIST_SZ(sc));
- if ((error = bus_dmamap_create(sc->sc_dmat, RTK_TX_LIST_SZ(sc), 1,
- RTK_TX_LIST_SZ(sc), 0, BUS_DMA_ALLOCNOW,
- &sc->rtk_ldata.rtk_tx_list_map)) != 0) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, RE_TX_LIST_SZ(sc), 1,
+ RE_TX_LIST_SZ(sc), 0, 0,
+ &sc->re_ldata.re_tx_list_map)) != 0) {
aprint_error("%s: can't create tx list map, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_2;
@@ -666,20 +667,19 @@
if ((error = bus_dmamap_load(sc->sc_dmat,
- sc->rtk_ldata.rtk_tx_list_map, sc->rtk_ldata.rtk_tx_list,
- RTK_TX_LIST_SZ(sc), NULL, BUS_DMA_NOWAIT)) != 0) {
+ sc->re_ldata.re_tx_list_map, sc->re_ldata.re_tx_list,
+ RE_TX_LIST_SZ(sc), NULL, BUS_DMA_NOWAIT)) != 0) {
aprint_error("%s: can't load tx list, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_3;
}
/* Create DMA maps for TX buffers */
- for (i = 0; i < RTK_TX_QLEN; i++) {
+ for (i = 0; i < RE_TX_QLEN; i++) {
error = bus_dmamap_create(sc->sc_dmat,
round_page(IP_MAXPACKET),
- RTK_TX_DESC_CNT(sc) - 4, RTK_TDESC_CMD_FRAGLEN,
- 0, BUS_DMA_ALLOCNOW,
- &sc->rtk_ldata.rtk_txq[i].txq_dmamap);
+ RE_TX_DESC_CNT(sc) - RE_NTXDESC_RSVD, RE_TDESC_CMD_FRAGLEN,
+ 0, 0, &sc->re_ldata.re_txq[i].txq_dmamap);
if (error) {
aprint_error("%s: can't create DMA map for TX\n",
sc->sc_dev.dv_xname);
@@ -688,45 +688,46 @@
}
/* Allocate DMA'able memory for the RX ring */
- if ((error = bus_dmamem_alloc(sc->sc_dmat, RTK_RX_LIST_SZ,
- RTK_RING_ALIGN, 0, &sc->rtk_ldata.rtk_rx_listseg, 1,
- &sc->rtk_ldata.rtk_rx_listnseg, BUS_DMA_NOWAIT)) != 0) {
+ /* XXX see also a comment about RE_RX_DMAMEM_SZ in rtl81x9var.h */
+ if ((error = bus_dmamem_alloc(sc->sc_dmat,
+ RE_RX_DMAMEM_SZ, RE_RING_ALIGN, 0, &sc->re_ldata.re_rx_listseg, 1,
+ &sc->re_ldata.re_rx_listnseg, BUS_DMA_NOWAIT)) != 0) {
aprint_error("%s: can't allocate rx listseg, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_4;
}
/* Load the map for the RX ring. */
- if ((error = bus_dmamem_map(sc->sc_dmat, &sc->rtk_ldata.rtk_rx_listseg,
- sc->rtk_ldata.rtk_rx_listnseg, RTK_RX_LIST_SZ,
- (caddr_t *)&sc->rtk_ldata.rtk_rx_list,
- BUS_DMA_NOWAIT)) != 0) {
+ if ((error = bus_dmamem_map(sc->sc_dmat, &sc->re_ldata.re_rx_listseg,
+ sc->re_ldata.re_rx_listnseg, RE_RX_DMAMEM_SZ,
+ (caddr_t *)&sc->re_ldata.re_rx_list,
+ BUS_DMA_COHERENT | BUS_DMA_NOWAIT)) != 0) {
aprint_error("%s: can't map rx list, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_5;
}
- memset(sc->rtk_ldata.rtk_rx_list, 0, RTK_RX_LIST_SZ);
+ memset(sc->re_ldata.re_rx_list, 0, RE_RX_DMAMEM_SZ);
- if ((error = bus_dmamap_create(sc->sc_dmat, RTK_RX_LIST_SZ, 1,
- RTK_RX_LIST_SZ, 0, BUS_DMA_ALLOCNOW,
- &sc->rtk_ldata.rtk_rx_list_map)) != 0) {
+ if ((error = bus_dmamap_create(sc->sc_dmat,
+ RE_RX_DMAMEM_SZ, 1, RE_RX_DMAMEM_SZ, 0, 0,
+ &sc->re_ldata.re_rx_list_map)) != 0) {
aprint_error("%s: can't create rx list map, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_6;
}
if ((error = bus_dmamap_load(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_list_map, sc->rtk_ldata.rtk_rx_list,
- RTK_RX_LIST_SZ, NULL, BUS_DMA_NOWAIT)) != 0) {
+ sc->re_ldata.re_rx_list_map, sc->re_ldata.re_rx_list,
+ RE_RX_DMAMEM_SZ, NULL, BUS_DMA_NOWAIT)) != 0) {
aprint_error("%s: can't load rx list, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_7;
}
/* Create DMA maps for RX buffers */
- for (i = 0; i < RTK_RX_DESC_CNT; i++) {
+ for (i = 0; i < RE_RX_DESC_CNT; i++) {
error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
- 0, BUS_DMA_ALLOCNOW, &sc->rtk_ldata.rtk_rx_dmamap[i]);
+ 0, 0, &sc->re_ldata.re_rxsoft[i].rxs_dmamap);
if (error) {
aprint_error("%s: can't create DMA map for RX\n",
sc->sc_dev.dv_xname);
@@ -745,20 +746,20 @@
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = re_ioctl;
- sc->ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
-
- /*
- * This is a way to disable hw VLAN tagging by default
- * (RE_VLAN is undefined), as it is problematic. PR 32643
- */
-
-#ifdef RE_VLAN
- sc->ethercom.ec_capabilities |= ETHERCAP_VLAN_HWTAGGING;
-#endif
+ sc->ethercom.ec_capabilities |=
+ ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING;
ifp->if_start = re_start;
ifp->if_stop = re_stop;
+
+ /*
+ * IFCAP_CSUM_IPv4_Tx on re(4) is broken for small packets,
+ * so we have a workaround to handle the bug by padding
+ * such packets manually.
+ */
ifp->if_capabilities |=
- IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4 |
+ IFCAP_CSUM_IPv4 |
+ IFCAP_CSUM_TCPv4 |
+ IFCAP_CSUM_UDPv4 |
IFCAP_TSOv4;
ifp->if_watchdog = re_watchdog;
ifp->if_init = re_init;
@@ -766,7 +767,7 @@
ifp->if_baudrate = 1000000000;
else
ifp->if_baudrate = 100000000;
- ifp->if_snd.ifq_maxlen = RTK_IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = RE_IFQ_MAXLEN;
ifp->if_capenable = ifp->if_capabilities;
IFQ_SET_READY(&ifp->if_snd);
@@ -809,42 +810,42 @@
return;
-fail_8:
+ fail_8:
/* Destroy DMA maps for RX buffers. */
- for (i = 0; i < RTK_RX_DESC_CNT; i++)
- if (sc->rtk_ldata.rtk_rx_dmamap[i] != NULL)
+ for (i = 0; i < RE_RX_DESC_CNT; i++)
+ if (sc->re_ldata.re_rxsoft[i].rxs_dmamap != NULL)
bus_dmamap_destroy(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_dmamap[i]);
+ sc->re_ldata.re_rxsoft[i].rxs_dmamap);
/* Free DMA'able memory for the RX ring. */
- bus_dmamap_unload(sc->sc_dmat, sc->rtk_ldata.rtk_rx_list_map);
-fail_7:
- bus_dmamap_destroy(sc->sc_dmat, sc->rtk_ldata.rtk_rx_list_map);
-fail_6:
+ bus_dmamap_unload(sc->sc_dmat, sc->re_ldata.re_rx_list_map);
+ fail_7:
+ bus_dmamap_destroy(sc->sc_dmat, sc->re_ldata.re_rx_list_map);
+ fail_6:
bus_dmamem_unmap(sc->sc_dmat,
- (caddr_t)sc->rtk_ldata.rtk_rx_list, RTK_RX_LIST_SZ);
-fail_5:
+ (caddr_t)sc->re_ldata.re_rx_list, RE_RX_DMAMEM_SZ);
+ fail_5:
bus_dmamem_free(sc->sc_dmat,
- &sc->rtk_ldata.rtk_rx_listseg, sc->rtk_ldata.rtk_rx_listnseg);
+ &sc->re_ldata.re_rx_listseg, sc->re_ldata.re_rx_listnseg);
-fail_4:
+ fail_4:
/* Destroy DMA maps for TX buffers. */
- for (i = 0; i < RTK_TX_QLEN; i++)
- if (sc->rtk_ldata.rtk_txq[i].txq_dmamap != NULL)
+ for (i = 0; i < RE_TX_QLEN; i++)
+ if (sc->re_ldata.re_txq[i].txq_dmamap != NULL)
bus_dmamap_destroy(sc->sc_dmat,
- sc->rtk_ldata.rtk_txq[i].txq_dmamap);
+ sc->re_ldata.re_txq[i].txq_dmamap);
/* Free DMA'able memory for the TX ring. */
- bus_dmamap_unload(sc->sc_dmat, sc->rtk_ldata.rtk_tx_list_map);
-fail_3:
- bus_dmamap_destroy(sc->sc_dmat, sc->rtk_ldata.rtk_tx_list_map);
-fail_2:
+ bus_dmamap_unload(sc->sc_dmat, sc->re_ldata.re_tx_list_map);
+ fail_3:
+ bus_dmamap_destroy(sc->sc_dmat, sc->re_ldata.re_tx_list_map);
+ fail_2:
bus_dmamem_unmap(sc->sc_dmat,
- (caddr_t)sc->rtk_ldata.rtk_tx_list, RTK_TX_LIST_SZ(sc));
-fail_1:
+ (caddr_t)sc->re_ldata.re_tx_list, RE_TX_LIST_SZ(sc));
+ fail_1:
bus_dmamem_free(sc->sc_dmat,
- &sc->rtk_ldata.rtk_tx_listseg, sc->rtk_ldata.rtk_tx_listnseg);
-fail_0:
+ &sc->re_ldata.re_tx_listseg, sc->re_ldata.re_tx_listnseg);
+ fail_0:
return;
}
@@ -856,7 +857,7 @@
int
re_activate(struct device *self, enum devact act)
{
- struct rtk_softc *sc = (void *) self;
+ struct rtk_softc *sc = (void *)self;
int s, error = 0;
s = splnet();
@@ -902,35 +903,33 @@
ether_ifdetach(ifp);
if_detach(ifp);
- /* XXX undo re_allocmem() */
-
/* Destroy DMA maps for RX buffers. */
- for (i = 0; i < RTK_RX_DESC_CNT; i++)
- if (sc->rtk_ldata.rtk_rx_dmamap[i] != NULL)
+ for (i = 0; i < RE_RX_DESC_CNT; i++)
+ if (sc->re_ldata.re_rxsoft[i].rxs_dmamap != NULL)
bus_dmamap_destroy(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_dmamap[i]);
+ sc->re_ldata.re_rxsoft[i].rxs_dmamap);
/* Free DMA'able memory for the RX ring. */
- bus_dmamap_unload(sc->sc_dmat, sc->rtk_ldata.rtk_rx_list_map);
- bus_dmamap_destroy(sc->sc_dmat, sc->rtk_ldata.rtk_rx_list_map);
+ bus_dmamap_unload(sc->sc_dmat, sc->re_ldata.re_rx_list_map);
+ bus_dmamap_destroy(sc->sc_dmat, sc->re_ldata.re_rx_list_map);
bus_dmamem_unmap(sc->sc_dmat,
- (caddr_t)sc->rtk_ldata.rtk_rx_list, RTK_RX_LIST_SZ);
+ (caddr_t)sc->re_ldata.re_rx_list, RE_RX_DMAMEM_SZ);
bus_dmamem_free(sc->sc_dmat,
- &sc->rtk_ldata.rtk_rx_listseg, sc->rtk_ldata.rtk_rx_listnseg);
+ &sc->re_ldata.re_rx_listseg, sc->re_ldata.re_rx_listnseg);
/* Destroy DMA maps for TX buffers. */
- for (i = 0; i < RTK_TX_QLEN; i++)
- if (sc->rtk_ldata.rtk_txq[i].txq_dmamap != NULL)
+ for (i = 0; i < RE_TX_QLEN; i++)
+ if (sc->re_ldata.re_txq[i].txq_dmamap != NULL)
bus_dmamap_destroy(sc->sc_dmat,
- sc->rtk_ldata.rtk_txq[i].txq_dmamap);
+ sc->re_ldata.re_txq[i].txq_dmamap);
/* Free DMA'able memory for the TX ring. */
- bus_dmamap_unload(sc->sc_dmat, sc->rtk_ldata.rtk_tx_list_map);
- bus_dmamap_destroy(sc->sc_dmat, sc->rtk_ldata.rtk_tx_list_map);
+ bus_dmamap_unload(sc->sc_dmat, sc->re_ldata.re_tx_list_map);
+ bus_dmamap_destroy(sc->sc_dmat, sc->re_ldata.re_tx_list_map);
bus_dmamem_unmap(sc->sc_dmat,
- (caddr_t)sc->rtk_ldata.rtk_tx_list, RTK_TX_LIST_SZ(sc));
+ (caddr_t)sc->re_ldata.re_tx_list, RE_TX_LIST_SZ(sc));
bus_dmamem_free(sc->sc_dmat,
- &sc->rtk_ldata.rtk_tx_listseg, sc->rtk_ldata.rtk_tx_listnseg);
+ &sc->re_ldata.re_tx_listseg, sc->re_ldata.re_tx_listnseg);
shutdownhook_disestablish(sc->sc_sdhook);
@@ -946,6 +945,7 @@
static int
re_enable(struct rtk_softc *sc)
{
+
if (RTK_IS_ENABLED(sc) == 0 && sc->sc_enable != NULL) {
if ((*sc->sc_enable)(sc) != 0) {
aprint_error("%s: device enable failed\n",
@@ -978,7 +978,7 @@
void
re_power(int why, void *arg)
{
- struct rtk_softc *sc = (void *) arg;
+ struct rtk_softc *sc = (void *)arg;
struct ifnet *ifp = &sc->ethercom.ec_if;
int s;
@@ -1011,21 +1011,22 @@
{
struct mbuf *n = NULL;
bus_dmamap_t map;
- struct rtk_desc *d;
- u_int32_t cmdstat;
+ struct re_desc *d;
+ struct re_rxsoft *rxs;
+ uint32_t cmdstat;
int error;
if (m == NULL) {
MGETHDR(n, M_DONTWAIT, MT_DATA);
if (n == NULL)
return ENOBUFS;
- m = n;
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- m_freem(m);
+ MCLGET(n, M_DONTWAIT);
+ if ((n->m_flags & M_EXT) == 0) {
+ m_freem(n);
return ENOBUFS;
}
+ m = n;
} else
m->m_data = m->m_ext.ext_buf;
@@ -1034,37 +1035,46 @@
* alignment so that the frame payload is
* longword aligned.
*/
- m->m_len = m->m_pkthdr.len = MCLBYTES;
- m_adj(m, RTK_ETHER_ALIGN);
+ m->m_len = m->m_pkthdr.len = MCLBYTES - RE_ETHER_ALIGN;
+ m->m_data += RE_ETHER_ALIGN;
- map = sc->rtk_ldata.rtk_rx_dmamap[idx];
+ rxs = &sc->re_ldata.re_rxsoft[idx];
+ map = rxs->rxs_dmamap;
error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m,
BUS_DMA_READ|BUS_DMA_NOWAIT);
if (error)
goto out;
- d = &sc->rtk_ldata.rtk_rx_list[idx];
- if (le32toh(d->rtk_cmdstat) & RTK_RDESC_STAT_OWN)
- goto out;
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
- cmdstat = map->dm_segs[0].ds_len;
- d->rtk_bufaddr_lo = htole32(RTK_ADDR_LO(map->dm_segs[0].ds_addr));
- d->rtk_bufaddr_hi = htole32(RTK_ADDR_HI(map->dm_segs[0].ds_addr));
- if (idx == (RTK_RX_DESC_CNT - 1))
- cmdstat |= RTK_RDESC_CMD_EOR;
- d->rtk_cmdstat = htole32(cmdstat);
-
- sc->rtk_ldata.rtk_rx_list[idx].rtk_cmdstat |=
- htole32(RTK_RDESC_CMD_OWN);
- sc->rtk_ldata.rtk_rx_mbuf[idx] = m;
+ d = &sc->re_ldata.re_rx_list[idx];
+#ifdef DIAGNOSTIC
+ RE_RXDESCSYNC(sc, idx, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ cmdstat = le32toh(d->re_cmdstat);
+ RE_RXDESCSYNC(sc, idx, BUS_DMASYNC_PREREAD);
+ if (cmdstat & RE_RDESC_STAT_OWN) {
+ panic("%s: tried to map busy RX descriptor",
+ sc->sc_dev.dv_xname);
+ }
+#endif
- bus_dmamap_sync(sc->sc_dmat, sc->rtk_ldata.rtk_rx_dmamap[idx], 0,
- sc->rtk_ldata.rtk_rx_dmamap[idx]->dm_mapsize,
- BUS_DMASYNC_PREREAD);
+ rxs->rxs_mbuf = m;
+
+ d->re_vlanctl = 0;
+ cmdstat = map->dm_segs[0].ds_len;
+ if (idx == (RE_RX_DESC_CNT - 1))
+ cmdstat |= RE_RDESC_CMD_EOR;
+ re_set_bufaddr(d, map->dm_segs[0].ds_addr);
+ d->re_cmdstat = htole32(cmdstat);
+ RE_RXDESCSYNC(sc, idx, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+ cmdstat |= RE_RDESC_CMD_OWN;
+ d->re_cmdstat = htole32(cmdstat);
+ RE_RXDESCSYNC(sc, idx, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
return 0;
-out:
+ out:
if (n != NULL)
m_freem(n);
return ENOMEM;
@@ -1075,18 +1085,20 @@
{
int i;
- memset(sc->rtk_ldata.rtk_tx_list, 0, RTK_TX_LIST_SZ(sc));
- for (i = 0; i < RTK_TX_QLEN; i++) {
- sc->rtk_ldata.rtk_txq[i].txq_mbuf = NULL;
+ memset(sc->re_ldata.re_tx_list, 0, RE_TX_LIST_SZ(sc));
+ for (i = 0; i < RE_TX_QLEN; i++) {
+ sc->re_ldata.re_txq[i].txq_mbuf = NULL;
}
bus_dmamap_sync(sc->sc_dmat,
- sc->rtk_ldata.rtk_tx_list_map, 0,
- sc->rtk_ldata.rtk_tx_list_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
- sc->rtk_ldata.rtk_txq_prodidx = 0;
- sc->rtk_ldata.rtk_txq_considx = 0;
- sc->rtk_ldata.rtk_tx_free = RTK_TX_DESC_CNT(sc);
- sc->rtk_ldata.rtk_tx_nextfree = 0;
+ sc->re_ldata.re_tx_list_map, 0,
+ sc->re_ldata.re_tx_list_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+ sc->re_ldata.re_txq_prodidx = 0;
+ sc->re_ldata.re_txq_considx = 0;
+ sc->re_ldata.re_txq_free = RE_TX_QLEN;
+ sc->re_ldata.re_tx_free = RE_TX_DESC_CNT(sc);
+ sc->re_ldata.re_tx_nextfree = 0;
return 0;
}
@@ -1096,24 +1108,15 @@
{
int i;
- memset((char *)sc->rtk_ldata.rtk_rx_list, 0, RTK_RX_LIST_SZ);
- memset((char *)&sc->rtk_ldata.rtk_rx_mbuf, 0,
- (RTK_RX_DESC_CNT * sizeof(struct mbuf *)));
+ memset((char *)sc->re_ldata.re_rx_list, 0, RE_RX_LIST_SZ);
- for (i = 0; i < RTK_RX_DESC_CNT; i++) {
+ for (i = 0; i < RE_RX_DESC_CNT; i++) {
if (re_newbuf(sc, i, NULL) == ENOBUFS)
return ENOBUFS;
}
- /* Flush the RX descriptors */
-
- bus_dmamap_sync(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_list_map,
- 0, sc->rtk_ldata.rtk_rx_list_map->dm_mapsize,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
-
- sc->rtk_ldata.rtk_rx_prodidx = 0;
- sc->rtk_head = sc->rtk_tail = NULL;
+ sc->re_ldata.re_rx_prodidx = 0;
+ sc->re_head = sc->re_tail = NULL;
return 0;
}
@@ -1129,47 +1132,43 @@
struct mbuf *m;
struct ifnet *ifp;
int i, total_len;
- struct rtk_desc *cur_rx;
- u_int32_t rxstat, rxvlan;
+ struct re_desc *cur_rx;
+ struct re_rxsoft *rxs;
+ uint32_t rxstat, rxvlan;
ifp = &sc->ethercom.ec_if;
- i = sc->rtk_ldata.rtk_rx_prodidx;
-
- /* Invalidate the descriptor memory */
-
- bus_dmamap_sync(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_list_map,
- 0, sc->rtk_ldata.rtk_rx_list_map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
-
- while (!RTK_OWN(&sc->rtk_ldata.rtk_rx_list[i])) {
- cur_rx = &sc->rtk_ldata.rtk_rx_list[i];
- m = sc->rtk_ldata.rtk_rx_mbuf[i];
- total_len = RTK_RXBYTES(cur_rx);
- rxstat = le32toh(cur_rx->rtk_cmdstat);
- rxvlan = le32toh(cur_rx->rtk_vlanctl);
+ for (i = sc->re_ldata.re_rx_prodidx;; i = RE_NEXT_RX_DESC(sc, i)) {
+ cur_rx = &sc->re_ldata.re_rx_list[i];
+ RE_RXDESCSYNC(sc, i,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ rxstat = le32toh(cur_rx->re_cmdstat);
+ RE_RXDESCSYNC(sc, i, BUS_DMASYNC_PREREAD);
+ if ((rxstat & RE_RDESC_STAT_OWN) != 0) {
+ break;
+ }
+ total_len = rxstat & sc->re_rxlenmask;
+ rxvlan = le32toh(cur_rx->re_vlanctl);
+ rxs = &sc->re_ldata.re_rxsoft[i];
+ m = rxs->rxs_mbuf;
/* Invalidate the RX mbuf and unload its map */
bus_dmamap_sync(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_dmamap[i],
- 0, sc->rtk_ldata.rtk_rx_dmamap[i]->dm_mapsize,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_dmamap[i]);
-
- if (!(rxstat & RTK_RDESC_STAT_EOF)) {
- m->m_len = MCLBYTES - RTK_ETHER_ALIGN;
- if (sc->rtk_head == NULL)
- sc->rtk_head = sc->rtk_tail = m;
+ rxs->rxs_dmamap, 0, rxs->rxs_dmamap->dm_mapsize,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
+
+ if ((rxstat & RE_RDESC_STAT_EOF) == 0) {
+ m->m_len = MCLBYTES - RE_ETHER_ALIGN;
+ if (sc->re_head == NULL)
+ sc->re_head = sc->re_tail = m;
else {
m->m_flags &= ~M_PKTHDR;
- sc->rtk_tail->m_next = m;
- sc->rtk_tail = m;
+ sc->re_tail->m_next = m;
+ sc->re_tail = m;
}
re_newbuf(sc, i, NULL);
- RTK_RX_DESC_INC(sc, i);
continue;
}
@@ -1192,18 +1191,34 @@
if (sc->rtk_type == RTK_8169)
rxstat >>= 1;
- if (rxstat & RTK_RDESC_STAT_RXERRSUM) {
+ if (__predict_false((rxstat & RE_RDESC_STAT_RXERRSUM) != 0)) {
+#ifdef RE_DEBUG
+ aprint_error("%s: RX error (rxstat = 0x%08x)",
+ sc->sc_dev.dv_xname, rxstat);
+ if (rxstat & RE_RDESC_STAT_FRALIGN)
+ aprint_error(", frame alignment error");
+ if (rxstat & RE_RDESC_STAT_BUFOFLOW)
+ aprint_error(", out of buffer space");
+ if (rxstat & RE_RDESC_STAT_FIFOOFLOW)
+ aprint_error(", FIFO overrun");
+ if (rxstat & RE_RDESC_STAT_GIANT)
+ aprint_error(", giant packet");
+ if (rxstat & RE_RDESC_STAT_RUNT)
+ aprint_error(", runt packet");
+ if (rxstat & RE_RDESC_STAT_CRCERR)
+ aprint_error(", CRC error");
+ aprint_error("\n");
+#endif
ifp->if_ierrors++;
/*
* If this is part of a multi-fragment packet,
* discard all the pieces.
*/
- if (sc->rtk_head != NULL) {
- m_freem(sc->rtk_head);
- sc->rtk_head = sc->rtk_tail = NULL;
+ if (sc->re_head != NULL) {
+ m_freem(sc->re_head);
+ sc->re_head = sc->re_tail = NULL;
}
re_newbuf(sc, i, m);
- RTK_RX_DESC_INC(sc, i);
continue;
}
@@ -1212,21 +1227,18 @@
* reload the current one.
*/
- if (re_newbuf(sc, i, NULL)) {
+ if (__predict_false(re_newbuf(sc, i, NULL) != 0)) {
ifp->if_ierrors++;
- if (sc->rtk_head != NULL) {
- m_freem(sc->rtk_head);
- sc->rtk_head = sc->rtk_tail = NULL;
+ if (sc->re_head != NULL) {
+ m_freem(sc->re_head);
+ sc->re_head = sc->re_tail = NULL;
}
re_newbuf(sc, i, m);
- RTK_RX_DESC_INC(sc, i);
continue;
}
- RTK_RX_DESC_INC(sc, i);
-
- if (sc->rtk_head != NULL) {
- m->m_len = total_len % (MCLBYTES - RTK_ETHER_ALIGN);
+ if (sc->re_head != NULL) {
+ m->m_len = total_len % (MCLBYTES - RE_ETHER_ALIGN);
/*
* Special case: if there's 4 bytes or less
* in this buffer, the mbuf can be discarded:
@@ -1234,16 +1246,16 @@
* care about anyway.
*/
if (m->m_len <= ETHER_CRC_LEN) {
- sc->rtk_tail->m_len -=
+ sc->re_tail->m_len -=
(ETHER_CRC_LEN - m->m_len);
m_freem(m);
} else {
m->m_len -= ETHER_CRC_LEN;
m->m_flags &= ~M_PKTHDR;
- sc->rtk_tail->m_next = m;
+ sc->re_tail->m_next = m;
}
- m = sc->rtk_head;
- sc->rtk_head = sc->rtk_tail = NULL;
+ m = sc->re_head;
+ sc->re_head = sc->re_tail = NULL;
m->m_pkthdr.len = total_len - ETHER_CRC_LEN;
} else
m->m_pkthdr.len = m->m_len =
@@ -1252,38 +1264,31 @@
ifp->if_ipackets++;
m->m_pkthdr.rcvif = ifp;
- /* Do RX checksumming if enabled */
+ /* Do RX checksumming */
- if (ifp->if_capenable & IFCAP_CSUM_IPv4) {
-
- /* Check IP header checksum */
- if (rxstat & RTK_RDESC_STAT_PROTOID)
- m->m_pkthdr.csum_flags |= M_CSUM_IPv4;;
- if (rxstat & RTK_RDESC_STAT_IPSUMBAD)
+ /* Check IP header checksum */
+ if (rxstat & RE_RDESC_STAT_PROTOID) {
+ m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
+ if (rxstat & RE_RDESC_STAT_IPSUMBAD)
m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
}
/* Check TCP/UDP checksum */
- if (RTK_TCPPKT(rxstat) &&
- (ifp->if_capenable & IFCAP_CSUM_TCPv4)) {
+ if (RE_TCPPKT(rxstat)) {
m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
- if (rxstat & RTK_RDESC_STAT_TCPSUMBAD)
+ if (rxstat & RE_RDESC_STAT_TCPSUMBAD)
m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
- }
- if (RTK_UDPPKT(rxstat) &&
- (ifp->if_capenable & IFCAP_CSUM_UDPv4)) {
+ } else if (RE_UDPPKT(rxstat)) {
m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
- if (rxstat & RTK_RDESC_STAT_UDPSUMBAD)
+ if (rxstat & RE_RDESC_STAT_UDPSUMBAD)
m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
}
-#ifdef RE_VLAN
- if (rxvlan & RTK_RDESC_VLANCTL_TAG) {
+ if (rxvlan & RE_RDESC_VLANCTL_TAG) {
VLAN_INPUT_TAG(ifp, m,
- be16toh(rxvlan & RTK_RDESC_VLANCTL_DATA),
+ bswap16(rxvlan & RE_RDESC_VLANCTL_DATA),
continue);
}
-#endif
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m);
@@ -1291,74 +1296,56 @@
(*ifp->if_input)(ifp, m);
}
- /* Flush the RX DMA ring */
-
- bus_dmamap_sync(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_list_map,
- 0, sc->rtk_ldata.rtk_rx_list_map->dm_mapsize,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
-
- sc->rtk_ldata.rtk_rx_prodidx = i;
-
- return;
+ sc->re_ldata.re_rx_prodidx = i;
}
static void
re_txeof(struct rtk_softc *sc)
{
struct ifnet *ifp;
- int idx;
+ struct re_txq *txq;
+ uint32_t txstat;
+ int idx, descidx;
ifp = &sc->ethercom.ec_if;
- idx = sc->rtk_ldata.rtk_txq_considx;
-
- /* Invalidate the TX descriptor list */
- bus_dmamap_sync(sc->sc_dmat,
- sc->rtk_ldata.rtk_tx_list_map,
- 0, sc->rtk_ldata.rtk_tx_list_map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
-
- while (/* CONSTCOND */ 1) {
- struct rtk_txq *txq = &sc->rtk_ldata.rtk_txq[idx];
- int descidx;
- u_int32_t txstat;
-
- if (txq->txq_mbuf == NULL) {
- KASSERT(idx == sc->rtk_ldata.rtk_txq_prodidx);
- break;
- }
+ for (idx = sc->re_ldata.re_txq_considx;
+ sc->re_ldata.re_txq_free < RE_TX_QLEN;
+ idx = RE_NEXT_TXQ(sc, idx), sc->re_ldata.re_txq_free++) {
+ txq = &sc->re_ldata.re_txq[idx];
+ KASSERT(txq->txq_mbuf != NULL);
descidx = txq->txq_descidx;
+ RE_TXDESCSYNC(sc, descidx,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
txstat =
- le32toh(sc->rtk_ldata.rtk_tx_list[descidx].rtk_cmdstat);
- KASSERT((txstat & RTK_TDESC_CMD_EOF) != 0);
- if (txstat & RTK_TDESC_CMD_OWN)
+ le32toh(sc->re_ldata.re_tx_list[descidx].re_cmdstat);
+ RE_TXDESCSYNC(sc, descidx, BUS_DMASYNC_PREREAD);
+ KASSERT((txstat & RE_TDESC_CMD_EOF) != 0);
+ if (txstat & RE_TDESC_CMD_OWN) {
break;
+ }
- sc->rtk_ldata.rtk_tx_free += txq->txq_dmamap->dm_nsegs;
- KASSERT(sc->rtk_ldata.rtk_tx_free <= RTK_TX_DESC_CNT(sc));
+ sc->re_ldata.re_tx_free += txq->txq_nsegs;
+ KASSERT(sc->re_ldata.re_tx_free <= RE_TX_DESC_CNT(sc));
+ bus_dmamap_sync(sc->sc_dmat, txq->txq_dmamap,
+ 0, txq->txq_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, txq->txq_dmamap);
m_freem(txq->txq_mbuf);
txq->txq_mbuf = NULL;
- if (txstat & (RTK_TDESC_STAT_EXCESSCOL | RTK_TDESC_STAT_COLCNT))
+ if (txstat & (RE_TDESC_STAT_EXCESSCOL | RE_TDESC_STAT_COLCNT))
ifp->if_collisions++;
- if (txstat & RTK_TDESC_STAT_TXERRSUM)
+ if (txstat & RE_TDESC_STAT_TXERRSUM)
ifp->if_oerrors++;
else
ifp->if_opackets++;
-
- idx = (idx + 1) % RTK_TX_QLEN;
}
- /* No changes made to the TX ring, so no flush needed */
+ sc->re_ldata.re_txq_considx = idx;
- if (idx != sc->rtk_ldata.rtk_txq_considx) {
- sc->rtk_ldata.rtk_txq_considx = idx;
+ if (sc->re_ldata.re_txq_free > RE_NTXDESC_RSVD)
ifp->if_flags &= ~IFF_OACTIVE;
- ifp->if_timer = 0;
- }
/*
* If not all descriptors have been released reaped yet,
@@ -1366,10 +1353,10 @@
* interrupt that will cause us to re-enter this routine.
* This is done in case the transmitter has gone idle.
*/
- if (sc->rtk_ldata.rtk_tx_free != RTK_TX_DESC_CNT(sc))
+ if (sc->re_ldata.re_txq_free < RE_TX_QLEN)
CSR_WRITE_4(sc, RTK_TIMERCNT, 1);
-
- return;
+ else
+ ifp->if_timer = 0;
}
/*
@@ -1380,7 +1367,7 @@
re_shutdown(void *vsc)
{
- struct rtk_softc *sc = (struct rtk_softc *)vsc;
+ struct rtk_softc *sc = vsc;
re_stop(&sc->ethercom.ec_if, 0);
}
@@ -1408,7 +1395,7 @@
struct rtk_softc *sc = ifp->if_softc;
RTK_LOCK(sc);
- if (!(ifp->if_capenable & IFCAP_POLLING)) {
+ if ((ifp->if_capenable & IFCAP_POLLING) == 0) {
ether_poll_deregister(ifp);
cmd = POLL_DEREGISTER;
}
@@ -1421,11 +1408,11 @@
re_rxeof(sc);
re_txeof(sc);
- if (ifp->if_snd.ifq_head != NULL)
+ if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
(*ifp->if_start)(ifp);
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
- u_int16_t status;
+ uint16_t status;
status = CSR_READ_2(sc, RTK_ISR);
if (status == 0xffff)
@@ -1438,11 +1425,10 @@
*/
if (status & RTK_ISR_SYSTEM_ERR) {
- re_reset(sc);
re_init(sc);
}
}
-done:
+ done:
RTK_UNLOCK(sc);
}
#endif /* DEVICE_POLLING */
@@ -1452,12 +1438,12 @@
{
struct rtk_softc *sc = arg;
struct ifnet *ifp;
- u_int16_t status;
+ uint16_t status;
int handled = 0;
ifp = &sc->ethercom.ec_if;
- if (!(ifp->if_flags & IFF_UP))
+ if ((ifp->if_flags & IFF_UP) == 0)
return 0;
#ifdef DEVICE_POLLING
@@ -1485,17 +1471,14 @@
if ((status & RTK_INTRS_CPLUS) == 0)
break;
- if ((status & RTK_ISR_RX_OK) ||
- (status & RTK_ISR_RX_ERR))
+ if (status & (RTK_ISR_RX_OK | RTK_ISR_RX_ERR))
re_rxeof(sc);
- if ((status & RTK_ISR_TIMEOUT_EXPIRED) ||
- (status & RTK_ISR_TX_ERR) ||
- (status & RTK_ISR_TX_DESC_UNAVAIL))
+ if (status & (RTK_ISR_TIMEOUT_EXPIRED | RTK_ISR_TX_ERR |
+ RTK_ISR_TX_DESC_UNAVAIL))
re_txeof(sc);
if (status & RTK_ISR_SYSTEM_ERR) {
- re_reset(sc);
re_init(ifp);
}
@@ -1505,166 +1488,17 @@
}
}
- if (ifp->if_flags & IFF_UP) /* kludge for interrupt during re_init() */
- if (ifp->if_snd.ifq_head != NULL)
- (*ifp->if_start)(ifp);
+ if (handled && !IFQ_IS_EMPTY(&ifp->if_snd))
+ re_start(ifp);
#ifdef DEVICE_POLLING
-done:
+ done:
#endif
return handled;
}
-static int
-re_encap(struct rtk_softc *sc, struct mbuf *m, int *idx)
-{
- bus_dmamap_t map;
- int error, i, startidx, curidx;
-#ifdef RE_VLAN
- struct m_tag *mtag;
-#endif
- struct rtk_desc *d;
- u_int32_t cmdstat, rtk_flags;
- struct rtk_txq *txq;
-
- if (sc->rtk_ldata.rtk_tx_free <= 4) {
- return EFBIG;
- }
-
- /*
- * Set up checksum offload. Note: checksum offload bits must
- * appear in all descriptors of a multi-descriptor transmit
- * attempt. (This is according to testing done with an 8169
- * chip. I'm not sure if this is a requirement or a bug.)
- */
-
- if ((m->m_pkthdr.csum_flags & M_CSUM_TSOv4) != 0) {
- u_int32_t segsz = m->m_pkthdr.segsz;
-
- rtk_flags = RTK_TDESC_CMD_LGSEND |
- (segsz << RTK_TDESC_CMD_MSSVAL_SHIFT);
- } else {
-
- /*
- * set RTK_TDESC_CMD_IPCSUM if any checksum offloading
- * is requested. otherwise, RTK_TDESC_CMD_TCPCSUM/
- * RTK_TDESC_CMD_UDPCSUM doesn't make effects.
- */
- rtk_flags = 0;
- if ((m->m_pkthdr.csum_flags &
- (M_CSUM_IPv4 | M_CSUM_TCPv4 | M_CSUM_UDPv4)) != 0) {
- rtk_flags |= RTK_TDESC_CMD_IPCSUM;
- if (m->m_pkthdr.csum_flags & M_CSUM_TCPv4) {
- rtk_flags |= RTK_TDESC_CMD_TCPCSUM;
- } else if (m->m_pkthdr.csum_flags & M_CSUM_UDPv4) {
- rtk_flags |= RTK_TDESC_CMD_UDPCSUM;
- }
- }
- }
-
- txq = &sc->rtk_ldata.rtk_txq[*idx];
- map = txq->txq_dmamap;
- error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m,
- BUS_DMA_WRITE|BUS_DMA_NOWAIT);
-
- if (error) {
- /* XXX try to defrag if EFBIG? */
-
- aprint_error("%s: can't map mbuf (error %d)\n",
- sc->sc_dev.dv_xname, error);
-
- return error;
- }
-
- if (map->dm_nsegs > sc->rtk_ldata.rtk_tx_free - 4) {
- error = EFBIG;
- goto fail_unload;
- }
- /*
- * Map the segment array into descriptors. Note that we set the
- * start-of-frame and end-of-frame markers for either TX or RX, but
- * they really only have meaning in the TX case. (In the RX case,
- * it's the chip that tells us where packets begin and end.)
- * We also keep track of the end of the ring and set the
- * end-of-ring bits as needed, and we set the ownership bits
- * in all except the very first descriptor. (The caller will
- * set this descriptor later when it start transmission or
- * reception.)
- */
- i = 0;
- curidx = startidx = sc->rtk_ldata.rtk_tx_nextfree;
- while (1) {
- d = &sc->rtk_ldata.rtk_tx_list[curidx];
- if (le32toh(d->rtk_cmdstat) & RTK_TDESC_STAT_OWN) {
- while (i > 0) {
- sc->rtk_ldata.rtk_tx_list[
- (curidx + RTK_TX_DESC_CNT(sc) - i) %
- RTK_TX_DESC_CNT(sc)].rtk_cmdstat = 0;
- i--;
- }
- error = ENOBUFS;
- goto fail_unload;
- }
-
- cmdstat = map->dm_segs[i].ds_len;
- d->rtk_bufaddr_lo =
- htole32(RTK_ADDR_LO(map->dm_segs[i].ds_addr));
- d->rtk_bufaddr_hi =
- htole32(RTK_ADDR_HI(map->dm_segs[i].ds_addr));
- if (i == 0)
- cmdstat |= RTK_TDESC_CMD_SOF;
- else
- cmdstat |= RTK_TDESC_CMD_OWN;
- if (curidx == (RTK_TX_DESC_CNT(sc) - 1))
- cmdstat |= RTK_TDESC_CMD_EOR;
- d->rtk_cmdstat = htole32(cmdstat | rtk_flags);
- i++;
- if (i == map->dm_nsegs)
- break;
- RTK_TX_DESC_INC(sc, curidx);
- }
-
- d->rtk_cmdstat |= htole32(RTK_TDESC_CMD_EOF);
-
- txq->txq_mbuf = m;
- sc->rtk_ldata.rtk_tx_free -= map->dm_nsegs;
-
- /*
- * Set up hardware VLAN tagging. Note: vlan tag info must
- * appear in the first descriptor of a multi-descriptor
- * transmission attempt.
- */
-
-#ifdef RE_VLAN
- if ((mtag = VLAN_OUTPUT_TAG(&sc->ethercom, m)) != NULL) {
- sc->rtk_ldata.rtk_tx_list[startidx].rtk_vlanctl =
- htole32(htons(VLAN_TAG_VALUE(mtag)) |
- RTK_TDESC_VLANCTL_TAG);
- }
-#endif
-
- /* Transfer ownership of packet to the chip. */
-
- sc->rtk_ldata.rtk_tx_list[curidx].rtk_cmdstat |=
- htole32(RTK_TDESC_CMD_OWN);
- if (startidx != curidx)
- sc->rtk_ldata.rtk_tx_list[startidx].rtk_cmdstat |=
- htole32(RTK_TDESC_CMD_OWN);
-
- txq->txq_descidx = curidx;
- RTK_TX_DESC_INC(sc, curidx);
- sc->rtk_ldata.rtk_tx_nextfree = curidx;
- *idx = (*idx + 1) % RTK_TX_QLEN;
-
- return 0;
-
-fail_unload:
- bus_dmamap_unload(sc->sc_dmat, map);
-
- return error;
-}
/*
* Main transmit routine for C+ and gigE NICs.
@@ -1674,40 +1508,200 @@
re_start(struct ifnet *ifp)
{
struct rtk_softc *sc;
- int idx;
+ struct mbuf *m;
+ bus_dmamap_t map;
+ struct re_txq *txq;
+ struct re_desc *d;
+ struct m_tag *mtag;
+ uint32_t cmdstat, re_flags;
+ int ofree, idx, error, nsegs, seg;
+ int startdesc, curdesc, lastdesc;
+ boolean_t pad;
sc = ifp->if_softc;
+ ofree = sc->re_ldata.re_txq_free;
- idx = sc->rtk_ldata.rtk_txq_prodidx;
- while (/* CONSTCOND */ 1) {
- struct mbuf *m;
- int error;
+ for (idx = sc->re_ldata.re_txq_prodidx;; idx = RE_NEXT_TXQ(sc, idx)) {
IFQ_POLL(&ifp->if_snd, m);
if (m == NULL)
break;
- if (sc->rtk_ldata.rtk_txq[idx].txq_mbuf != NULL) {
- KASSERT(idx == sc->rtk_ldata.rtk_txq_considx);
+ if (sc->re_ldata.re_txq_free == 0 ||
+ sc->re_ldata.re_tx_free <= RE_NTXDESC_RSVD) {
+ /* no more free slots left */
ifp->if_flags |= IFF_OACTIVE;
break;
}
- error = re_encap(sc, m, &idx);
- if (error == EFBIG &&
- sc->rtk_ldata.rtk_tx_free == RTK_TX_DESC_CNT(sc)) {
+ /*
+ * Set up checksum offload. Note: checksum offload bits must
+ * appear in all descriptors of a multi-descriptor transmit
+ * attempt. (This is according to testing done with an 8169
+ * chip. I'm not sure if this is a requirement or a bug.)
+ */
+
+ if ((m->m_pkthdr.csum_flags & M_CSUM_TSOv4) != 0) {
+ uint32_t segsz = m->m_pkthdr.segsz;
+
+ re_flags = RE_TDESC_CMD_LGSEND |
+ (segsz << RE_TDESC_CMD_MSSVAL_SHIFT);
+ } else {
+ /*
+ * set RE_TDESC_CMD_IPCSUM if any checksum offloading
+ * is requested. otherwise, RE_TDESC_CMD_TCPCSUM/
+ * RE_TDESC_CMD_UDPCSUM doesn't make effects.
+ */
+ re_flags = 0;
+ if ((m->m_pkthdr.csum_flags &
+ (M_CSUM_IPv4 | M_CSUM_TCPv4 | M_CSUM_UDPv4))
+ != 0) {
+ re_flags |= RE_TDESC_CMD_IPCSUM;
+ if (m->m_pkthdr.csum_flags & M_CSUM_TCPv4) {
+ re_flags |= RE_TDESC_CMD_TCPCSUM;
+ } else if (m->m_pkthdr.csum_flags &
+ M_CSUM_UDPv4) {
+ re_flags |= RE_TDESC_CMD_UDPCSUM;
+ }
+ }
+ }
+
+ txq = &sc->re_ldata.re_txq[idx];
+ map = txq->txq_dmamap;
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m,
+ BUS_DMA_WRITE|BUS_DMA_NOWAIT);
+
+ if (__predict_false(error)) {
+ /* XXX try to defrag if EFBIG? */
+ aprint_error("%s: can't map mbuf (error %d)\n",
+ sc->sc_dev.dv_xname, error);
+
IFQ_DEQUEUE(&ifp->if_snd, m);
m_freem(m);
ifp->if_oerrors++;
continue;
}
- if (error) {
+
+ nsegs = map->dm_nsegs;
+ pad = FALSE;
+ if (__predict_false(m->m_pkthdr.len <= RE_IP4CSUMTX_PADLEN &&
+ (re_flags & RE_TDESC_CMD_IPCSUM) != 0)) {
+ pad = TRUE;
+ nsegs++;
+ }
+
+ if (nsegs > sc->re_ldata.re_tx_free - RE_NTXDESC_RSVD) {
+ /*
+ * Not enough free descriptors to transmit this packet.
+ */
ifp->if_flags |= IFF_OACTIVE;
+ bus_dmamap_unload(sc->sc_dmat, map);
break;
}
IFQ_DEQUEUE(&ifp->if_snd, m);
+ /*
+ * Make sure that the caches are synchronized before we
+ * ask the chip to start DMA for the packet data.
+ */
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_PREWRITE);
+
+ /*
+ * Map the segment array into descriptors.
+ * Note that we set the start-of-frame and
+ * end-of-frame markers for either TX or RX,
+ * but they really only have meaning in the TX case.
+ * (In the RX case, it's the chip that tells us
+ * where packets begin and end.)
+ * We also keep track of the end of the ring
+ * and set the end-of-ring bits as needed,
+ * and we set the ownership bits in all except
+ * the very first descriptor. (The caller will
+ * set this descriptor later when it start
+ * transmission or reception.)
+ */
+ curdesc = startdesc = sc->re_ldata.re_tx_nextfree;
+ lastdesc = -1;
+ for (seg = 0; seg < map->dm_nsegs;
+ seg++, curdesc = RE_NEXT_TX_DESC(sc, curdesc)) {
+ d = &sc->re_ldata.re_tx_list[curdesc];
+#ifdef DIAGNOSTIC
+ RE_TXDESCSYNC(sc, curdesc,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ cmdstat = le32toh(d->re_cmdstat);
+ RE_TXDESCSYNC(sc, curdesc, BUS_DMASYNC_PREREAD);
+ if (cmdstat & RE_TDESC_STAT_OWN) {
+ panic("%s: tried to map busy TX descriptor",
+ sc->sc_dev.dv_xname);
+ }
+#endif
+
+ d->re_vlanctl = 0;
+ re_set_bufaddr(d, map->dm_segs[seg].ds_addr);
+ cmdstat = re_flags | map->dm_segs[seg].ds_len;
+ if (seg == 0)
+ cmdstat |= RE_TDESC_CMD_SOF;
+ else
+ cmdstat |= RE_TDESC_CMD_OWN;
+ if (curdesc == (RE_TX_DESC_CNT(sc) - 1))
+ cmdstat |= RE_TDESC_CMD_EOR;
+ if (seg == nsegs - 1) {
+ cmdstat |= RE_TDESC_CMD_EOF;
+ lastdesc = curdesc;
+ }
+ d->re_cmdstat = htole32(cmdstat);
+ RE_TXDESCSYNC(sc, curdesc,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+ }
+ if (__predict_false(pad)) {
+ bus_addr_t paddaddr;
+
+ d = &sc->re_ldata.re_tx_list[curdesc];
+ d->re_vlanctl = 0;
+ paddaddr = RE_TXPADDADDR(sc);
+ re_set_bufaddr(d, paddaddr);
+ cmdstat = re_flags |
+ RE_TDESC_CMD_OWN | RE_TDESC_CMD_EOF |
+ (RE_IP4CSUMTX_PADLEN + 1 - m->m_pkthdr.len);
+ if (curdesc == (RE_TX_DESC_CNT(sc) - 1))
+ cmdstat |= RE_TDESC_CMD_EOR;
+ d->re_cmdstat = htole32(cmdstat);
+ RE_TXDESCSYNC(sc, curdesc,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+ lastdesc = curdesc;
+ curdesc = RE_NEXT_TX_DESC(sc, curdesc);
+ }
+ KASSERT(lastdesc != -1);
+
+ /*
+ * Set up hardware VLAN tagging. Note: vlan tag info must
+ * appear in the first descriptor of a multi-descriptor
+ * transmission attempt.
+ */
+ if ((mtag = VLAN_OUTPUT_TAG(&sc->ethercom, m)) != NULL) {
+ sc->re_ldata.re_tx_list[startdesc].re_vlanctl =
+ htole32(bswap16(VLAN_TAG_VALUE(mtag)) |
+ RE_TDESC_VLANCTL_TAG);
+ }
+
+ /* Transfer ownership of packet to the chip. */
+
+ sc->re_ldata.re_tx_list[startdesc].re_cmdstat |=
+ htole32(RE_TDESC_CMD_OWN);
+ RE_TXDESCSYNC(sc, startdesc,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+
+ /* update info of TX queue and descriptors */
+ txq->txq_mbuf = m;
+ txq->txq_descidx = lastdesc;
+ txq->txq_nsegs = nsegs;
+
+ sc->re_ldata.re_txq_free--;
+ sc->re_ldata.re_tx_free -= nsegs;
+ sc->re_ldata.re_tx_nextfree = curdesc;
+
#if NBPFILTER > 0
/*
* If there's a BPF listener, bounce a copy of this frame
@@ -1718,52 +1712,47 @@
#endif
}
- if (sc->rtk_ldata.rtk_txq_prodidx == idx) {
- return;
- }
- sc->rtk_ldata.rtk_txq_prodidx = idx;
-
- /* Flush the TX descriptors */
-
- bus_dmamap_sync(sc->sc_dmat,
- sc->rtk_ldata.rtk_tx_list_map,
- 0, sc->rtk_ldata.rtk_tx_list_map->dm_mapsize,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
-
- /*
- * RealTek put the TX poll request register in a different
- * location on the 8169 gigE chip. I don't know why.
- */
-
- if (sc->rtk_type == RTK_8169)
- CSR_WRITE_2(sc, RTK_GTXSTART, RTK_TXSTART_START);
- else
- CSR_WRITE_2(sc, RTK_TXSTART, RTK_TXSTART_START);
+ if (sc->re_ldata.re_txq_free < ofree) {
+ /*
+ * TX packets are enqueued.
+ */
+ sc->re_ldata.re_txq_prodidx = idx;
- /*
- * Use the countdown timer for interrupt moderation.
- * 'TX done' interrupts are disabled. Instead, we reset the
- * countdown timer, which will begin counting until it hits
- * the value in the TIMERINT register, and then trigger an
- * interrupt. Each time we write to the TIMERCNT register,
- * the timer count is reset to 0.
- */
- CSR_WRITE_4(sc, RTK_TIMERCNT, 1);
+ /*
+ * Start the transmitter to poll.
+ *
+ * RealTek put the TX poll request register in a different
+ * location on the 8169 gigE chip. I don't know why.
+ */
+ if (sc->rtk_type == RTK_8169)
+ CSR_WRITE_2(sc, RTK_GTXSTART, RTK_TXSTART_START);
+ else
+ CSR_WRITE_1(sc, RTK_TXSTART, RTK_TXSTART_START);
- /*
- * Set a timeout in case the chip goes out to lunch.
- */
- ifp->if_timer = 5;
+ /*
+ * Use the countdown timer for interrupt moderation.
+ * 'TX done' interrupts are disabled. Instead, we reset the
+ * countdown timer, which will begin counting until it hits
+ * the value in the TIMERINT register, and then trigger an
+ * interrupt. Each time we write to the TIMERCNT register,
+ * the timer count is reset to 0.
+ */
+ CSR_WRITE_4(sc, RTK_TIMERCNT, 1);
- return;
+ /*
+ * Set a timeout in case the chip goes out to lunch.
+ */
+ ifp->if_timer = 5;
+ }
}
static int
re_init(struct ifnet *ifp)
{
struct rtk_softc *sc = ifp->if_softc;
- u_int32_t rxcfg = 0;
- u_int32_t reg;
+ uint8_t *enaddr;
+ uint32_t rxcfg = 0;
+ uint32_t reg;
int error;
if ((error = re_enable(sc)) != 0)
@@ -1774,6 +1763,8 @@
*/
re_stop(ifp, 0);
+ re_reset(sc);
+
/*
* Enable C+ RX and TX mode, as well as VLAN stripping and
* RX checksum offload. We must configure the C+ register
@@ -1788,19 +1779,18 @@
*/
/*
- * XXX: For 8169 and 8196S revs below 2, set bit 14.
+ * XXX: For 8169 and 8169S revs below 2, set bit 14.
* For 8169S/8110S rev 2 and above, do not set bit 14.
*/
if (sc->rtk_type == RTK_8169 && sc->sc_rev == 1)
reg |= (0x1 << 14) | RTK_CPLUSCMD_PCI_MRW;;
if (1) {/* not for 8169S ? */
- reg |=
-#ifdef RE_VLAN
+ reg |=
RTK_CPLUSCMD_VLANSTRIP |
-#endif
(ifp->if_capenable &
- (IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4) ?
+ (IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
+ IFCAP_CSUM_UDPv4) ?
RTK_CPLUSCMD_RXCSUM_ENB : 0);
}
@@ -1809,7 +1799,7 @@
/* XXX: from Realtek-supplied Linux driver. Wholly undocumented. */
if (sc->rtk_type == RTK_8169)
- CSR_WRITE_2(sc, RTK_CPLUS_CMD+0x2, 0x0000);
+ CSR_WRITE_2(sc, RTK_IM, 0x0000);
DELAY(10000);
@@ -1819,11 +1809,12 @@
* register write enable" mode to modify the ID registers.
*/
CSR_WRITE_1(sc, RTK_EECMD, RTK_EEMODE_WRITECFG);
- memcpy(®, LLADDR(ifp->if_sadl), 4);
- CSR_WRITE_STREAM_4(sc, RTK_IDR0, reg);
- reg = 0;
- memcpy(®, LLADDR(ifp->if_sadl) + 4, 4);
- CSR_WRITE_STREAM_4(sc, RTK_IDR4, reg);
+ enaddr = LLADDR(ifp->if_sadl);
+ reg = enaddr[0] | (enaddr[1] << 8) |
+ (enaddr[2] << 16) | (enaddr[3] << 24);
+ CSR_WRITE_4(sc, RTK_IDR0, reg);
+ reg = enaddr[4] | (enaddr[5] << 8);
+ CSR_WRITE_4(sc, RTK_IDR4, reg);
CSR_WRITE_1(sc, RTK_EECMD, RTK_EEMODE_OFF);
/*
@@ -1833,6 +1824,19 @@
re_tx_list_init(sc);
/*
+ * Load the addresses of the RX and TX lists into the chip.
+ */
+ CSR_WRITE_4(sc, RTK_RXLIST_ADDR_HI,
+ RE_ADDR_HI(sc->re_ldata.re_rx_list_map->dm_segs[0].ds_addr));
+ CSR_WRITE_4(sc, RTK_RXLIST_ADDR_LO,
+ RE_ADDR_LO(sc->re_ldata.re_rx_list_map->dm_segs[0].ds_addr));
+
+ CSR_WRITE_4(sc, RTK_TXLIST_ADDR_HI,
+ RE_ADDR_HI(sc->re_ldata.re_tx_list_map->dm_segs[0].ds_addr));
+ CSR_WRITE_4(sc, RTK_TXLIST_ADDR_LO,
+ RE_ADDR_LO(sc->re_ldata.re_tx_list_map->dm_segs[0].ds_addr));
+
+ /*
* Enable transmit and receive.
*/
CSR_WRITE_1(sc, RTK_COMMAND, RTK_CMD_TX_ENB | RTK_CMD_RX_ENB);
@@ -1840,16 +1844,19 @@
/*
* Set the initial TX and RX configuration.
*/
- if (sc->rtk_testmode) {
+ if (sc->re_testmode) {
if (sc->rtk_type == RTK_8169)
CSR_WRITE_4(sc, RTK_TXCFG,
- RTK_TXCFG_CONFIG | RTK_LOOPTEST_ON);
+ RE_TXCFG_CONFIG | RTK_LOOPTEST_ON);
else
CSR_WRITE_4(sc, RTK_TXCFG,
- RTK_TXCFG_CONFIG | RTK_LOOPTEST_ON_CPLUS);
+ RE_TXCFG_CONFIG | RTK_LOOPTEST_ON_CPLUS);
} else
- CSR_WRITE_4(sc, RTK_TXCFG, RTK_TXCFG_CONFIG);
- CSR_WRITE_4(sc, RTK_RXCFG, RTK_RXCFG_CONFIG);
+ CSR_WRITE_4(sc, RTK_TXCFG, RE_TXCFG_CONFIG);
+
+ CSR_WRITE_1(sc, RTK_EARLY_TX_THRESH, 16);
+
+ CSR_WRITE_4(sc, RTK_RXCFG, RE_RXCFG_CONFIG);
/* Set the individual bit to receive frames for this host only. */
rxcfg = CSR_READ_4(sc, RTK_RXCFG);
@@ -1887,7 +1894,7 @@
/*
* Enable interrupts.
*/
- if (sc->rtk_testmode)
+ if (sc->re_testmode)
CSR_WRITE_2(sc, RTK_IMR, 0);
else
CSR_WRITE_2(sc, RTK_IMR, RTK_INTRS_CPLUS);
@@ -1898,21 +1905,6 @@
/* Enable receiver and transmitter. */
CSR_WRITE_1(sc, RTK_COMMAND, RTK_CMD_TX_ENB | RTK_CMD_RX_ENB);
#endif
- /*
- * Load the addresses of the RX and TX lists into the chip.
- */
-
- CSR_WRITE_4(sc, RTK_RXLIST_ADDR_HI,
- RTK_ADDR_HI(sc->rtk_ldata.rtk_rx_list_map->dm_segs[0].ds_addr));
- CSR_WRITE_4(sc, RTK_RXLIST_ADDR_LO,
- RTK_ADDR_LO(sc->rtk_ldata.rtk_rx_list_map->dm_segs[0].ds_addr));
-
- CSR_WRITE_4(sc, RTK_TXLIST_ADDR_HI,
- RTK_ADDR_HI(sc->rtk_ldata.rtk_tx_list_map->dm_segs[0].ds_addr));
- CSR_WRITE_4(sc, RTK_TXLIST_ADDR_LO,
- RTK_ADDR_LO(sc->rtk_ldata.rtk_tx_list_map->dm_segs[0].ds_addr));
-
- CSR_WRITE_1(sc, RTK_EARLY_TX_THRESH, 16);
/*
* Initialize the timer interrupt register so that
@@ -1934,19 +1926,17 @@
if (sc->rtk_type == RTK_8169)
CSR_WRITE_2(sc, RTK_MAXRXPKTLEN, 16383);
- if (sc->rtk_testmode)
+ if (sc->re_testmode)
return 0;
- mii_mediachg(&sc->mii);
-
- CSR_WRITE_1(sc, RTK_CFG1, RTK_CFG1_DRVLOAD | RTK_CFG1_FULLDUPLEX);
+ CSR_WRITE_1(sc, RTK_CFG1, RTK_CFG1_DRVLOAD);
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
callout_reset(&sc->rtk_tick_ch, hz, re_tick, sc);
-out:
+ out:
if (error) {
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
ifp->if_timer = 0;
@@ -1955,7 +1945,6 @@
}
return error;
-
}
/*
@@ -1984,8 +1973,6 @@
mii_pollstat(&sc->mii);
ifmr->ifm_active = sc->mii.mii_media_active;
ifmr->ifm_status = sc->mii.mii_media_status;
-
- return;
}
static int
@@ -1999,7 +1986,7 @@
switch (command) {
case SIOCSIFMTU:
- if (ifr->ifr_mtu > RTK_JUMBO_MTU)
+ if (ifr->ifr_mtu > RE_JUMBO_MTU)
error = EINVAL;
ifp->if_mtu = ifr->ifr_mtu;
break;
@@ -2048,7 +2035,7 @@
static void
re_stop(struct ifnet *ifp, int disable)
{
- register int i;
+ int i;
struct rtk_softc *sc = ifp->if_softc;
callout_stop(&sc->rtk_tick_ch);
@@ -2062,28 +2049,28 @@
CSR_WRITE_1(sc, RTK_COMMAND, 0x00);
CSR_WRITE_2(sc, RTK_IMR, 0x0000);
- if (sc->rtk_head != NULL) {
- m_freem(sc->rtk_head);
- sc->rtk_head = sc->rtk_tail = NULL;
+ if (sc->re_head != NULL) {
+ m_freem(sc->re_head);
+ sc->re_head = sc->re_tail = NULL;
}
/* Free the TX list buffers. */
- for (i = 0; i < RTK_TX_QLEN; i++) {
- if (sc->rtk_ldata.rtk_txq[i].txq_mbuf != NULL) {
+ for (i = 0; i < RE_TX_QLEN; i++) {
+ if (sc->re_ldata.re_txq[i].txq_mbuf != NULL) {
bus_dmamap_unload(sc->sc_dmat,
- sc->rtk_ldata.rtk_txq[i].txq_dmamap);
- m_freem(sc->rtk_ldata.rtk_txq[i].txq_mbuf);
- sc->rtk_ldata.rtk_txq[i].txq_mbuf = NULL;
+ sc->re_ldata.re_txq[i].txq_dmamap);
+ m_freem(sc->re_ldata.re_txq[i].txq_mbuf);
+ sc->re_ldata.re_txq[i].txq_mbuf = NULL;
}
}
/* Free the RX list buffers. */
- for (i = 0; i < RTK_RX_DESC_CNT; i++) {
- if (sc->rtk_ldata.rtk_rx_mbuf[i] != NULL) {
+ for (i = 0; i < RE_RX_DESC_CNT; i++) {
+ if (sc->re_ldata.re_rxsoft[i].rxs_mbuf != NULL) {
bus_dmamap_unload(sc->sc_dmat,
- sc->rtk_ldata.rtk_rx_dmamap[i]);
- m_freem(sc->rtk_ldata.rtk_rx_mbuf[i]);
- sc->rtk_ldata.rtk_rx_mbuf[i] = NULL;
+ sc->re_ldata.re_rxsoft[i].rxs_dmamap);
+ m_freem(sc->re_ldata.re_rxsoft[i].rxs_mbuf);
+ sc->re_ldata.re_rxsoft[i].rxs_mbuf = NULL;
}
}
@@ -2092,6 +2079,4 @@
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
ifp->if_timer = 0;
-
- return;
}
Index: dev/ic/rtl81x9.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/rtl81x9.c,v
retrieving revision 1.51
diff -u -r1.51 rtl81x9.c
--- dev/ic/rtl81x9.c 27 Feb 2005 00:27:02 -0000 1.51
+++ dev/ic/rtl81x9.c 11 Feb 2007 03:42:01 -0000
@@ -131,13 +131,13 @@
#define STATIC static
#endif
-STATIC void rtk_reset (struct rtk_softc *);
-STATIC void rtk_rxeof (struct rtk_softc *);
-STATIC void rtk_txeof (struct rtk_softc *);
-STATIC void rtk_start (struct ifnet *);
-STATIC int rtk_ioctl (struct ifnet *, u_long, caddr_t);
-STATIC int rtk_init (struct ifnet *);
-STATIC void rtk_stop (struct ifnet *, int);
+STATIC void rtk_reset(struct rtk_softc *);
+STATIC void rtk_rxeof(struct rtk_softc *);
+STATIC void rtk_txeof(struct rtk_softc *);
+STATIC void rtk_start(struct ifnet *);
+STATIC int rtk_ioctl(struct ifnet *, u_long, caddr_t);
+STATIC int rtk_init(struct ifnet *);
+STATIC void rtk_stop(struct ifnet *, int);
STATIC void rtk_watchdog(struct ifnet *);
STATIC void rtk_shutdown(void *);
@@ -146,18 +146,18 @@
STATIC void rtk_eeprom_putbyte(struct rtk_softc *, int, int);
STATIC void rtk_mii_sync(struct rtk_softc *);
-STATIC void rtk_mii_send(struct rtk_softc *, u_int32_t, int);
+STATIC void rtk_mii_send(struct rtk_softc *, uint32_t, int);
STATIC int rtk_mii_readreg(struct rtk_softc *, struct rtk_mii_frame *);
STATIC int rtk_mii_writereg(struct rtk_softc *, struct rtk_mii_frame *);
STATIC int rtk_phy_readreg(struct device *, int, int);
STATIC void rtk_phy_writereg(struct device *, int, int, int);
STATIC void rtk_phy_statchg(struct device *);
-STATIC void rtk_tick (void *);
+STATIC void rtk_tick(void *);
-STATIC int rtk_enable (struct rtk_softc *);
-STATIC void rtk_disable (struct rtk_softc *);
-STATIC void rtk_power (int, void *);
+STATIC int rtk_enable(struct rtk_softc *);
+STATIC void rtk_disable(struct rtk_softc *);
+STATIC void rtk_power(int, void *);
STATIC int rtk_list_tx_init(struct rtk_softc *);
@@ -169,17 +169,17 @@
CSR_WRITE_1(sc, RTK_EECMD, \
CSR_READ_1(sc, RTK_EECMD) & ~(x))
+#define EE_DELAY() DELAY(100)
+
#define ETHER_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN)
/*
* Send a read command and address to the EEPROM, check for ACK.
*/
STATIC void
-rtk_eeprom_putbyte(sc, addr, addr_len)
- struct rtk_softc *sc;
- int addr, addr_len;
+rtk_eeprom_putbyte(struct rtk_softc *sc, int addr, int addr_len)
{
- int d, i;
+ int d, i;
d = (RTK_EECMD_READ << addr_len) | addr;
@@ -192,51 +192,50 @@
} else {
EE_CLR(RTK_EE_DATAIN);
}
- DELAY(4);
+ EE_DELAY();
EE_SET(RTK_EE_CLK);
- DELAY(4);
+ EE_DELAY();
EE_CLR(RTK_EE_CLK);
- DELAY(4);
+ EE_DELAY();
}
}
/*
* Read a word of data stored in the EEPROM at address 'addr.'
*/
-u_int16_t
-rtk_read_eeprom(sc, addr, addr_len)
- struct rtk_softc *sc;
- int addr, addr_len;
+uint16_t
+rtk_read_eeprom(struct rtk_softc *sc, int addr, int addr_len)
{
- u_int16_t word = 0;
- int i;
+ uint16_t word;
+ int i;
/* Enter EEPROM access mode. */
- CSR_WRITE_1(sc, RTK_EECMD, RTK_EEMODE_PROGRAM|RTK_EE_SEL);
+ CSR_WRITE_1(sc, RTK_EECMD, RTK_EEMODE_PROGRAM);
+ EE_DELAY();
+ EE_SET(RTK_EE_SEL);
/*
* Send address of word we want to read.
*/
rtk_eeprom_putbyte(sc, addr, addr_len);
- CSR_WRITE_1(sc, RTK_EECMD, RTK_EEMODE_PROGRAM|RTK_EE_SEL);
-
/*
* Start reading bits from EEPROM.
*/
+ word = 0;
for (i = 16; i > 0; i--) {
EE_SET(RTK_EE_CLK);
- DELAY(4);
+ EE_DELAY();
if (CSR_READ_1(sc, RTK_EECMD) & RTK_EE_DATAOUT)
word |= 1 << (i - 1);
EE_CLR(RTK_EE_CLK);
- DELAY(4);
+ EE_DELAY();
}
/* Turn off EEPROM access mode. */
CSR_WRITE_1(sc, RTK_EECMD, RTK_EEMODE_OFF);
- return (word);
+ return word;
}
/*
@@ -257,10 +256,9 @@
* Sync the PHYs by setting data bit and strobing the clock 32 times.
*/
STATIC void
-rtk_mii_sync(sc)
- struct rtk_softc *sc;
+rtk_mii_sync(struct rtk_softc *sc)
{
- int i;
+ int i;
MII_SET(RTK_MII_DIR|RTK_MII_DATAOUT);
@@ -276,21 +274,18 @@
* Clock a series of bits through the MII.
*/
STATIC void
-rtk_mii_send(sc, bits, cnt)
- struct rtk_softc *sc;
- u_int32_t bits;
- int cnt;
+rtk_mii_send(struct rtk_softc *sc, uint32_t bits, int cnt)
{
- int i;
+ int i;
MII_CLR(RTK_MII_CLK);
for (i = cnt; i > 0; i--) {
- if (bits & (1 << (i - 1))) {
+ if (bits & (1 << (i - 1))) {
MII_SET(RTK_MII_DATAOUT);
- } else {
+ } else {
MII_CLR(RTK_MII_DATAOUT);
- }
+ }
DELAY(1);
MII_CLR(RTK_MII_CLK);
DELAY(1);
@@ -302,11 +297,9 @@
* Read an PHY register through the MII.
*/
STATIC int
-rtk_mii_readreg(sc, frame)
- struct rtk_softc *sc;
- struct rtk_mii_frame *frame;
+rtk_mii_readreg(struct rtk_softc *sc, struct rtk_mii_frame *frame)
{
- int i, ack, s;
+ int i, ack, s;
s = splnet();
@@ -321,7 +314,7 @@
CSR_WRITE_2(sc, RTK_MII, 0);
/*
- * Turn on data xmit.
+ * Turn on data xmit.
*/
MII_SET(RTK_MII_DIR);
@@ -347,9 +340,9 @@
/* Check for ack */
MII_CLR(RTK_MII_CLK);
DELAY(1);
+ ack = CSR_READ_2(sc, RTK_MII) & RTK_MII_DATAIN;
MII_SET(RTK_MII_CLK);
DELAY(1);
- ack = CSR_READ_2(sc, RTK_MII) & RTK_MII_DATAIN;
/*
* Now try reading data bits. If the ack failed, we still
@@ -386,19 +379,17 @@
splx(s);
if (ack)
- return (1);
- return (0);
+ return 1;
+ return 0;
}
/*
* Write to a PHY register through the MII.
*/
STATIC int
-rtk_mii_writereg(sc, frame)
- struct rtk_softc *sc;
- struct rtk_mii_frame *frame;
+rtk_mii_writereg(struct rtk_softc *sc, struct rtk_mii_frame *frame)
{
- int s;
+ int s;
s = splnet();
/*
@@ -409,7 +400,7 @@
frame->mii_turnaround = RTK_MII_TURNAROUND;
/*
- * Turn on data output.
+ * Turn on data output.
*/
MII_SET(RTK_MII_DIR);
@@ -435,24 +426,22 @@
splx(s);
- return (0);
+ return 0;
}
STATIC int
-rtk_phy_readreg(self, phy, reg)
- struct device *self;
- int phy, reg;
-{
- struct rtk_softc *sc = (void *)self;
- struct rtk_mii_frame frame;
- int rval = 0;
- int rtk8139_reg = 0;
+rtk_phy_readreg(struct device *self, int phy, int reg)
+{
+ struct rtk_softc *sc = (void *)self;
+ struct rtk_mii_frame frame;
+ int rval;
+ int rtk8139_reg;
if (sc->rtk_type == RTK_8139) {
if (phy != 7)
- return (0);
+ return 0;
- switch(reg) {
+ switch (reg) {
case MII_BMCR:
rtk8139_reg = RTK_BMCR;
break;
@@ -472,10 +461,10 @@
#if 0
printf("%s: bad phy register\n", sc->sc_dev.dv_xname);
#endif
- return (0);
+ return 0;
}
rval = CSR_READ_2(sc, rtk8139_reg);
- return (rval);
+ return rval;
}
memset((char *)&frame, 0, sizeof(frame));
@@ -484,23 +473,20 @@
frame.mii_regaddr = reg;
rtk_mii_readreg(sc, &frame);
- return (frame.mii_data);
+ return frame.mii_data;
}
-STATIC void rtk_phy_writereg(self, phy, reg, data)
- struct device *self;
- int phy, reg;
- int data;
+STATIC void rtk_phy_writereg(struct device *self, int phy, int reg, int data)
{
- struct rtk_softc *sc = (void *)self;
- struct rtk_mii_frame frame;
- int rtk8139_reg = 0;
+ struct rtk_softc *sc = (void *)self;
+ struct rtk_mii_frame frame;
+ int rtk8139_reg;
if (sc->rtk_type == RTK_8139) {
if (phy != 7)
return;
- switch(reg) {
+ switch (reg) {
case MII_BMCR:
rtk8139_reg = RTK_BMCR;
break;
@@ -536,8 +522,7 @@
}
STATIC void
-rtk_phy_statchg(v)
- struct device *v;
+rtk_phy_statchg(struct device *v)
{
/* Nothing to do. */
@@ -550,23 +535,21 @@
* Program the 64-bit multicast hash filter.
*/
void
-rtk_setmulti(sc)
- struct rtk_softc *sc;
+rtk_setmulti(struct rtk_softc *sc)
{
- struct ifnet *ifp;
- int h = 0;
- u_int32_t hashes[2] = { 0, 0 };
- u_int32_t rxfilt;
- int mcnt = 0;
+ struct ifnet *ifp;
+ uint32_t hashes[2] = { 0, 0 };
+ uint32_t rxfilt, hwrev;
struct ether_multi *enm;
struct ether_multistep step;
+ int h, mcnt;
ifp = &sc->ethercom.ec_if;
rxfilt = CSR_READ_4(sc, RTK_RXCFG);
if (ifp->if_flags & IFF_PROMISC) {
-allmulti:
+ allmulti:
ifp->if_flags |= IFF_ALLMULTI;
rxfilt |= RTK_RXCFG_RX_MULTI;
CSR_WRITE_4(sc, RTK_RXCFG, rxfilt);
@@ -581,6 +564,7 @@
/* now program new ones */
ETHER_FIRST_MULTI(step, &sc->ethercom, enm);
+ mcnt = 0;
while (enm != NULL) {
if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
ETHER_ADDR_LEN) != 0)
@@ -603,15 +587,28 @@
rxfilt &= ~RTK_RXCFG_RX_MULTI;
CSR_WRITE_4(sc, RTK_RXCFG, rxfilt);
- CSR_WRITE_4(sc, RTK_MAR0, hashes[0]);
- CSR_WRITE_4(sc, RTK_MAR4, hashes[1]);
+
+ /*
+ * For some unfathomable reason, RealTek decided to reverse
+ * the order of the multicast hash registers in the PCI Express
+ * parts. This means we have to write the hash pattern in reverse
+ * order for those devices.
+ */
+ hwrev = CSR_READ_4(sc, RTK_TXCFG) & RTK_TXCFG_HWREV;
+ if (hwrev == RTK_HWREV_8100E || hwrev == RTK_HWREV_8101E ||
+ hwrev == RTK_HWREV_8168_SPIN1 || hwrev == RTK_HWREV_8168_SPIN2) {
+ CSR_WRITE_4(sc, RTK_MAR0, bswap32(hashes[1]));
+ CSR_WRITE_4(sc, RTK_MAR4, bswap32(hashes[0]));
+ } else {
+ CSR_WRITE_4(sc, RTK_MAR0, hashes[0]);
+ CSR_WRITE_4(sc, RTK_MAR4, hashes[1]);
+ }
}
void
-rtk_reset(sc)
- struct rtk_softc *sc;
+rtk_reset(struct rtk_softc *sc)
{
- int i;
+ int i;
CSR_WRITE_1(sc, RTK_COMMAND, RTK_CMD_RESET);
@@ -629,13 +626,12 @@
* setup and ethernet/BPF attach.
*/
void
-rtk_attach(sc)
- struct rtk_softc *sc;
+rtk_attach(struct rtk_softc *sc)
{
struct ifnet *ifp;
struct rtk_tx_desc *txd;
- u_int16_t val;
- u_int8_t eaddr[ETHER_ADDR_LEN];
+ uint16_t val;
+ uint8_t eaddr[ETHER_ADDR_LEN];
int error;
int i, addr_len;
@@ -666,7 +662,7 @@
RTK_RXBUFLEN + 16, PAGE_SIZE, 0, &sc->sc_dmaseg, 1, &sc->sc_dmanseg,
BUS_DMA_NOWAIT)) != 0) {
printf("%s: can't allocate recv buffer, error = %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_dev.dv_xname, error);
goto fail_0;
}
@@ -674,7 +670,7 @@
RTK_RXBUFLEN + 16, (caddr_t *)&sc->rtk_rx_buf,
BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
printf("%s: can't map recv buffer, error = %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_dev.dv_xname, error);
goto fail_1;
}
@@ -682,7 +678,7 @@
RTK_RXBUFLEN + 16, 1, RTK_RXBUFLEN + 16, 0, BUS_DMA_NOWAIT,
&sc->recv_dmamap)) != 0) {
printf("%s: can't create recv buffer DMA map, error = %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_dev.dv_xname, error);
goto fail_2;
}
@@ -690,7 +686,7 @@
sc->rtk_rx_buf, RTK_RXBUFLEN + 16,
NULL, BUS_DMA_READ|BUS_DMA_NOWAIT)) != 0) {
printf("%s: can't load recv buffer DMA map, error = %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_dev.dv_xname, error);
goto fail_3;
}
@@ -716,9 +712,6 @@
*/
sc->sc_flags |= RTK_ATTACHED;
- /* Init Early TX threshold. */
- sc->sc_txthresh = TXTH_256;
-
/* Reset the adapter. */
rtk_reset(sc);
@@ -743,7 +736,8 @@
sc->mii.mii_readreg = rtk_phy_readreg;
sc->mii.mii_writereg = rtk_phy_writereg;
sc->mii.mii_statchg = rtk_phy_statchg;
- ifmedia_init(&sc->mii.mii_media, IFM_IMASK, rtk_ifmedia_upd, rtk_ifmedia_sts);
+ ifmedia_init(&sc->mii.mii_media, IFM_IMASK, rtk_ifmedia_upd,
+ rtk_ifmedia_sts);
mii_attach(&sc->sc_dev, &sc->mii, 0xffffffff,
MII_PHY_ANY, MII_OFFSET_ANY, 0);
@@ -805,8 +799,7 @@
* Initialize the transmit descriptors.
*/
STATIC int
-rtk_list_tx_init(sc)
- struct rtk_softc *sc;
+rtk_list_tx_init(struct rtk_softc *sc)
{
struct rtk_tx_desc *txd;
int i;
@@ -822,7 +815,7 @@
SIMPLEQ_INSERT_TAIL(&sc->rtk_tx_free, txd, txd_q);
}
- return (0);
+ return 0;
}
/*
@@ -830,13 +823,12 @@
* Handle device activation/deactivation requests.
*/
int
-rtk_activate(self, act)
- struct device *self;
- enum devact act;
+rtk_activate(struct device *self, enum devact act)
{
- struct rtk_softc *sc = (void *) self;
- int s, error = 0;
+ struct rtk_softc *sc = (void *)self;
+ int s, error;
+ error = 0;
s = splnet();
switch (act) {
case DVACT_ACTIVATE:
@@ -849,7 +841,7 @@
}
splx(s);
- return (error);
+ return error;
}
/*
@@ -857,8 +849,7 @@
* Detach a rtk interface.
*/
int
-rtk_detach(sc)
- struct rtk_softc *sc;
+rtk_detach(struct rtk_softc *sc)
{
struct ifnet *ifp = &sc->ethercom.ec_if;
struct rtk_tx_desc *txd;
@@ -868,7 +859,7 @@
* Succeed now if there isn't any work to do.
*/
if ((sc->sc_flags & RTK_ATTACHED) == 0)
- return (0);
+ return 0;
/* Unhook our tick handler. */
callout_stop(&sc->rtk_tick_ch);
@@ -899,7 +890,7 @@
shutdownhook_disestablish(sc->sc_sdhook);
powerhook_disestablish(sc->sc_powerhook);
- return (0);
+ return 0;
}
/*
@@ -907,19 +898,18 @@
* Enable the RTL81X9 chip.
*/
int
-rtk_enable(sc)
- struct rtk_softc *sc;
+rtk_enable(struct rtk_softc *sc)
{
if (RTK_IS_ENABLED(sc) == 0 && sc->sc_enable != NULL) {
if ((*sc->sc_enable)(sc) != 0) {
printf("%s: device enable failed\n",
sc->sc_dev.dv_xname);
- return (EIO);
+ return EIO;
}
sc->sc_flags |= RTK_ENABLED;
}
- return (0);
+ return 0;
}
/*
@@ -927,8 +917,7 @@
* Disable the RTL81X9 chip.
*/
void
-rtk_disable(sc)
- struct rtk_softc *sc;
+rtk_disable(struct rtk_softc *sc)
{
if (RTK_IS_ENABLED(sc) && sc->sc_disable != NULL) {
@@ -942,11 +931,9 @@
* Power management (suspend/resume) hook.
*/
void
-rtk_power(why, arg)
- int why;
- void *arg;
+rtk_power(int why, void *arg)
{
- struct rtk_softc *sc = (void *) arg;
+ struct rtk_softc *sc = (void *)arg;
struct ifnet *ifp = &sc->ethercom.ec_if;
int s;
@@ -994,17 +981,16 @@
* shifted forward 2 bytes.
*/
STATIC void
-rtk_rxeof(sc)
- struct rtk_softc *sc;
+rtk_rxeof(struct rtk_softc *sc)
{
- struct mbuf *m;
- struct ifnet *ifp;
- caddr_t rxbufpos, dst;
- u_int total_len, wrap = 0;
- u_int32_t rxstat;
- u_int16_t cur_rx, new_rx;
- u_int16_t limit;
- u_int16_t rx_bytes = 0, max_bytes;
+ struct mbuf *m;
+ struct ifnet *ifp;
+ caddr_t rxbufpos, dst;
+ u_int total_len, wrap;
+ uint32_t rxstat;
+ uint16_t cur_rx, new_rx;
+ uint16_t limit;
+ uint16_t rx_bytes, max_bytes;
ifp = &sc->ethercom.ec_if;
@@ -1017,12 +1003,13 @@
max_bytes = (RTK_RXBUFLEN - cur_rx) + limit;
else
max_bytes = limit - cur_rx;
+ rx_bytes = 0;
- while((CSR_READ_1(sc, RTK_COMMAND) & RTK_CMD_EMPTY_RXBUF) == 0) {
+ while ((CSR_READ_1(sc, RTK_COMMAND) & RTK_CMD_EMPTY_RXBUF) == 0) {
rxbufpos = sc->rtk_rx_buf + cur_rx;
bus_dmamap_sync(sc->sc_dmat, sc->recv_dmamap, cur_rx,
RTK_RXSTAT_LEN, BUS_DMASYNC_POSTREAD);
- rxstat = le32toh(*(u_int32_t *)rxbufpos);
+ rxstat = le32toh(*(uint32_t *)rxbufpos);
bus_dmamap_sync(sc->sc_dmat, sc->recv_dmamap, cur_rx,
RTK_RXSTAT_LEN, BUS_DMASYNC_PREREAD);
@@ -1039,7 +1026,8 @@
break;
if ((rxstat & RTK_RXSTAT_RXOK) == 0 ||
- total_len > ETHER_MAX_LEN) {
+ total_len < ETHER_MIN_LEN ||
+ total_len > (MCLBYTES - RTK_ETHER_ALIGN)) {
ifp->if_ierrors++;
/*
@@ -1099,7 +1087,13 @@
else
new_rx = cur_rx + total_len;
/* Round up to 32-bit boundary. */
- new_rx = (new_rx + 3) & ~3;
+ new_rx = ((new_rx + 3) & ~3) % RTK_RXBUFLEN;
+
+ /*
+ * The RealTek chip includes the CRC with every
+ * incoming packet; trim it off here.
+ */
+ total_len -= ETHER_CRC_LEN;
/*
* Now allocate an mbuf (and possibly a cluster) to hold
@@ -1154,18 +1148,12 @@
cur_rx, total_len, BUS_DMASYNC_PREREAD);
next_packet:
- CSR_WRITE_2(sc, RTK_CURRXADDR, new_rx - 16);
+ CSR_WRITE_2(sc, RTK_CURRXADDR, (new_rx - 16) % RTK_RXBUFLEN);
cur_rx = new_rx;
if (m == NULL)
continue;
- /*
- * The RealTek chip includes the CRC with every
- * incoming packet.
- */
- m->m_flags |= M_HASFCS;
-
ifp->if_ipackets++;
#if NBPFILTER > 0
@@ -1182,18 +1170,14 @@
* the list buffers.
*/
STATIC void
-rtk_txeof(sc)
- struct rtk_softc *sc;
+rtk_txeof(struct rtk_softc *sc)
{
struct ifnet *ifp;
struct rtk_tx_desc *txd;
- u_int32_t txstat;
+ uint32_t txstat;
ifp = &sc->ethercom.ec_if;
- /* Clear the timeout timer. */
- ifp->if_timer = 0;
-
/*
* Go through our tx list and free mbufs for those
* frames that have been uploaded.
@@ -1224,12 +1208,16 @@
* Increase step 64 bytes.
*/
if (txstat & RTK_TXSTAT_TX_UNDERRUN) {
+#ifdef DEBUG
printf("%s: transmit underrun;",
sc->sc_dev.dv_xname);
- if (sc->sc_txthresh < TXTH_MAX) {
+#endif
+ if (sc->sc_txthresh < RTK_TXTH_MAX) {
sc->sc_txthresh += 2;
+#ifdef DEBUG
printf(" new threshold: %d bytes",
sc->sc_txthresh * 32);
+#endif
}
printf("\n");
}
@@ -1239,16 +1227,20 @@
SIMPLEQ_INSERT_TAIL(&sc->rtk_tx_free, txd, txd_q);
ifp->if_flags &= ~IFF_OACTIVE;
}
+
+ /* Clear the timeout timer if there is no pending packet. */
+ if (SIMPLEQ_EMPTY(&sc->rtk_tx_dirty))
+ ifp->if_timer = 0;
+
}
int
-rtk_intr(arg)
- void *arg;
+rtk_intr(void *arg)
{
- struct rtk_softc *sc;
- struct ifnet *ifp;
- u_int16_t status;
- int handled = 0;
+ struct rtk_softc *sc;
+ struct ifnet *ifp;
+ uint16_t status;
+ int handled;
sc = arg;
ifp = &sc->ethercom.ec_if;
@@ -1256,17 +1248,18 @@
/* Disable interrupts. */
CSR_WRITE_2(sc, RTK_IMR, 0x0000);
+ handled = 0;
for (;;) {
status = CSR_READ_2(sc, RTK_ISR);
if (status)
CSR_WRITE_2(sc, RTK_ISR, status);
- handled = 1;
-
if ((status & RTK_INTRS) == 0)
break;
+ handled = 1;
+
if (status & RTK_ISR_RX_OK)
rtk_rxeof(sc);
@@ -1293,7 +1286,7 @@
rnd_add_uint32(&sc->rnd_source, status);
#endif
- return (handled);
+ return handled;
}
/*
@@ -1301,12 +1294,11 @@
*/
STATIC void
-rtk_start(ifp)
- struct ifnet *ifp;
+rtk_start(struct ifnet *ifp)
{
struct rtk_softc *sc;
struct rtk_tx_desc *txd;
- struct mbuf *m_head = NULL, *m_new;
+ struct mbuf *m_head, *m_new;
int error, len;
sc = ifp->if_softc;
@@ -1383,7 +1375,7 @@
/*
* Transmit the frame.
- */
+ */
bus_dmamap_sync(sc->sc_dmat,
txd->txd_dmamap, 0, txd->txd_dmamap->dm_mapsize,
BUS_DMASYNC_PREWRITE);
@@ -1392,7 +1384,13 @@
CSR_WRITE_4(sc, txd->txd_txaddr,
txd->txd_dmamap->dm_segs[0].ds_addr);
- CSR_WRITE_4(sc, txd->txd_txstat, RTK_TX_THRESH(sc) | len);
+ CSR_WRITE_4(sc, txd->txd_txstat,
+ RTK_TXSTAT_THRESH(sc->sc_txthresh) | len);
+
+ /*
+ * Set a timeout in case the chip goes out to lunch.
+ */
+ ifp->if_timer = 5;
}
/*
@@ -1402,20 +1400,14 @@
*/
if (SIMPLEQ_EMPTY(&sc->rtk_tx_free))
ifp->if_flags |= IFF_OACTIVE;
-
- /*
- * Set a timeout in case the chip goes out to lunch.
- */
- ifp->if_timer = 5;
}
STATIC int
-rtk_init(ifp)
- struct ifnet *ifp;
+rtk_init(struct ifnet *ifp)
{
- struct rtk_softc *sc = ifp->if_softc;
- int error = 0, i;
- u_int32_t rxcfg;
+ struct rtk_softc *sc = ifp->if_softc;
+ int error, i;
+ uint32_t rxcfg;
if ((error = rtk_enable(sc)) != 0)
goto out;
@@ -1439,7 +1431,7 @@
rtk_list_tx_init(sc);
/* Init Early TX threshold. */
- sc->sc_txthresh = TXTH_256;
+ sc->sc_txthresh = RTK_TXTH_256;
/*
* Enable transmit and receive.
*/
@@ -1509,32 +1501,29 @@
ifp->if_timer = 0;
printf("%s: interface not running\n", sc->sc_dev.dv_xname);
}
- return (error);
+ return error;
}
/*
* Set media options.
*/
STATIC int
-rtk_ifmedia_upd(ifp)
- struct ifnet *ifp;
+rtk_ifmedia_upd(struct ifnet *ifp)
{
- struct rtk_softc *sc;
+ struct rtk_softc *sc;
sc = ifp->if_softc;
- return (mii_mediachg(&sc->mii));
+ return mii_mediachg(&sc->mii);
}
/*
* Report current media status.
*/
STATIC void
-rtk_ifmedia_sts(ifp, ifmr)
- struct ifnet *ifp;
- struct ifmediareq *ifmr;
+rtk_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
- struct rtk_softc *sc;
+ struct rtk_softc *sc;
sc = ifp->if_softc;
@@ -1544,14 +1533,11 @@
}
STATIC int
-rtk_ioctl(ifp, command, data)
- struct ifnet *ifp;
- u_long command;
- caddr_t data;
-{
- struct rtk_softc *sc = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *) data;
- int s, error = 0;
+rtk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct rtk_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int s, error;
s = splnet();
@@ -1578,14 +1564,13 @@
splx(s);
- return (error);
+ return error;
}
STATIC void
-rtk_watchdog(ifp)
- struct ifnet *ifp;
+rtk_watchdog(struct ifnet *ifp)
{
- struct rtk_softc *sc;
+ struct rtk_softc *sc;
sc = ifp->if_softc;
@@ -1601,9 +1586,7 @@
* RX and TX lists.
*/
STATIC void
-rtk_stop(ifp, disable)
- struct ifnet *ifp;
- int disable;
+rtk_stop(struct ifnet *ifp, int disable)
{
struct rtk_softc *sc = ifp->if_softc;
struct rtk_tx_desc *txd;
@@ -1638,21 +1621,20 @@
* get confused by errant DMAs when rebooting.
*/
STATIC void
-rtk_shutdown(vsc)
- void *vsc;
+rtk_shutdown(void *arg)
{
- struct rtk_softc *sc = (struct rtk_softc *)vsc;
+ struct rtk_softc *sc = (struct rtk_softc *)arg;
rtk_stop(&sc->ethercom.ec_if, 0);
}
STATIC void
-rtk_tick(arg)
- void *arg;
+rtk_tick(void *arg)
{
struct rtk_softc *sc = arg;
- int s = splnet();
+ int s;
+ s = splnet();
mii_tick(&sc->mii);
splx(s);
Index: dev/ic/rtl81x9reg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/rtl81x9reg.h,v
retrieving revision 1.11.2.2
diff -u -r1.11.2.2 rtl81x9reg.h
--- dev/ic/rtl81x9reg.h 29 Dec 2005 19:44:18 -0000 1.11.2.2
+++ dev/ic/rtl81x9reg.h 11 Feb 2007 03:42:01 -0000
@@ -37,7 +37,7 @@
/*
* RealTek 8129/8139 register offsets
*/
-#define RTK_IDR0 0x0000 /* ID register 0 (station addr) */
+#define RTK_IDR0 0x0000 /* ID register 0 (station addr) */
#define RTK_IDR1 0x0001 /* Must use 32-bit accesses (?) */
#define RTK_IDR2 0x0002
#define RTK_IDR3 0x0003
@@ -123,14 +123,17 @@
/*
* Registers specific to the 8169 gigE chip
*/
+#define RTK_GTXSTART 0x0038 /* 16 bits */
#define RTK_TIMERINT_8169 0x0058 /* different offset than 8139 */
#define RTK_PHYAR 0x0060
#define RTK_TBICSR 0x0064
#define RTK_TBI_ANAR 0x0068
#define RTK_TBI_LPAR 0x006A
#define RTK_GMEDIASTAT 0x006C /* 8 bits */
+#define RTK_LDPS 0x0082 /* Link Down Power Saving */
#define RTK_MAXRXPKTLEN 0x00DA /* 16 bits, chip multiplies by 8 */
-#define RTK_GTXSTART 0x0038 /* 16 bits */
+#define RTK_IM 0x00E2
+
/*
* TX config register bits
*/
@@ -146,10 +149,17 @@
#define RTK_LOOPTEST_ON 0x00020000
#define RTK_LOOPTEST_ON_CPLUS 0x00060000
+/* Known revision codes. */
#define RTK_HWREV_8169 0x00000000
-#define RTK_HWREV_8169S 0x04000000
-#define RTK_HWREV_8169SB 0x10000000
#define RTK_HWREV_8110S 0x00800000
+#define RTK_HWREV_8169S 0x04000000
+#define RTK_HWREV_8169_8110SB 0x10000000
+#define RTK_HWREV_8169_8110SC 0x18000000
+#define RTK_HWREV_8168_SPIN1 0x30000000
+#define RTK_HWREV_8100E 0x30800000
+#define RTK_HWREV_8101E 0x34000000
+#define RTK_HWREV_8168_SPIN2 0x38000000
+#define RTK_HWREV_8100E_SPIN2 0x38800000
#define RTK_HWREV_8139 0x60000000
#define RTK_HWREV_8139A 0x70000000
#define RTK_HWREV_8139AG 0x70800000
@@ -184,6 +194,10 @@
#define RTK_TXSTAT_TXABRT 0x40000000
#define RTK_TXSTAT_CARRLOSS 0x80000000
+#define RTK_TXSTAT_THRESH(x) (((x) << 16) & RTK_TXSTAT_EARLY_THRESH)
+#define RTK_TXTH_256 8 /* (x) * 32 bytes */
+#define RTK_TXTH_1536 48
+
/*
* Interrupt status register bits.
*/
@@ -251,6 +265,7 @@
#define RTK_RXBUF_16 0x00000800
#define RTK_RXBUF_32 0x00001000
#define RTK_RXBUF_64 0x00001800
+#define RTK_RXBUF_LEN(x) (1 << (((x) >> 11) + 13))
#define RTK_RXFIFO_16BYTES 0x00000000
#define RTK_RXFIFO_32BYTES 0x00002000
@@ -409,28 +424,7 @@
#define RTK_GMEDIASTAT_TXFLOW 0x40 /* TX flow control on */
#define RTK_GMEDIASTAT_TBI 0x80 /* TBI enabled */
-/*
- * The RealTek doesn't use a fragment-based descriptor mechanism.
- * Instead, there are only four register sets, each or which represents
- * one 'descriptor.' Basically, each TX descriptor is just a contiguous
- * packet buffer (32-bit aligned!) and we place the buffer addresses in
- * the registers so the chip knows where they are.
- *
- * We can sort of kludge together the same kind of buffer management
- * used in previous drivers, but we have to do buffer copies almost all
- * the time, so it doesn't really buy us much.
- *
- * For reception, there's just one large buffer where the chip stores
- * all received packets.
- */
-#ifdef dreamcast
-#define RTK_RX_BUF_SZ RTK_RXBUF_16
-#else
-#define RTK_RX_BUF_SZ RTK_RXBUF_64
-#endif
-#define RTK_RXBUFLEN (1 << ((RTK_RX_BUF_SZ >> 11) + 13))
-#define RTK_TX_LIST_CNT 4
#define RTK_TX_EARLYTHRESH ((256 / 32) << 16)
#define RTK_RX_FIFOTHRESH RTK_RXFIFO_256BYTES
#define RTK_RX_MAXDMA RTK_RXDMA_256BYTES
@@ -439,13 +433,12 @@
#define RTK_RXCFG_CONFIG (RTK_RX_FIFOTHRESH|RTK_RX_MAXDMA|RTK_RX_BUF_SZ)
#define RTK_TXCFG_CONFIG (RTK_TXCFG_IFG|RTK_TX_MAXDMA)
+#define RE_RX_FIFOTHRESH RTK_RXFIFO_NOTHRESH
+#define RE_RX_MAXDMA RTK_RXDMA_UNLIMITED
+#define RE_TX_MAXDMA RTK_TXDMA_2048BYTES
-/*
- * The 8139C+ and 8160 gigE chips support descriptor-based TX
- * and RX. In fact, they even support TCP large send. Descriptors
- * must be allocated in contiguous blocks that are aligned on a
- * 256-byte boundary. The rings can hold a maximum of 64 descriptors.
- */
+#define RE_RXCFG_CONFIG (RE_RX_FIFOTHRESH|RE_RX_MAXDMA|RTK_RX_BUF_SZ)
+#define RE_TXCFG_CONFIG (RTK_TXCFG_IFG|RE_TX_MAXDMA)
/*
* RX/TX descriptor definition. When large send mode is enabled, the
@@ -454,117 +447,109 @@
* the same for RX and TX descriptors
*/
-struct rtk_desc {
- u_int32_t rtk_cmdstat;
- u_int32_t rtk_vlanctl;
- u_int32_t rtk_bufaddr_lo;
- u_int32_t rtk_bufaddr_hi;
+struct re_desc {
+ volatile uint32_t re_cmdstat;
+ volatile uint32_t re_vlanctl;
+ volatile uint32_t re_bufaddr_lo;
+ volatile uint32_t re_bufaddr_hi;
};
-#define RTK_TDESC_CMD_FRAGLEN 0x0000FFFF
-#define RTK_TDESC_CMD_TCPCSUM 0x00010000 /* TCP checksum enable */
-#define RTK_TDESC_CMD_UDPCSUM 0x00020000 /* UDP checksum enable */
-#define RTK_TDESC_CMD_IPCSUM 0x00040000 /* IP header checksum enable */
-#define RTK_TDESC_CMD_MSSVAL 0x07FF0000 /* Large send MSS value */
-#define RTK_TDESC_CMD_MSSVAL_SHIFT 16 /* Shift of the above */
-#define RTK_TDESC_CMD_LGSEND 0x08000000 /* TCP large send enb */
-#define RTK_TDESC_CMD_EOF 0x10000000 /* end of frame marker */
-#define RTK_TDESC_CMD_SOF 0x20000000 /* start of frame marker */
-#define RTK_TDESC_CMD_EOR 0x40000000 /* end of ring marker */
-#define RTK_TDESC_CMD_OWN 0x80000000 /* chip owns descriptor */
+#define RE_TDESC_CMD_FRAGLEN 0x0000FFFF
+#define RE_TDESC_CMD_TCPCSUM 0x00010000 /* TCP checksum enable */
+#define RE_TDESC_CMD_UDPCSUM 0x00020000 /* UDP checksum enable */
+#define RE_TDESC_CMD_IPCSUM 0x00040000 /* IP header checksum enable */
+#define RE_TDESC_CMD_MSSVAL 0x07FF0000 /* Large send MSS value */
+#define RE_TDESC_CMD_MSSVAL_SHIFT 16 /* Shift of the above */
+#define RE_TDESC_CMD_LGSEND 0x08000000 /* TCP large send enb */
+#define RE_TDESC_CMD_EOF 0x10000000 /* end of frame marker */
+#define RE_TDESC_CMD_SOF 0x20000000 /* start of frame marker */
+#define RE_TDESC_CMD_EOR 0x40000000 /* end of ring marker */
+#define RE_TDESC_CMD_OWN 0x80000000 /* chip owns descriptor */
-#define RTK_TDESC_VLANCTL_TAG 0x00020000 /* Insert VLAN tag */
-#define RTK_TDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */
+#define RE_TDESC_VLANCTL_TAG 0x00020000 /* Insert VLAN tag */
+#define RE_TDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */
/*
* Error bits are valid only on the last descriptor of a frame
- * (i.e. RTK_TDESC_CMD_EOF == 1)
+ * (i.e. RE_TDESC_CMD_EOF == 1)
*/
-#define RTK_TDESC_STAT_COLCNT 0x000F0000 /* collision count */
-#define RTK_TDESC_STAT_EXCESSCOL 0x00100000 /* excessive collisions */
-#define RTK_TDESC_STAT_LINKFAIL 0x00200000 /* link faulure */
-#define RTK_TDESC_STAT_OWINCOL 0x00400000 /* out-of-window collision */
-#define RTK_TDESC_STAT_TXERRSUM 0x00800000 /* transmit error summary */
-#define RTK_TDESC_STAT_UNDERRUN 0x02000000 /* TX underrun occurred */
-#define RTK_TDESC_STAT_OWN 0x80000000
+#define RE_TDESC_STAT_COLCNT 0x000F0000 /* collision count */
+#define RE_TDESC_STAT_EXCESSCOL 0x00100000 /* excessive collisions */
+#define RE_TDESC_STAT_LINKFAIL 0x00200000 /* link faulure */
+#define RE_TDESC_STAT_OWINCOL 0x00400000 /* out-of-window collision */
+#define RE_TDESC_STAT_TXERRSUM 0x00800000 /* transmit error summary */
+#define RE_TDESC_STAT_UNDERRUN 0x02000000 /* TX underrun occurred */
+#define RE_TDESC_STAT_OWN 0x80000000
/*
* RX descriptor cmd/vlan definitions
*/
-#define RTK_RDESC_CMD_EOR 0x40000000
-#define RTK_RDESC_CMD_OWN 0x80000000
-#define RTK_RDESC_CMD_BUFLEN 0x00001FFF
-
-#define RTK_RDESC_STAT_OWN 0x80000000
-#define RTK_RDESC_STAT_EOR 0x40000000
-#define RTK_RDESC_STAT_SOF 0x20000000
-#define RTK_RDESC_STAT_EOF 0x10000000
-#define RTK_RDESC_STAT_FRALIGN 0x08000000 /* frame alignment error */
-#define RTK_RDESC_STAT_MCAST 0x04000000 /* multicast pkt received */
-#define RTK_RDESC_STAT_UCAST 0x02000000 /* unicast pkt received */
-#define RTK_RDESC_STAT_BCAST 0x01000000 /* broadcast pkt received */
-#define RTK_RDESC_STAT_BUFOFLOW 0x00800000 /* out of buffer space */
-#define RTK_RDESC_STAT_FIFOOFLOW 0x00400000 /* FIFO overrun */
-#define RTK_RDESC_STAT_GIANT 0x00200000 /* pkt > 4096 bytes */
-#define RTK_RDESC_STAT_RXERRSUM 0x00100000 /* RX error summary */
-#define RTK_RDESC_STAT_RUNT 0x00080000 /* runt packet received */
-#define RTK_RDESC_STAT_CRCERR 0x00040000 /* CRC error */
-#define RTK_RDESC_STAT_PROTOID 0x00030000 /* Protocol type */
-#define RTK_RDESC_STAT_IPSUMBAD 0x00008000 /* IP header checksum bad */
-#define RTK_RDESC_STAT_UDPSUMBAD 0x00004000 /* UDP checksum bad */
-#define RTK_RDESC_STAT_TCPSUMBAD 0x00002000 /* TCP checksum bad */
-#define RTK_RDESC_STAT_FRAGLEN 0x00001FFF /* RX'ed frame/frag len */
-#define RTK_RDESC_STAT_GFRAGLEN 0x00003FFF /* RX'ed frame/frag len */
-
-#define RTK_RDESC_VLANCTL_TAG 0x00010000 /* VLAN tag available
- (rtk_vlandata valid)*/
-#define RTK_RDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */
-
-#define RTK_PROTOID_NONIP 0x00000000
-#define RTK_PROTOID_TCPIP 0x00010000
-#define RTK_PROTOID_UDPIP 0x00020000
-#define RTK_PROTOID_IP 0x00030000
-#define RTK_TCPPKT(x) (((x) & RTK_RDESC_STAT_PROTOID) == \
- RTK_PROTOID_TCPIP)
-#define RTK_UDPPKT(x) (((x) & RTK_RDESC_STAT_PROTOID) == \
- RTK_PROTOID_UDPIP)
+#define RE_RDESC_CMD_EOR 0x40000000
+#define RE_RDESC_CMD_OWN 0x80000000
+#define RE_RDESC_CMD_BUFLEN 0x00001FFF
+
+#define RE_RDESC_STAT_OWN 0x80000000
+#define RE_RDESC_STAT_EOR 0x40000000
+#define RE_RDESC_STAT_SOF 0x20000000
+#define RE_RDESC_STAT_EOF 0x10000000
+#define RE_RDESC_STAT_FRALIGN 0x08000000 /* frame alignment error */
+#define RE_RDESC_STAT_MCAST 0x04000000 /* multicast pkt received */
+#define RE_RDESC_STAT_UCAST 0x02000000 /* unicast pkt received */
+#define RE_RDESC_STAT_BCAST 0x01000000 /* broadcast pkt received */
+#define RE_RDESC_STAT_BUFOFLOW 0x00800000 /* out of buffer space */
+#define RE_RDESC_STAT_FIFOOFLOW 0x00400000 /* FIFO overrun */
+#define RE_RDESC_STAT_GIANT 0x00200000 /* pkt > 4096 bytes */
+#define RE_RDESC_STAT_RXERRSUM 0x00100000 /* RX error summary */
+#define RE_RDESC_STAT_RUNT 0x00080000 /* runt packet received */
+#define RE_RDESC_STAT_CRCERR 0x00040000 /* CRC error */
+#define RE_RDESC_STAT_PROTOID 0x00030000 /* Protocol type */
+#define RE_RDESC_STAT_IPSUMBAD 0x00008000 /* IP header checksum bad */
+#define RE_RDESC_STAT_UDPSUMBAD 0x00004000 /* UDP checksum bad */
+#define RE_RDESC_STAT_TCPSUMBAD 0x00002000 /* TCP checksum bad */
+#define RE_RDESC_STAT_FRAGLEN 0x00001FFF /* RX'ed frame/frag len */
+#define RE_RDESC_STAT_GFRAGLEN 0x00003FFF /* RX'ed frame/frag len */
+
+#define RE_RDESC_VLANCTL_TAG 0x00010000 /* VLAN tag available
+ (re_vlandata valid)*/
+#define RE_RDESC_VLANCTL_DATA 0x0000FFFF /* TAG data */
+
+#define RE_PROTOID_NONIP 0x00000000
+#define RE_PROTOID_TCPIP 0x00010000
+#define RE_PROTOID_UDPIP 0x00020000
+#define RE_PROTOID_IP 0x00030000
+#define RE_TCPPKT(x) (((x) & RE_RDESC_STAT_PROTOID) == \
+ RE_PROTOID_TCPIP)
+#define RE_UDPPKT(x) (((x) & RE_RDESC_STAT_PROTOID) == \
+ RE_PROTOID_UDPIP)
+
+#define RE_ADDR_LO(y) ((uint64_t)(y) & 0xFFFFFFFF)
+#define RE_ADDR_HI(y) ((uint64_t)(y) >> 32)
/*
* Statistics counter structure (8139C+ and 8169 only)
*/
-struct rtk_stats {
- u_int32_t rtk_tx_pkts_lo;
- u_int32_t rtk_tx_pkts_hi;
- u_int32_t rtk_tx_errs_lo;
- u_int32_t rtk_tx_errs_hi;
- u_int32_t rtk_tx_errs;
- u_int16_t rtk_missed_pkts;
- u_int16_t rtk_rx_framealign_errs;
- u_int32_t rtk_tx_onecoll;
- u_int32_t rtk_tx_multicolls;
- u_int32_t rtk_rx_ucasts_hi;
- u_int32_t rtk_rx_ucasts_lo;
- u_int32_t rtk_rx_bcasts_lo;
- u_int32_t rtk_rx_bcasts_hi;
- u_int32_t rtk_rx_mcasts;
- u_int16_t rtk_tx_aborts;
- u_int16_t rtk_rx_underruns;
+struct re_stats {
+ uint32_t re_tx_pkts_lo;
+ uint32_t re_tx_pkts_hi;
+ uint32_t re_tx_errs_lo;
+ uint32_t re_tx_errs_hi;
+ uint32_t re_tx_errs;
+ uint16_t re_missed_pkts;
+ uint16_t re_rx_framealign_errs;
+ uint32_t re_tx_onecoll;
+ uint32_t re_tx_multicolls;
+ uint32_t re_rx_ucasts_hi;
+ uint32_t re_rx_ucasts_lo;
+ uint32_t re_rx_bcasts_lo;
+ uint32_t re_rx_bcasts_hi;
+ uint32_t re_rx_mcasts;
+ uint16_t re_tx_aborts;
+ uint16_t re_rx_underruns;
};
-#define RTK_RX_DESC_CNT 64
-#define RTK_TX_DESC_CNT_8139 64
-#define RTK_TX_DESC_CNT_8169 1024
-#define RTK_RX_LIST_SZ (RTK_RX_DESC_CNT * sizeof(struct rtk_desc))
-#define RTK_RING_ALIGN 256
-#define RTK_IFQ_MAXLEN 512
-#define RTK_OWN(x) (le32toh((x)->rtk_cmdstat) & RTK_RDESC_STAT_OWN)
-#define RTK_RXBYTES(x) (le32toh((x)->rtk_cmdstat) & sc->rtk_rxlenmask)
-#define RTK_PKTSZ(x) ((x)/* >> 3*/)
-
-#define RTK_ADDR_LO(y) ((u_int64_t) (y) & 0xFFFFFFFF)
-#define RTK_ADDR_HI(y) ((u_int64_t) (y) >> 32)
+#define RE_IFQ_MAXLEN 512
-#define RTK_JUMBO_FRAMELEN 9018
-#define RTK_JUMBO_MTU (RTK_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
+#define RE_JUMBO_FRAMELEN 9018
+#define RE_JUMBO_MTU (RE_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
Index: dev/ic/rtl81x9var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/rtl81x9var.h,v
retrieving revision 1.17.4.1
diff -u -r1.17.4.1 rtl81x9var.h
--- dev/ic/rtl81x9var.h 4 Apr 2005 17:23:57 -0000 1.17.4.1
+++ dev/ic/rtl81x9var.h 11 Feb 2007 03:42:01 -0000
@@ -43,9 +43,20 @@
#define RTK_ETHER_ALIGN 2
#define RTK_RXSTAT_LEN 4
+#ifdef __NO_STRICT_ALIGNMENT
+/*
+ * XXX According to PR kern/33763, some 8168 and variants can't DMA
+ * XXX RX packet data into unaligned buffer. This means such chips will
+ * XXX never work on !__NO_STRICT_ALIGNMENT hosts without copying buffer.
+ */
+#define RE_ETHER_ALIGN 0
+#else
+#define RE_ETHER_ALIGN 2
+#endif
+
struct rtk_type {
- u_int16_t rtk_vid;
- u_int16_t rtk_did;
+ uint16_t rtk_vid;
+ uint16_t rtk_did;
int rtk_basetype;
const char *rtk_name;
};
@@ -53,16 +64,25 @@
struct rtk_hwrev {
uint32_t rtk_rev;
int rtk_type;
- char *rtk_desc;
+ const char *rtk_desc;
};
+#define RTK_8129 1
+#define RTK_8139 2
+#define RTK_8139CPLUS 3
+#define RTK_8169 4
+
+#define RTK_ISCPLUS(x) ((x)->rtk_type == RTK_8139CPLUS || \
+ (x)->rtk_type == RTK_8169)
+
+
struct rtk_mii_frame {
- u_int8_t mii_stdelim;
- u_int8_t mii_opcode;
- u_int8_t mii_phyaddr;
- u_int8_t mii_regaddr;
- u_int8_t mii_turnaround;
- u_int16_t mii_data;
+ uint8_t mii_stdelim;
+ uint8_t mii_opcode;
+ uint8_t mii_phyaddr;
+ uint8_t mii_regaddr;
+ uint8_t mii_turnaround;
+ uint16_t mii_data;
};
/*
@@ -73,47 +93,90 @@
#define RTK_MII_WRITEOP 0x01
#define RTK_MII_TURNAROUND 0x02
-#define RTK_8129 1
-#define RTK_8139 2
-#define RTK_8139CPLUS 3
-#define RTK_8169 4
-#define RTK_ISCPLUS(x) ((x)->rtk_type == RTK_8139CPLUS || \
- (x)->rtk_type == RTK_8169)
+/*
+ * The RealTek doesn't use a fragment-based descriptor mechanism.
+ * Instead, there are only four register sets, each or which represents
+ * one 'descriptor.' Basically, each TX descriptor is just a contiguous
+ * packet buffer (32-bit aligned!) and we place the buffer addresses in
+ * the registers so the chip knows where they are.
+ *
+ * We can sort of kludge together the same kind of buffer management
+ * used in previous drivers, but we have to do buffer copies almost all
+ * the time, so it doesn't really buy us much.
+ *
+ * For reception, there's just one large buffer where the chip stores
+ * all received packets.
+ */
-#define RTK_TX_QLEN 64
+#ifdef dreamcast
+/*
+ * XXX dreamcast has only 32KB DMA'able memory on its PCI bridge.
+ * XXX Maybe this should be handled by prop_dictionary, or
+ * XXX some other new API which returns available DMA resources.
+ */
+#define RTK_RX_BUF_SZ RTK_RXBUF_16
+#else
+#define RTK_RX_BUF_SZ RTK_RXBUF_64
+#endif
+#define RTK_RXBUFLEN RTK_RXBUF_LEN(RTK_RX_BUF_SZ)
+#define RTK_TX_LIST_CNT 4
/*
- * The 8139C+ and 8160 gigE chips support descriptor-based TX
+ * The 8139C+ and 8169 gigE chips support descriptor-based TX
* and RX. In fact, they even support TCP large send. Descriptors
* must be allocated in contiguous blocks that are aligned on a
- * 256-byte boundary. The rings can hold a maximum of 64 descriptors.
+ * 256-byte boundary. The RX rings can hold a maximum of 64 descriptors.
+ * The TX rings can hold upto 64 descriptors on 8139C+, and
+ * 1024 descriptors on 8169 gigE chips.
+ */
+#define RE_RING_ALIGN 256
+
+/*
+ * Size of descriptors and TX queue.
+ * These numbers must be power of two to simplify RE_NEXT_*() macro.
*/
+#define RE_RX_DESC_CNT 64
+#define RE_TX_DESC_CNT_8139 64
+#define RE_TX_DESC_CNT_8169 1024
+#define RE_TX_QLEN 64
+
+#define RE_NTXDESC_RSVD 4
+
+struct re_rxsoft {
+ struct mbuf *rxs_mbuf;
+ bus_dmamap_t rxs_dmamap;
+};
-struct rtk_list_data {
- struct rtk_txq {
- struct mbuf *txq_mbuf;
- bus_dmamap_t txq_dmamap;
- int txq_descidx;
- } rtk_txq[RTK_TX_QLEN];
- int rtk_txq_considx;
- int rtk_txq_prodidx;
- bus_dmamap_t rtk_tx_list_map;
- struct rtk_desc *rtk_tx_list;
- bus_dma_segment_t rtk_tx_listseg;
- int rtk_tx_free; /* # of free descriptors */
- int rtk_tx_nextfree; /* next descriptor to use */
- int rtk_tx_desc_cnt; /* # of descriptors */
- int rtk_tx_listnseg;
-
- struct mbuf *rtk_rx_mbuf[RTK_RX_DESC_CNT];
- bus_dmamap_t rtk_rx_dmamap[RTK_RX_DESC_CNT];
- bus_dmamap_t rtk_rx_list_map;
- struct rtk_desc *rtk_rx_list;
- bus_dma_segment_t rtk_rx_listseg;
- int rtk_rx_prodidx;
- int rtk_rx_listnseg;
+struct re_txq {
+ struct mbuf *txq_mbuf;
+ bus_dmamap_t txq_dmamap;
+ int txq_descidx;
+ int txq_nsegs;
};
+
+struct re_list_data {
+ struct re_txq re_txq[RE_TX_QLEN];
+ int re_txq_considx;
+ int re_txq_prodidx;
+ int re_txq_free;
+
+ bus_dmamap_t re_tx_list_map;
+ struct re_desc *re_tx_list;
+ int re_tx_free; /* # of free descriptors */
+ int re_tx_nextfree; /* next descriptor to use */
+ int re_tx_desc_cnt; /* # of descriptors */
+ bus_dma_segment_t re_tx_listseg;
+ int re_tx_listnseg;
+
+ struct re_rxsoft re_rxsoft[RE_RX_DESC_CNT];
+ bus_dmamap_t re_rx_list_map;
+ struct re_desc *re_rx_list;
+ int re_rx_prodidx;
+ bus_dma_segment_t re_rx_listseg;
+ int re_rx_listnseg;
+};
+
struct rtk_tx_desc {
SIMPLEQ_ENTRY(rtk_tx_desc) txd_q;
struct mbuf *txd_mbuf;
@@ -131,20 +194,22 @@
bus_space_tag_t rtk_btag; /* bus space tag */
int rtk_type;
bus_dma_tag_t sc_dmat;
- bus_dma_segment_t sc_dmaseg;
- int sc_dmanseg;
- bus_dmamap_t recv_dmamap;
+ bus_dma_segment_t sc_dmaseg; /* for rtk(4) */
+ int sc_dmanseg; /* for rtk(4) */
+
+ bus_dmamap_t recv_dmamap; /* for rtk(4) */
caddr_t rtk_rx_buf;
struct rtk_tx_desc rtk_tx_descs[RTK_TX_LIST_CNT];
SIMPLEQ_HEAD(, rtk_tx_desc) rtk_tx_free;
SIMPLEQ_HEAD(, rtk_tx_desc) rtk_tx_dirty;
- struct rtk_list_data rtk_ldata;
- struct mbuf *rtk_head;
- struct mbuf *rtk_tail;
- u_int32_t rtk_rxlenmask;
- int rtk_testmode;
+
+ struct re_list_data re_ldata;
+ struct mbuf *re_head;
+ struct mbuf *re_tail;
+ uint32_t re_rxlenmask;
+ int re_testmode;
int sc_flags; /* misc flags */
int sc_txthresh; /* Early tx threshold */
@@ -162,23 +227,51 @@
#endif
};
-#define RTK_TX_DESC_CNT(sc) \
- ((sc)->rtk_ldata.rtk_tx_desc_cnt)
-#define RTK_TX_LIST_SZ(sc) \
- (RTK_TX_DESC_CNT(sc) * sizeof(struct rtk_desc))
-#define RTK_TX_DESC_INC(sc, x) \
- ((x) = ((x) + 1) % RTK_TX_DESC_CNT(sc))
-#define RTK_RX_DESC_INC(sc, x) \
- ((x) = ((x) + 1) % RTK_RX_DESC_CNT)
+#define RE_TX_DESC_CNT(sc) ((sc)->re_ldata.re_tx_desc_cnt)
+#define RE_TX_LIST_SZ(sc) (RE_TX_DESC_CNT(sc) * sizeof(struct re_desc))
+#define RE_NEXT_TX_DESC(sc, x) (((x) + 1) & (RE_TX_DESC_CNT(sc) - 1))
+
+#define RE_RX_LIST_SZ (RE_RX_DESC_CNT * sizeof(struct re_desc))
+#define RE_NEXT_RX_DESC(sc, x) (((x) + 1) & (RE_RX_DESC_CNT - 1))
+
+#define RE_NEXT_TXQ(sc, x) (((x) + 1) & (RE_TX_QLEN - 1))
+
+#define RE_TXDESCSYNC(sc, idx, ops) \
+ bus_dmamap_sync((sc)->sc_dmat, \
+ (sc)->re_ldata.re_tx_list_map, \
+ sizeof(struct re_desc) * (idx), \
+ sizeof(struct re_desc), \
+ (ops))
+#define RE_RXDESCSYNC(sc, idx, ops) \
+ bus_dmamap_sync((sc)->sc_dmat, \
+ (sc)->re_ldata.re_rx_list_map, \
+ sizeof(struct re_desc) * (idx), \
+ sizeof(struct re_desc), \
+ (ops))
+
+/*
+ * re(4) hardware ip4csum-tx could be mangled with 28 byte or less IP packets
+ */
+#define RE_IP4CSUMTX_MINLEN 28
+#define RE_IP4CSUMTX_PADLEN (ETHER_HDR_LEN + RE_IP4CSUMTX_MINLEN)
+/*
+ * XXX
+ * We are allocating pad DMA buffer after RX DMA descs for now
+ * because RE_TX_LIST_SZ(sc) always occupies whole page but
+ * RE_RX_LIST_SZ is less than PAGE_SIZE so there is some unused region.
+ */
+#define RE_RX_DMAMEM_SZ (RE_RX_LIST_SZ + RE_IP4CSUMTX_PADLEN)
+#define RE_TXPADOFF RE_RX_LIST_SZ
+#define RE_TXPADDADDR(sc) \
+ ((sc)->re_ldata.re_rx_list_map->dm_segs[0].ds_addr + RE_TXPADOFF)
+
#define RTK_ATTACHED 0x00000001 /* attach has succeeded */
#define RTK_ENABLED 0x00000002 /* chip is enabled */
#define RTK_IS_ENABLED(sc) ((sc)->sc_flags & RTK_ENABLED)
-#define RTK_TX_THRESH(sc) (((sc)->sc_txthresh << 16) & 0x003F0000)
-#define TXTH_256 8
-#define TXTH_MAX 48
+#define RTK_TXTH_MAX RTK_TXTH_1536
/*
* register space access macros
@@ -189,9 +282,6 @@
bus_space_write_2(sc->rtk_btag, sc->rtk_bhandle, reg, val)
#define CSR_WRITE_1(sc, reg, val) \
bus_space_write_1(sc->rtk_btag, sc->rtk_bhandle, reg, val)
-#define CSR_WRITE_STREAM_4(sc, reg, val) \
- bus_space_write_stream_4(sc->rtk_btag, sc->rtk_bhandle, reg, val)
-
#define CSR_READ_4(sc, reg) \
bus_space_read_4(sc->rtk_btag, sc->rtk_bhandle, reg)
@@ -203,23 +293,14 @@
#define RTK_TIMEOUT 1000
/*
- * PCI low memory base and low I/O base register, and
- * other PCI registers.
+ * PCI low memory base and low I/O base registers
*/
#define RTK_PCI_LOIO 0x10
#define RTK_PCI_LOMEM 0x14
-#define RTK_PSTATE_MASK 0x0003
-#define RTK_PSTATE_D0 0x0000
-#define RTK_PSTATE_D1 0x0002
-#define RTK_PSTATE_D2 0x0002
-#define RTK_PSTATE_D3 0x0003
-#define RTK_PME_EN 0x0010
-#define RTK_PME_STATUS 0x8000
-
#ifdef _KERNEL
-u_int16_t rtk_read_eeprom(struct rtk_softc *, int, int);
+uint16_t rtk_read_eeprom(struct rtk_softc *, int, int);
void rtk_setmulti(struct rtk_softc *);
void rtk_attach(struct rtk_softc *);
int rtk_detach(struct rtk_softc *);
Index: dev/mii/files.mii
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/files.mii,v
retrieving revision 1.36
diff -u -r1.36 files.mii
--- dev/mii/files.mii 20 Feb 2005 16:35:56 -0000 1.36
+++ dev/mii/files.mii 11 Feb 2007 03:42:02 -0000
@@ -117,3 +117,7 @@
device ciphy: mii_phy
attach ciphy at mii
file dev/mii/ciphy.c ciphy
+
+device rlphy: mii_phy
+attach rlphy at mii
+file dev/mii/rlphy.c rlphy
Index: dev/mii/miidevs
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miidevs,v
retrieving revision 1.58.2.4
diff -u -r1.58.2.4 miidevs
--- dev/mii/miidevs 28 Apr 2006 22:23:56 -0000 1.58.2.4
+++ dev/mii/miidevs 11 Feb 2007 03:42:02 -0000
@@ -58,6 +58,7 @@
oui CICADA 0x0003F1 Cicada Semiconductor
oui DAVICOM 0x00606e Davicom Semiconductor
oui ENABLESEMI 0x0010dd Enable Semiconductor
+oui ICPLUS 0x0090c3 IC Plus Corp.
oui ICS 0x00a0be Integrated Circuit Systems
oui INTEL 0x00aa00 Intel
oui LEVEL1 0x00207b Level 1
@@ -99,7 +100,7 @@
oui xxPMCSIERRA2 0x009057 PMC-Sierra
oui xxREALTEK 0x000732 Realtek
-
+oui yyREALTEK 0x000004 Realtek
/*
* List of known models. Grouped by oui.
*/
@@ -151,6 +152,9 @@
model xxDAVICOM DM9101 0x0000 DM9101 (AMD Am79C873) 10/100 media interface
model xxDAVICOM DM9102 0x0004 DM9102 10/100 media interface
+/* IC Plus Corp. PHYs */
+model ICPLUS IP101 0x0005 IP101 10/100 PHY
+
/* Integrated Circuit Systems PHYs */
model ICS 1889 0x0001 ICS1889 10/100 media interface
model ICS 1890 0x0002 ICS1890 10/100 media interface
@@ -203,6 +207,7 @@
model xxQUALSEMI QS6612 0x0000 QS6612 10/100 media interface
/* RealTek PHYs */
+model yyREALTEK RTL8201L 0x0020 RTL8201L 10/100 media interface
model xxREALTEK RTL8169S 0x0011 RTL8169S/8110S 1000BASE-T media interface
model REALTEK RTL8169S 0x0011 RTL8169S/8110S 1000BASE-T media interface
Index: dev/mii/miidevs.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miidevs.h,v
retrieving revision 1.60.2.4
diff -u -r1.60.2.4 miidevs.h
--- dev/mii/miidevs.h 28 Apr 2006 22:25:19 -0000 1.60.2.4
+++ dev/mii/miidevs.h 11 Feb 2007 03:42:02 -0000
@@ -65,6 +65,7 @@
#define MII_OUI_CICADA 0x0003F1 /* Cicada Semiconductor */
#define MII_OUI_DAVICOM 0x00606e /* Davicom Semiconductor */
#define MII_OUI_ENABLESEMI 0x0010dd /* Enable Semiconductor */
+#define MII_OUI_ICPLUS 0x0090c3 /* IC Plus Corp. */
#define MII_OUI_ICS 0x00a0be /* Integrated Circuit Systems */
#define MII_OUI_INTEL 0x00aa00 /* Intel */
#define MII_OUI_LEVEL1 0x00207b /* Level 1 */
@@ -106,7 +107,7 @@
#define MII_OUI_xxPMCSIERRA2 0x009057 /* PMC-Sierra */
#define MII_OUI_xxREALTEK 0x000732 /* Realtek */
-
+#define MII_OUI_yyREALTEK 0x000004 /* Realtek */
/*
* List of known models. Grouped by oui.
*/
@@ -191,6 +192,10 @@
#define MII_MODEL_xxDAVICOM_DM9102 0x0004
#define MII_STR_xxDAVICOM_DM9102 "DM9102 10/100 media interface"
+/* IC Plus Corp. PHYs */
+#define MII_MODEL_ICPLUS_IP101 0x0005
+#define MII_STR_ICPLUS_IP101 "IP101 10/100 PHY"
+
/* Integrated Circuit Systems PHYs */
#define MII_MODEL_ICS_1889 0x0001
#define MII_STR_ICS_1889 "ICS1889 10/100 media interface"
@@ -277,6 +282,8 @@
#define MII_STR_xxQUALSEMI_QS6612 "QS6612 10/100 media interface"
/* RealTek PHYs */
+#define MII_MODEL_yyREALTEK_RTL8201L 0x0020
+#define MII_STR_yyREALTEK_RTL8201L "RTL8201L 10/100 media interface"
#define MII_MODEL_xxREALTEK_RTL8169S 0x0011
#define MII_STR_xxREALTEK_RTL8169S "RTL8169S/8110S 1000BASE-T media interface"
#define MII_MODEL_REALTEK_RTL8169S 0x0011
Index: dev/mii/miidevs_data.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/miidevs_data.h,v
retrieving revision 1.50.2.4
diff -u -r1.50.2.4 miidevs_data.h
--- dev/mii/miidevs_data.h 28 Apr 2006 22:25:19 -0000 1.50.2.4
+++ dev/mii/miidevs_data.h 11 Feb 2007 03:42:02 -0000
@@ -77,6 +77,7 @@
{ MII_OUI_xxCICADA, MII_MODEL_xxCICADA_CS8201B, MII_STR_xxCICADA_CS8201B },
{ MII_OUI_xxDAVICOM, MII_MODEL_xxDAVICOM_DM9101, MII_STR_xxDAVICOM_DM9101 },
{ MII_OUI_xxDAVICOM, MII_MODEL_xxDAVICOM_DM9102, MII_STR_xxDAVICOM_DM9102 },
+ { MII_OUI_ICPLUS, MII_MODEL_ICPLUS_IP101, MII_STR_ICPLUS_IP101 },
{ MII_OUI_ICS, MII_MODEL_ICS_1889, MII_STR_ICS_1889 },
{ MII_OUI_ICS, MII_MODEL_ICS_1890, MII_STR_ICS_1890 },
{ MII_OUI_ICS, MII_MODEL_ICS_1892, MII_STR_ICS_1892 },
@@ -111,6 +112,7 @@
{ MII_OUI_xxPMCSIERRA2, MII_MODEL_xxPMCSIERRA2_PM8353, MII_STR_xxPMCSIERRA2_PM8353 },
{ MII_OUI_PMCSIERRA, MII_MODEL_PMCSIERRA_PM8354, MII_STR_PMCSIERRA_PM8354 },
{ MII_OUI_xxQUALSEMI, MII_MODEL_xxQUALSEMI_QS6612, MII_STR_xxQUALSEMI_QS6612 },
+ { MII_OUI_yyREALTEK, MII_MODEL_yyREALTEK_RTL8201L, MII_STR_yyREALTEK_RTL8201L },
{ MII_OUI_xxREALTEK, MII_MODEL_xxREALTEK_RTL8169S, MII_STR_xxREALTEK_RTL8169S },
{ MII_OUI_REALTEK, MII_MODEL_REALTEK_RTL8169S, MII_STR_REALTEK_RTL8169S },
{ MII_OUI_SEEQ, MII_MODEL_SEEQ_80220, MII_STR_SEEQ_80220 },
Index: dev/mii/rgephy.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/rgephy.c,v
retrieving revision 1.5.2.1
diff -u -r1.5.2.1 rgephy.c
--- dev/mii/rgephy.c 27 Mar 2005 16:28:40 -0000 1.5.2.1
+++ dev/mii/rgephy.c 11 Feb 2007 03:42:02 -0000
@@ -43,6 +43,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/device.h>
#include <sys/socket.h>
@@ -70,7 +71,6 @@
static void rgephy_reset(struct mii_softc *);
static void rgephy_loop(struct mii_softc *);
static void rgephy_load_dspcode(struct mii_softc *);
-static int rgephy_mii_model;
static const struct mii_phy_funcs rgephy_funcs = {
rgephy_service, rgephy_status, rgephy_reset,
@@ -93,9 +93,9 @@
struct mii_attach_args *ma = aux;
if (mii_phy_match(ma, rgephys) != NULL)
- return (10);
+ return 10;
- return (0);
+ return 0;
}
static void
@@ -122,24 +122,14 @@
sc->mii_funcs = &rgephy_funcs;
- /* Don't do isolate on this PHY. */
- sc->mii_flags |= MIIF_NOISOLATE;
-
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
#define PRINT(n) aprint_normal("%s%s", sep, (n)); sep = ", "
-#if 0
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
- BMCR_ISO);
-#endif
#ifdef __FreeBSD__
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
BMCR_LOOP|BMCR_S100);
#endif
- rgephy_mii_model = MII_MODEL(ma->mii_id2);
- PHY_RESET(sc);
-
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
sc->mii_capabilities &= ~BMSR_ANEG;
@@ -148,19 +138,11 @@
* media explicitly. Why?
*/
aprint_normal("%s: ", sc->mii_dev.dv_xname);
-#ifdef __FreeBSD__
- mii_phy_add_media(sc);
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
- RGEPHY_BMCR_FDX);
- PRINT(", 1000baseTX");
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), 0);
- PRINT("1000baseTX-FDX");
-#else
if (sc->mii_capabilities & BMSR_EXTSTAT) {
sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
}
mii_phy_add_media(sc);
-#endif
+
/* rtl8169S does not report auto-sense; add manually. */
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), MII_NMEDIA);
sep =", ";
@@ -169,17 +151,15 @@
#undef ADD
#undef PRINT
+ PHY_RESET(sc);
aprint_normal("\n");
}
static int
-rgephy_service(sc, mii, cmd)
- struct mii_softc *sc;
- struct mii_data *mii;
- int cmd;
+rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
- int reg, speed, gig;
+ int reg, speed, gig, anar;
switch (cmd) {
case MII_POLLSTAT:
@@ -187,7 +167,7 @@
* If we're not polling our PHY instance, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
- return (0);
+ return 0;
break;
case MII_MEDIACHG:
@@ -198,7 +178,7 @@
if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
reg = PHY_READ(sc, MII_BMCR);
PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
- return (0);
+ return 0;
}
/*
@@ -209,6 +189,10 @@
PHY_RESET(sc); /* XXX hardware bug work-around */
+ anar = PHY_READ(sc, RGEPHY_MII_ANAR);
+ anar &= ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
+ RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10);
+
switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
#ifdef foo
@@ -216,40 +200,42 @@
* If we're already in auto mode, just return.
*/
if (PHY_READ(sc, RGEPHY_MII_BMCR) & RGEPHY_BMCR_AUTOEN)
- return (0);
+ return 0;
#endif
- (void) rgephy_mii_phy_auto(sc);
+ (void)rgephy_mii_phy_auto(sc);
break;
case IFM_1000_T:
speed = RGEPHY_S1000;
goto setit;
case IFM_100_TX:
speed = RGEPHY_S100;
+ anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX;
goto setit;
case IFM_10_T:
speed = RGEPHY_S10;
-setit:
+ anar |= RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10;
+ setit:
rgephy_loop(sc);
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
speed |= RGEPHY_BMCR_FDX;
gig = RGEPHY_1000CTL_AFD;
+ anar &= ~(RGEPHY_ANAR_TX | RGEPHY_ANAR_10);
} else {
gig = RGEPHY_1000CTL_AHD;
+ anar &=
+ ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_10_FD);
}
- PHY_WRITE(sc, RGEPHY_MII_1000CTL, 0);
- PHY_WRITE(sc, RGEPHY_MII_BMCR, speed);
- PHY_WRITE(sc, RGEPHY_MII_ANAR, RGEPHY_SEL_TYPE);
-
- if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) {
+ PHY_WRITE(sc, RGEPHY_MII_1000CTL, 0);
+ PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
+ PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
+ RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
break;
-
- PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig);
- PHY_WRITE(sc, RGEPHY_MII_BMCR,
- speed|RGEPHY_BMCR_AUTOEN|RGEPHY_BMCR_STARTNEG);
+ }
/*
- * When settning the link manually, one side must
+ * When setting the link manually, one side must
* be the master and the other the slave. However
* ifmedia doesn't give us a good way to specify
* this, so we fake it by using one of the LINK
@@ -263,15 +249,15 @@
PHY_WRITE(sc, RGEPHY_MII_1000CTL,
gig|RGEPHY_1000CTL_MSE);
}
+ PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
+ RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
break;
-#ifdef foo
case IFM_NONE:
PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
break;
-#endif
case IFM_100_T4:
default:
- return (EINVAL);
+ return EINVAL;
}
break;
@@ -280,13 +266,13 @@
* If we're not currently selected, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
- return (0);
+ return 0;
/*
* Is the interface even up?
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- return (0);
+ return 0;
/*
* Only used for autonegotiation.
@@ -300,7 +286,7 @@
* the BMSR twice in case it's latched.
*/
reg = PHY_READ(sc, RTK_GMEDIASTAT);
- if (reg & RTK_GMEDIASTAT_LINK)
+ if ((reg & RTK_GMEDIASTAT_LINK) != 0)
break;
/*
@@ -311,7 +297,7 @@
sc->mii_ticks = 0;
rgephy_mii_phy_auto(sc);
- return (0);
+ return 0;
}
/* Update the media status. */
@@ -330,12 +316,11 @@
rgephy_load_dspcode(sc);
}
mii_phy_update(sc, cmd);
- return (0);
+ return 0;
}
static void
-rgephy_status(sc)
- struct mii_softc *sc;
+rgephy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
int bmsr, bmcr;
@@ -343,24 +328,22 @@
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
- bmsr = PHY_READ(sc, RTK_GMEDIASTAT);
-
- if (bmsr & RTK_GMEDIASTAT_LINK)
+ if ((PHY_READ(sc, RTK_GMEDIASTAT) & RTK_GMEDIASTAT_LINK) != 0)
mii->mii_media_status |= IFM_ACTIVE;
- bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
+ bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
bmcr = PHY_READ(sc, RGEPHY_MII_BMCR);
- if (bmcr & RGEPHY_BMCR_ISO) {
+ if ((bmcr & RGEPHY_BMCR_ISO) != 0) {
mii->mii_media_active |= IFM_NONE;
mii->mii_media_status = 0;
return;
}
- if (bmcr & RGEPHY_BMCR_LOOP)
+ if ((bmcr & RGEPHY_BMCR_LOOP) != 0)
mii->mii_media_active |= IFM_LOOP;
- if (bmcr & RGEPHY_BMCR_AUTOEN) {
+ if ((bmcr & RGEPHY_BMCR_AUTOEN) != 0) {
if ((bmsr & RGEPHY_BMSR_ACOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
@@ -369,42 +352,43 @@
}
bmsr = PHY_READ(sc, RTK_GMEDIASTAT);
- if (bmsr & RTK_GMEDIASTAT_10MBPS)
- mii->mii_media_active |= IFM_10_T;
- if (bmsr & RTK_GMEDIASTAT_100MBPS)
- mii->mii_media_active |= IFM_100_TX;
- if (bmsr & RTK_GMEDIASTAT_1000MBPS)
+ if ((bmsr & RTK_GMEDIASTAT_1000MBPS) != 0)
mii->mii_media_active |= IFM_1000_T;
- if (bmsr & RTK_GMEDIASTAT_FDX)
+ else if ((bmsr & RTK_GMEDIASTAT_100MBPS) != 0)
+ mii->mii_media_active |= IFM_100_TX;
+ else if ((bmsr & RTK_GMEDIASTAT_10MBPS) != 0)
+ mii->mii_media_active |= IFM_10_T;
+ else
+ mii->mii_media_active |= IFM_NONE;
+ if ((bmsr & RTK_GMEDIASTAT_FDX) != 0)
mii->mii_media_active |= IFM_FDX;
-
- return;
}
static int
-rgephy_mii_phy_auto(mii)
- struct mii_softc *mii;
+rgephy_mii_phy_auto(struct mii_softc *mii)
{
+
rgephy_loop(mii);
PHY_RESET(mii);
PHY_WRITE(mii, RGEPHY_MII_ANAR,
BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
DELAY(1000);
- PHY_WRITE(mii, RGEPHY_MII_1000CTL, RGEPHY_1000CTL_AFD);
+ PHY_WRITE(mii, RGEPHY_MII_1000CTL,
+ RGEPHY_1000CTL_AHD | RGEPHY_1000CTL_AFD);
DELAY(1000);
PHY_WRITE(mii, RGEPHY_MII_BMCR,
RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
DELAY(100);
- return (EJUSTRETURN);
+ return EJUSTRETURN;
}
static void
rgephy_loop(struct mii_softc *sc)
{
- u_int32_t bmsr;
+ uint32_t bmsr;
int i;
PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN);
@@ -412,7 +396,7 @@
for (i = 0; i < 15000; i++) {
bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
- if (!(bmsr & RGEPHY_BMSR_LINK)) {
+ if ((bmsr & RGEPHY_BMSR_LINK) == 0) {
#if 0
device_printf(sc->mii_dev, "looped %d\n", i);
#endif
@@ -430,8 +414,9 @@
/*
* Initialize RealTek PHY per the datasheet. The DSP in the PHYs of
* existing revisions of the 8169S/8110S chips need to be tuned in
- * order to reliably negotiate a 1000Mbps link. Later revs of the
- * chips may not require this software tuning.
+ * order to reliably negotiate a 1000Mbps link. This is only needed
+ * for rev 0 and rev 1 of the PHY. Later versions work without
+ * any fixups.
*/
static void
rgephy_load_dspcode(struct mii_softc *sc)
@@ -530,6 +515,7 @@
static void
rgephy_reset(struct mii_softc *sc)
{
+
mii_phy_reset(sc);
DELAY(1000);
@@ -548,11 +534,16 @@
/* Reset capabilities */
/* Step1: write our capability */
- PHY_WRITE(sc, 0x04,0x01e1); /* 10/100 capability */
- PHY_WRITE(sc, 0x09,0x0200); /* 1000 capability */
+ /* 10/100 capability */
+ PHY_WRITE(sc, RGEPHY_MII_ANAR,
+ RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
+ RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10 | ANAR_CSMA);
+ /* 1000 capability */
+ PHY_WRITE(sc, RGEPHY_MII_1000CTL,
+ RGEPHY_1000CTL_AFD | RGEPHY_1000CTL_AHD);
-#ifdef jrs_notyet
/* Step2: Restart NWay */
- PHY_WRITE(sc, 0x00, 0x1200); // NWay enable and Restart NWay
-#endif
+ /* NWay enable and Restart NWay */
+ PHY_WRITE(sc, RGEPHY_MII_BMCR,
+ RGEPHY_BMCR_RESET | RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
}
Index: dev/pci/if_re_pci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_re_pci.c,v
retrieving revision 1.8.2.4
diff -u -r1.8.2.4 if_re_pci.c
--- dev/pci/if_re_pci.c 29 Dec 2005 19:44:18 -0000 1.8.2.4
+++ dev/pci/if_re_pci.c 11 Feb 2007 03:42:02 -0000
@@ -41,7 +41,7 @@
* Senior Networking Software Engineer
* Wind River Systems
*
- * Netbsd bus-specific frontends for written by
+ * NetBSD bus-specific frontends for written by
* Jonathan Stone <jonathan@netbsd.org>
*/
@@ -76,11 +76,6 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
-/*
- * Default to using PIO access for this driver.
- */
-#define RE_USEIOSPACE
-
#include <dev/ic/rtl81x9reg.h>
#include <dev/ic/rtl81x9var.h>
#include <dev/ic/rtl8169var.h>
@@ -93,31 +88,58 @@
pcitag_t sc_pcitag;
};
-static int re_pci_probe(struct device *, struct cfdata *, void *);
+static int re_pci_match(struct device *, struct cfdata *, void *);
static void re_pci_attach(struct device *, struct device *, void *);
/*
* Various supported device vendors/types and their names.
*/
static const struct rtk_type re_devs[] = {
- { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8139, RTK_HWREV_8139CPLUS,
- "RealTek 8139C+ 10/100BaseTX" },
- { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169, RTK_HWREV_8169,
- "RealTek 8169 Gigabit Ethernet" },
- { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169, RTK_HWREV_8169S,
- "RealTek 8169S Single-chip Gigabit Ethernet" },
- { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169, RTK_HWREV_8169SB,
- "RealTek 8169SB Single-chip Gigabit Ethernet" },
- { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_LAPCIGT, RTK_HWREV_8169S,
- "Corega CG-LAPCIGT Gigabit Ethernet" },
- { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169, RTK_HWREV_8110S,
- "RealTek 8110S Single-chip Gigabit Ethernet" },
- { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE528T, RTK_HWREV_8169S,
- "D-Link DGE-528T Gigabit Ethernet" },
- { PCI_VENDOR_USR2, PCI_PRODUCT_USR2_USR997902, RTK_HWREV_8169S,
- "US Robotics (3Com) USR997902 Gigabit Ethernet" },
- { PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_EG1032, RTK_HWREV_8169S,
- "Linksys EG1032 rev. 3 Gigabit Ethernet" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8139,
+ RTK_HWREV_8139CPLUS,
+ "RealTek 8139C+ 10/100BaseTX" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8101E,
+ RTK_HWREV_8100E,
+ "RealTek 8100E PCIe 10/100BaseTX" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8101E,
+ RTK_HWREV_8101E,
+ "RealTek 8101E PCIe 10/100BaseTX" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8168,
+ RTK_HWREV_8168_SPIN1,
+ "RealTek 8168B/8111B PCIe Gigabit Ethernet" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8168,
+ RTK_HWREV_8168_SPIN2,
+ "RealTek 8168B/8111B PCIe Gigabit Ethernet" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169,
+ RTK_HWREV_8169,
+ "RealTek 8169 Gigabit Ethernet" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169,
+ RTK_HWREV_8169S,
+ "RealTek 8169S Single-chip Gigabit Ethernet" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169,
+ RTK_HWREV_8110S,
+ "RealTek 8110S Single-chip Gigabit Ethernet" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169,
+ RTK_HWREV_8169_8110SB,
+ "RealTek 8169SB/8110SB Single-chip Gigabit Ethernet" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169,
+ RTK_HWREV_8169_8110SC,
+ "RealTek 8169SC/8110SC Single-chip Gigabit Ethernet" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169SC,
+ RTK_HWREV_8169_8110SC,
+ "RealTek 8169SC/8110SC Single-chip Gigabit Ethernet" },
+ { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_LAPCIGT,
+ RTK_HWREV_8169S,
+ "Corega CG-LAPCIGT Gigabit Ethernet" },
+ { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE528T,
+ RTK_HWREV_8169S,
+ "D-Link DGE-528T Gigabit Ethernet" },
+ { PCI_VENDOR_USR2, PCI_PRODUCT_USR2_USR997902,
+ RTK_HWREV_8169S,
+ "US Robotics (3Com) USR997902 Gigabit Ethernet" },
+ { PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_EG1032,
+ RTK_HWREV_8169S,
+ "Linksys EG1032 rev. 3 Gigabit Ethernet" },
{ 0, 0, 0, NULL }
};
@@ -130,10 +152,15 @@
{ RTK_HWREV_8139C, RTK_8139, "C" },
{ RTK_HWREV_8139D, RTK_8139, "8139D/8100B/8100C" },
{ RTK_HWREV_8139CPLUS, RTK_8139CPLUS, "C+"},
+ { RTK_HWREV_8168_SPIN1, RTK_8169, "8168B/8111B"},
+ { RTK_HWREV_8168_SPIN2, RTK_8169, "8168B/8111B"},
{ RTK_HWREV_8169, RTK_8169, "8169"},
{ RTK_HWREV_8169S, RTK_8169, "8169S"},
- { RTK_HWREV_8169SB, RTK_8169, "8169SB"},
{ RTK_HWREV_8110S, RTK_8169, "8110S"},
+ { RTK_HWREV_8169_8110SB, RTK_8169, "8169SB"},
+ { RTK_HWREV_8169_8110SC, RTK_8169, "8169SC"},
+ { RTK_HWREV_8100E, RTK_8169, "8100E"},
+ { RTK_HWREV_8101E, RTK_8169, "8101E"},
{ RTK_HWREV_8100, RTK_8139, "8100"},
{ RTK_HWREV_8101, RTK_8139, "8101"},
{ 0, 0, NULL }
@@ -141,7 +168,7 @@
#define RE_LINKSYS_EG1032_SUBID 0x00241737
-CFATTACH_DECL(re_pci, sizeof(struct re_pci_softc), re_pci_probe, re_pci_attach,
+CFATTACH_DECL(re_pci, sizeof(struct re_pci_softc), re_pci_match, re_pci_attach,
NULL, NULL);
/*
@@ -149,15 +176,16 @@
* IDs against our list and return a device name if we find a match.
*/
static int
-re_pci_probe(struct device *parent, struct cfdata *match, void *aux)
+re_pci_match(struct device *parent, struct cfdata *match, void *aux)
{
- const struct rtk_type *t;
+ const struct rtk_type *t;
struct pci_attach_args *pa = aux;
- bus_space_tag_t rtk_btag;
- bus_space_handle_t rtk_bhandle;
- bus_size_t bsize;
+ bus_space_tag_t iot, memt, bst;
+ bus_space_handle_t ioh, memh, bsh;
+ bus_size_t memsize, iosize, bsize;
u_int32_t hwrev;
pcireg_t subid;
+ boolean_t ioh_valid, memh_valid;
subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
@@ -177,24 +205,25 @@
* Temporarily map the I/O space
* so we can read the chip ID register.
*/
-#ifdef RE_USEIOSPACE
- if (pci_mapreg_map(pa, RTK_PCI_LOIO,
- PCI_MAPREG_TYPE_IO, 0, &rtk_btag,
- &rtk_bhandle, NULL, &bsize)) {
- aprint_error("can't map i/o space\n");
+ ioh_valid = (pci_mapreg_map(pa, RTK_PCI_LOIO,
+ PCI_MAPREG_TYPE_IO, 0, &iot, &ioh,
+ NULL, &iosize) == 0);
+ memh_valid = (pci_mapreg_map(pa, RTK_PCI_LOMEM,
+ PCI_MAPREG_TYPE_MEM, 0, &memt, &memh,
+ NULL, &memsize) == 0);
+ if (ioh_valid) {
+ bst = iot;
+ bsh = ioh;
+ bsize = iosize;
+ } else if (memh_valid) {
+ bst = memt;
+ bsh = memh;
+ bsize = memsize;
+ } else
return 0;
- }
-#else
- if (pci_mapreg_map(pa, RTK_PCI_LOMEM,
- PCI_MAPREG_TYPE_MEM, 0, &rtk_btag,
- &rtk_bhandle, NULL, &bsize)) {
- aprint_error("can't map mem space\n");
- return 0;
- }
-#endif
- hwrev = bus_space_read_4(rtk_btag, rtk_bhandle,
- RTK_TXCFG) & RTK_TXCFG_HWREV;
- bus_space_unmap(rtk_btag, rtk_bhandle, bsize);
+ hwrev = bus_space_read_4(bst, bsh, RTK_TXCFG) &
+ RTK_TXCFG_HWREV;
+ bus_space_unmap(bst, bsh, bsize);
if (t->rtk_basetype == hwrev)
return 2; /* defeat rtk(4) */
}
@@ -215,11 +244,14 @@
const char *intrstr = NULL;
const struct rtk_type *t;
const struct rtk_hwrev *hw_rev;
- int hwrev;
+ uint32_t hwrev;
int error = 0;
int pmreg;
+ boolean_t ioh_valid, memh_valid;
pcireg_t command;
- bus_size_t bsize;
+ bus_space_tag_t iot, memt;
+ bus_space_handle_t ioh, memh;
+ bus_size_t iosize, memsize, bsize;
/*
@@ -227,7 +259,7 @@
*/
if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
command = pci_conf_read(pc, pa->pa_tag, pmreg + PCI_PMCSR);
- if (command & RTK_PSTATE_MASK) {
+ if (command & PCI_PMCSR_STATE_MASK) {
u_int32_t iobase, membase, irq;
/* Save important PCI config data. */
@@ -238,9 +270,9 @@
/* Reset the power state. */
aprint_normal("%s: chip is is in D%d power mode "
"-- setting to D0\n", sc->sc_dev.dv_xname,
- command & RTK_PSTATE_MASK);
+ command & PCI_PMCSR_STATE_MASK);
- command &= ~RTK_PSTATE_MASK;
+ command &= ~PCI_PMCSR_STATE_MASK;
pci_conf_write(pc, pa->pa_tag,
pmreg + PCI_PMCSR, command);
@@ -258,19 +290,23 @@
command |= PCI_COMMAND_MASTER_ENABLE;
pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
-#ifdef RE_USEIOSPACE
- if (pci_mapreg_map(pa, RTK_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
- &sc->rtk_btag, &sc->rtk_bhandle, NULL, &bsize)) {
- aprint_error("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
+ ioh_valid = (pci_mapreg_map(pa, RTK_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
+ &iot, &ioh, NULL, &iosize) == 0);
+ memh_valid = (pci_mapreg_map(pa, RTK_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
+ &memt, &memh, NULL, &memsize) == 0);
+ if (ioh_valid) {
+ sc->rtk_btag = iot;
+ sc->rtk_bhandle = ioh;
+ bsize = iosize;
+ } else if (memh_valid) {
+ sc->rtk_btag = memt;
+ sc->rtk_bhandle = memh;
+ bsize = memsize;
+ } else {
+ aprint_error("%s: can't map registers\n", sc->sc_dev.dv_xname);
return;
}
-#else
- if (pci_mapreg_map(pa, RTK_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
- &sc->rtk_btag, &sc->rtk_bhandle, NULL, &bsize)) {
- aprint_error("%s: can't map mem space\n", sc->sc_dev.dv_xname);
- return;
- }
-#endif
+
t = re_devs;
hwrev = CSR_READ_4(sc, RTK_TXCFG) & RTK_TXCFG_HWREV;
@@ -325,24 +361,27 @@
re_attach(sc);
/*
- * Perform hardware diagnostic.
- * XXX: this diagnostic only makes sense for attachemnts with 64-bit
- * busses: PCI, but not CardBus.
+ * Perform hardware diagnostic on the original RTL8169.
+ * Some 32-bit cards were incorrectly wired and would
+ * malfunction if plugged into a 64-bit slot.
*/
- error = re_diag(sc);
- if (error) {
- aprint_error(
- "%s: attach aborted due to hardware diag failure\n",
- sc->sc_dev.dv_xname);
-
- re_detach(sc);
+ if (hwrev == RTK_HWREV_8169) {
+ error = re_diag(sc);
+ if (error) {
+ aprint_error(
+ "%s: attach aborted due to hardware diag failure\n",
+ sc->sc_dev.dv_xname);
+
+ re_detach(sc);
+
+ if (psc->sc_ih != NULL) {
+ pci_intr_disestablish(pc, psc->sc_ih);
+ psc->sc_ih = NULL;
+ }
- if (psc->sc_ih != NULL) {
- pci_intr_disestablish(pc, psc->sc_ih);
- psc->sc_ih = NULL;
+ if (bsize)
+ bus_space_unmap(sc->rtk_btag, sc->rtk_bhandle,
+ bsize);
}
-
- if (bsize)
- bus_space_unmap(sc->rtk_btag, sc->rtk_bhandle, bsize);
}
}
Index: dev/pci/if_rtk_pci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_rtk_pci.c,v
retrieving revision 1.22.4.1
diff -u -r1.22.4.1 if_rtk_pci.c
--- dev/pci/if_rtk_pci.c 17 Mar 2006 15:24:00 -0000 1.22.4.1
+++ dev/pci/if_rtk_pci.c 11 Feb 2007 03:42:02 -0000
@@ -82,7 +82,7 @@
* on the part of Realtek. Memory mapped mode does appear to work on
* uniprocessor systems though.
*/
-#ifndef dreamcast /* XXX */
+#if !defined(__sh__) /* XXX: dreamcast, landisk */
#define RTK_USEIOSPACE
#endif
@@ -178,15 +178,15 @@
printf("\n");
panic("rtk_pci_attach: impossible");
}
- printf(": %s\n", t->rtk_name);
+ printf(": %s (rev. 0x%02x)\n", t->rtk_name, PCI_REVISION(pa->pa_class));
/*
* Handle power management nonsense.
*/
if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
- command = pci_conf_read(pc, pa->pa_tag, pmreg + 4);
- if (command & RTK_PSTATE_MASK) {
+ command = pci_conf_read(pc, pa->pa_tag, pmreg + PCI_PMCSR);
+ if (command & PCI_PMCSR_STATE_MASK) {
pcireg_t iobase, membase, irq;
/* Save important PCI config data. */
@@ -197,9 +197,10 @@
/* Reset the power state. */
printf("%s: chip is in D%d power mode "
"-- setting to D0\n", sc->sc_dev.dv_xname,
- command & RTK_PSTATE_MASK);
- command &= 0xFFFFFFFC;
- pci_conf_write(pc, pa->pa_tag, pmreg + 4, command);
+ command & PCI_PMCSR_STATE_MASK);
+ command &= ~PCI_PMCSR_STATE_MASK;
+ pci_conf_write(pc, pa->pa_tag,
+ pmreg + PCI_PMCSR, command);
/* Restore PCI config data. */
pci_conf_write(pc, pa->pa_tag, RTK_PCI_LOIO, iobase);
Index: dev/pci/pcidevs
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pcidevs,v
retrieving revision 1.701.2.39
diff -u -r1.701.2.39 pcidevs
--- dev/pci/pcidevs 20 Nov 2006 15:49:38 -0000 1.701.2.39
+++ dev/pci/pcidevs 11 Feb 2007 03:42:04 -0000
@@ -2579,13 +2579,17 @@
/* RATOC Systems products */
product RATOC REXPCI31 0x0853 REX PCI-31/33 SCSI
-/* Realtek (Creative Labs?) products */
-product REALTEK RT8029 0x8029 8029 Ethernet
-product REALTEK RT8129 0x8129 8129 10/100 Ethernet
+/* Realtek products */
+product REALTEK RT8029 0x8029 8029 Ethernet
+product REALTEK RT8100 0x8100 8100 Ethernet
+product REALTEK RT8129 0x8129 8129 10/100 Ethernet
+product REALTEK RT8101E 0x8136 8101E Ethernet
product REALTEK RT8138 0x8138 8138 10/100 Ethernet
product REALTEK RT8139B 0x8138 8139B 10/100 Ethernet
product REALTEK RT8139 0x8139 8139 10/100 Ethernet
-product REALTEK RT8169 0x8169 8169 10/100/1000 Ethernet
+product REALTEK RT8169SC 0x8167 8169SC/8110SC 10/100/1000 Ethernet
+product REALTEK RT8168 0x8168 8168B/8111B 10/100/1000 Ethernet
+product REALTEK RT8169 0x8169 8169/S/SB 10/100/1000 Ethernet
product REALTEK RT8180 0x8180 8180 802.11b
/* RICOH products */
Index: dev/pci/pcidevs.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pcidevs.h,v
retrieving revision 1.702.2.37
diff -u -r1.702.2.37 pcidevs.h
--- dev/pci/pcidevs.h 20 Nov 2006 15:51:12 -0000 1.702.2.37
+++ dev/pci/pcidevs.h 11 Feb 2007 03:42:06 -0000
@@ -2586,13 +2586,17 @@
/* RATOC Systems products */
#define PCI_PRODUCT_RATOC_REXPCI31 0x0853 /* REX PCI-31/33 SCSI */
-/* Realtek (Creative Labs?) products */
+/* Realtek products */
#define PCI_PRODUCT_REALTEK_RT8029 0x8029 /* 8029 Ethernet */
+#define PCI_PRODUCT_REALTEK_RT8100 0x8100 /* 8100 Ethernet */
#define PCI_PRODUCT_REALTEK_RT8129 0x8129 /* 8129 10/100 Ethernet */
+#define PCI_PRODUCT_REALTEK_RT8101E 0x8136 /* 8101E Ethernet */
#define PCI_PRODUCT_REALTEK_RT8138 0x8138 /* 8138 10/100 Ethernet */
#define PCI_PRODUCT_REALTEK_RT8139B 0x8138 /* 8139B 10/100 Ethernet */
#define PCI_PRODUCT_REALTEK_RT8139 0x8139 /* 8139 10/100 Ethernet */
-#define PCI_PRODUCT_REALTEK_RT8169 0x8169 /* 8169 10/100/1000 Ethernet */
+#define PCI_PRODUCT_REALTEK_RT8169SC 0x8167 /* 8169SC/8110SC 10/100/1000 Ethernet */
+#define PCI_PRODUCT_REALTEK_RT8168 0x8168 /* 8168B/8111B 10/100/1000 Ethernet */
+#define PCI_PRODUCT_REALTEK_RT8169 0x8169 /* 8169/S/SB 10/100/1000 Ethernet */
#define PCI_PRODUCT_REALTEK_RT8180 0x8180 /* 8180 802.11b */
/* RICOH products */
Index: dev/pci/pcidevs_data.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pcidevs_data.h,v
retrieving revision 1.700.2.37
diff -u -r1.700.2.37 pcidevs_data.h
--- dev/pci/pcidevs_data.h 20 Nov 2006 15:51:12 -0000 1.700.2.37
+++ dev/pci/pcidevs_data.h 11 Feb 2007 03:42:08 -0000
@@ -8700,10 +8700,18 @@
"8029 Ethernet",
},
{
+ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8100,
+ "8100 Ethernet",
+ },
+ {
PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8129,
"8129 10/100 Ethernet",
},
{
+ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8101E,
+ "8101E Ethernet",
+ },
+ {
PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8138,
"8138 10/100 Ethernet",
},
@@ -8716,8 +8724,16 @@
"8139 10/100 Ethernet",
},
{
+ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169SC,
+ "8169SC/8110SC 10/100/1000 Ethernet",
+ },
+ {
+ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8168,
+ "8168B/8111B 10/100/1000 Ethernet",
+ },
+ {
PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169,
- "8169 10/100/1000 Ethernet",
+ "8169/S/SB 10/100/1000 Ethernet",
},
{
PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8180,
@@ -10904,4 +10920,4 @@
"Video Controller",
},
};
-const int pci_nproducts = 2143;
+const int pci_nproducts = 2147;
--- /dev/null 2007-02-11 11:35:08.000000000 +0900
+++ dev/mii/rlphy.c 2007-02-11 12:17:29.000000000 +0900
@@ -0,0 +1,336 @@
+/* $NetBSD: rlphy.c,v 1.12 2006/11/16 01:33:06 christos Exp $ */
+/* $OpenBSD: rlphy.c,v 1.20 2005/07/31 05:27:30 pvalchev Exp $ */
+
+/*
+ * Copyright (c) 1998, 1999 Jason L. Wright (jason@thought.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Driver for the internal PHY found on RTL8139 based nics, based
+ * on drivers for the 'exphy' (Internal 3Com phys) and 'nsphy'
+ * (National Semiconductor DP83840).
+ */
+
+/*
+ * Ported to NetBSD by Juan Romero Pardines <xtraeme@NetBSD.org>
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/mii/miidevs.h>
+#include <machine/bus.h>
+#include <dev/ic/rtl81x9reg.h>
+
+int rlphymatch(struct device *, struct cfdata *, void *);
+void rlphyattach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(rlphy, sizeof(struct mii_softc),
+ rlphymatch, rlphyattach, mii_phy_detach, mii_phy_activate);
+
+int rlphy_service(struct mii_softc *, struct mii_data *, int);
+void rlphy_status(struct mii_softc *);
+
+const struct mii_phy_funcs rlphy_funcs = {
+ rlphy_service, rlphy_status, mii_phy_reset,
+};
+
+static const struct mii_phydesc rlphys[] = {
+ { MII_OUI_yyREALTEK, MII_MODEL_yyREALTEK_RTL8201L,
+ MII_STR_yyREALTEK_RTL8201L },
+ { MII_OUI_ICPLUS, MII_MODEL_ICPLUS_IP101,
+ MII_STR_ICPLUS_IP101 },
+
+ { 0, 0,
+ NULL },
+};
+
+int
+rlphymatch(struct device *parent, struct cfdata *match, void *aux)
+{
+ struct mii_attach_args *ma = aux;
+
+ if (mii_phy_match(ma, rlphys) != NULL)
+ return (10);
+
+ if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 ||
+ MII_MODEL(ma->mii_id2) != 0)
+ return 0;
+
+ if (strcmp(parent->dv_cfdata->cf_name, "rtk") != 0 &&
+ strcmp(parent->dv_cfdata->cf_name, "re") != 0)
+ return 0;
+
+ /*
+ * A "real" phy should get preference, but on the 8139 there
+ * is no phyid register.
+ */
+ return 5;
+}
+
+void
+rlphyattach(struct device *parent, struct device *self, void *aux)
+{
+ struct mii_softc *sc = (void *)self;
+ struct mii_attach_args *ma = aux;
+ struct mii_data *mii = ma->mii_data;
+
+ if (MII_MODEL(ma->mii_id2) == MII_MODEL_yyREALTEK_RTL8201L) {
+ aprint_normal(": %s, rev. %d\n", MII_STR_yyREALTEK_RTL8201L,
+ MII_REV(ma->mii_id2));
+ } else
+ aprint_normal(": Realtek internal PHY\n");
+
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_funcs = &rlphy_funcs;
+ sc->mii_pdata = mii;
+ sc->mii_flags = ma->mii_flags;
+
+ sc->mii_flags |= MIIF_NOISOLATE;
+
+ PHY_RESET(sc);
+
+ aprint_normal("%s: ", sc->mii_dev.dv_xname);
+ sc->mii_capabilities =
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ if (sc->mii_capabilities & BMSR_MEDIAMASK)
+ mii_phy_add_media(sc);
+ aprint_normal("\n");
+}
+
+int
+rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
+{
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+
+ int rv;
+
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return ENXIO;
+
+ /*
+ * Can't isolate the RTL8139 phy, so it has to be the only one.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ panic("rlphy_service: attempt to isolate phy");
+
+ switch (cmd) {
+ case MII_POLLSTAT:
+ break;
+
+ case MII_MEDIACHG:
+ /*
+ * If the interface is not up, don't do anything.
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ break;
+
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
+ case IFM_AUTO:
+ /*
+ * If we're already in auto mode, just return.
+ */
+ if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
+ return (0);
+ (void) mii_phy_auto(sc, 0);
+ break;
+ case IFM_100_T4:
+ /*
+ * XXX Not supported as a manual setting right now.
+ */
+ return (EINVAL);
+ default:
+ /*
+ * BMCR data is stored in the ifmedia entry.
+ */
+ switch (ife->ifm_media &
+ (IFM_TMASK|IFM_NMASK|IFM_FDX)) {
+ case IFM_ETHER|IFM_10_T:
+ rv = ANAR_10|ANAR_CSMA;
+ break;
+ case IFM_ETHER|IFM_10_T|IFM_FDX:
+ rv = ANAR_10_FD|ANAR_CSMA;
+ break;
+ case IFM_ETHER|IFM_100_TX:
+ rv = ANAR_TX|ANAR_CSMA;
+ break;
+ case IFM_ETHER|IFM_100_TX|IFM_FDX:
+ rv = ANAR_TX_FD|ANAR_CSMA;
+ break;
+ case IFM_ETHER|IFM_100_T4:
+ rv = ANAR_T4|ANAR_CSMA;
+ break;
+ default:
+ rv = 0;
+ break;
+ }
+
+ PHY_WRITE(sc, MII_ANAR, rv);
+ PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
+ }
+ break;
+
+ case MII_TICK:
+ /*
+ * Is the interface even up?
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ return (0);
+
+ /*
+ * Only used for autonegotiation.
+ */
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ break;
+
+ /*
+ * The RealTek PHY's autonegotiation doesn't need to be
+ * kicked; it continues in the background.
+ */
+ break;
+
+ case MII_DOWN:
+ mii_phy_down(sc);
+ return (0);
+ }
+
+ /* Update the media status. */
+ mii_phy_status(sc);
+
+ /* Callback if something changed. */
+ mii_phy_update(sc, cmd);
+ return (0);
+}
+
+void
+rlphy_status(struct mii_softc *sc)
+{
+ struct mii_data *mii = sc->mii_pdata;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ int bmsr, bmcr, anlpar;
+
+ mii->mii_media_status = IFM_AVALID;
+ mii->mii_media_active = IFM_ETHER;
+
+ bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if (bmsr & BMSR_LINK)
+ mii->mii_media_status |= IFM_ACTIVE;
+
+ bmcr = PHY_READ(sc, MII_BMCR);
+ if (bmcr & BMCR_ISO) {
+ mii->mii_media_active |= IFM_NONE;
+ mii->mii_media_status = 0;
+ return;
+ }
+
+ if (bmcr & BMCR_LOOP)
+ mii->mii_media_active |= IFM_LOOP;
+
+ if (bmcr & BMCR_AUTOEN) {
+ /*
+ * NWay autonegotiation takes the highest-order common
+ * bit of the ANAR and ANLPAR (i.e. best media advertised
+ * both by us and our link partner).
+ */
+ if ((bmsr & BMSR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+
+ if ((anlpar = PHY_READ(sc, MII_ANAR) &
+ PHY_READ(sc, MII_ANLPAR))) {
+ if (anlpar & ANLPAR_T4)
+ mii->mii_media_active |= IFM_100_T4;
+ else if (anlpar & ANLPAR_TX_FD)
+ mii->mii_media_active |= IFM_100_TX|IFM_FDX;
+ else if (anlpar & ANLPAR_TX)
+ mii->mii_media_active |= IFM_100_TX;
+ else if (anlpar & ANLPAR_10_FD)
+ mii->mii_media_active |= IFM_10_T|IFM_FDX;
+ else if (anlpar & ANLPAR_10)
+ mii->mii_media_active |= IFM_10_T;
+ else
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+
+ /*
+ * If the other side doesn't support NWAY, then the
+ * best we can do is determine if we have a 10Mbps or
+ * 100Mbps link. There's no way to know if the link
+ * is full or half duplex, so we default to half duplex
+ * and hope that the user is clever enough to manually
+ * change the media settings if we're wrong.
+ */
+
+ /*
+ * The RealTek PHY supports non-NWAY link speed
+ * detection, however it does not report the link
+ * detection results via the ANLPAR or BMSR registers.
+ * (What? RealTek doesn't do things the way everyone
+ * else does? I'm just shocked, shocked I tell you.)
+ * To determine the link speed, we have to do one
+ * of two things:
+ *
+ * - If this is a standalone RealTek RTL8201(L) PHY,
+ * we can determine the link speed by testing bit 0
+ * in the magic, vendor-specific register at offset
+ * 0x19.
+ *
+ * - If this is a RealTek MAC with integrated PHY, we
+ * can test the 'SPEED10' bit of the MAC's media status
+ * register.
+ */
+ if (strcmp("rtk",
+ sc->mii_dev.dv_parent->dv_cfdata->cf_name)
+ == 0) {
+ if (PHY_READ(sc, RTK_MEDIASTAT) & RTK_MEDIASTAT_SPEED10)
+ mii->mii_media_active |= IFM_10_T;
+ else
+ mii->mii_media_active |= IFM_100_TX;
+ } else {
+ if (PHY_READ(sc, 0x0019) & 0x01)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ }
+
+ } else
+ mii->mii_media_active = ife->ifm_media;
+}
---
Izumi Tsutsui