kern/50644: [PATCH] Update xe driver: multicast, hardware
setup, etc.
Scott Mitchell
scott+freebsd at fishballoon.org
Sun Jun 15 05:10:19 PDT 2003
The following reply was made to PR kern/50644; it has been noted by GNATS.
From: Scott Mitchell <scott+freebsd at fishballoon.org>
To: FreeBSD-gnats-submit at FreeBSD.org
Cc: scott+freebsd at fishballoon.org
Subject: Re: kern/50644: [PATCH] Update xe driver: multicast, hardware setup, etc.
Date: Sun, 15 Jun 2003 13:08:02 +0100
This patch adds support for the Ethernet side of the CEM28 and CEM33 10Mbps
Ethernet/modem combo cards. The driver now works well with all the cards I
have to test against (a CE2, CE3, CEM28 and CEM33).
There are a couple of gotchas to be aware of:
- My CEM28 (and all others, as far as I know) has its MAC address in a
non-standard location in the CIS. Ultimately some quirk code will be
required to deal with this, but for now I've just added 'ether 0x98' to
the relevant pccard.conf entry.
- I/O port selection for the CEM28 and CEM33 is a bit crufty -- it needs to
find a port range adjacent to whichever sio port range the pccard layer
has picked from the CIS config entries. I needed to disable one of the
onboard serial ports on my laptop to free up enough I/O space in the
right place. Some combination of disabling ports and picking the right
CIS config entry will probably be required.
- I still have no idea how all of this works (or doesn't) with NEWCARD.
Scott
cards.
Index: src/sys/dev/xe/if_xe.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/xe/if_xe.c,v
retrieving revision 1.35.10000.4
diff -u -r1.35.10000.4 if_xe.c
--- src/sys/dev/xe/if_xe.c 24 May 2003 17:04:06 -0000 1.35.10000.4
+++ src/sys/dev/xe/if_xe.c 15 Jun 2003 11:42:39 -0000
@@ -573,13 +573,22 @@
ifp = &scp->arpcom.ac_if;
/* Disable interrupts */
- XE_OUTB(XE_CR, 0);
+ if (scp->mohawk)
+ XE_OUTB(XE_CR, 0);
/* Cache current register page */
psr = XE_INB(XE_PR);
/* Read ISR to see what caused this interrupt */
- if ((isr = XE_INB(XE_ISR)) != 0) {
+ while ((isr = XE_INB(XE_ISR)) != 0) {
+
+ /* 0xff might mean the card is no longer around */
+ if (isr == 0xff) {
+#if XE_DEBUG > 2
+ device_printf(scp->dev, "intr: interrupt received for missing card?\n");
+#endif
+ break;
+ }
/* Read other status registers */
XE_SELECT_PAGE(0x40);
@@ -658,7 +667,7 @@
XE_OUTB(XE_CR, XE_CR_RESTART_TX);
}
/* Transmit underrun -- increase early transmit threshold */
- if (txst0 & XE_TXST0_TX_UNDERRUN) {
+ if (txst0 & XE_TXST0_TX_UNDERRUN && scp->mohawk) {
device_printf(scp->dev, "transmit underrun");
if (scp->tx_thres < ETHER_MAX_LEN) {
if ((scp->tx_thres += 64) > ETHER_MAX_LEN)
@@ -714,6 +723,10 @@
len = XE_INW(XE_RBC) - ETHER_CRC_LEN;
+#if XE_DEBUG > 2
+ device_printf(scp->dev, "intr: receive length = %d\n", len);
+#endif
+
if (len == 0) {
ifp->if_iqdrops++;
continue;
@@ -807,7 +820,9 @@
/* Clear receiver overruns now we have some free buffer space */
if (rst0 & XE_RST0_RX_OVERRUN) {
+#if XE_DEBUG > 0
device_printf(scp->dev, "receive overrun\n");
+#endif
ifp->if_ierrors++;
scp->mibdata.dot3StatsInternalMacReceiveErrors++;
XE_OUTB(XE_CR, XE_CR_CLEAR_OVERRUN);
@@ -1922,17 +1937,18 @@
xe_activate(device_t dev)
{
struct xe_softc *sc = device_get_softc(dev);
- int start, err;
+ int start, err, i;
#if XE_DEBUG > 1
device_printf(dev, "activate\n");
#endif
- if (!sc->dingo) {
+ if (!sc->modem) {
sc->port_rid = 0; /* 0 is managed by pccard */
sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
&sc->port_rid, 0, ~0, 16, RF_ACTIVE);
- } else {
+ }
+ else if (sc->dingo) {
/*
* Find a 16 byte aligned ioport for the card.
*/
@@ -1953,12 +1969,59 @@
sc->port_res);
start = (rman_get_start(sc->port_res) + 15) & ~0xf;
} while (1);
+#if XE_DEBUG > 1
+ device_printf(dev, "RealPort port 0x%0lx, size 0x%0lx\n",
+ bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
+ bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid));
+#endif /* XE_DEBUG */
+ }
+ else if (sc->ce2) {
+ /*
+ * Find contiguous I/O port for the Ethernet function on CEM2 and
+ * CEM3 cards. We allocate window 0 wherever pccard has decided
+ * it should be, then find an available window adjacent to it for
+ * the second function. Not sure that both windows are actually
+ * needed.
+ */
+#if XE_DEBUG > 0
+ device_printf(dev, "Finding I/O port for CEM2/CEM3\n");
+#endif
+ sc->ce2_port_rid = 0; /* 0 is managed by pccard */
+ sc->ce2_port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->ce2_port_rid, 0, ~0,
+ 8, RF_ACTIVE);
+ if (!sc->ce2_port_res) {
+#if XE_DEBUG > 0
+ device_printf(dev, "Cannot allocate I/O port for modem\n");
+#endif
+ return ENOMEM;
+ }
+
+ sc->port_rid = 1;
+ start = bus_get_resource_start(dev, SYS_RES_IOPORT,
+ sc->ce2_port_rid);
+ for (i = 0; i < 2; i++) {
+ start += (i == 0 ? 8 : -24);
+ sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->port_rid, start,
+ start + 18, 18, RF_ACTIVE);
+ if (sc->port_res == 0)
+ continue; /* Failed, try again if possible */
+ if (bus_get_resource_start(dev, SYS_RES_IOPORT,
+ sc->port_rid) == start)
+ break; /* Success! */
+
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
+ sc->port_res);
+ sc->port_res = 0;
+ }
#if XE_DEBUG > 2
- device_printf(dev, "port 0x%0lx, size 0x%0lx\n",
+ device_printf(dev, "CEM2/CEM3 port 0x%0lx, size 0x%0lx\n",
bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid));
#endif /* XE_DEBUG */
}
+
if (!sc->port_res) {
#if XE_DEBUG > 0
device_printf(dev, "Cannot allocate ioport\n");
@@ -1995,6 +2058,7 @@
#if XE_DEBUG > 1
device_printf(dev, "deactivate\n");
#endif
+ xe_disable_intr(sc);
if (sc->intrhand)
bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
@@ -2003,6 +2067,10 @@
bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
sc->port_res);
sc->port_res = 0;
+ if (sc->ce2_port_res)
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->ce2_port_rid,
+ sc->ce2_port_res);
+ sc->ce2_port_res = 0;
if (sc->irq_res)
bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid,
sc->irq_res);
Index: src/sys/dev/xe/if_xe_pccard.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/xe/if_xe_pccard.c,v
retrieving revision 1.7.10000.2
diff -u -r1.7.10000.2 if_xe_pccard.c
--- src/sys/dev/xe/if_xe_pccard.c 24 May 2003 17:04:06 -0000 1.7.10000.2
+++ src/sys/dev/xe/if_xe_pccard.c 24 May 2003 18:14:19 -0000
@@ -25,7 +25,7 @@
*
*
* xe pccard interface driver
- * $FreeBSD: src/sys/dev/xe/if_xe_pccard.c,v 1.7.10000.2 2003/05/24 17:04:06 scott Exp $
+ * $FreeBSD: src/sys/dev/xe/if_xe_pccard.c,v 1.7.10000.1 2003/03/25 21:02:31 scott Exp $
*/
#include <sys/param.h>
@@ -118,18 +118,19 @@
/*
* Prototypes
*/
-static int xe_cem56fix(device_t dev);
+static int xe_cemfix(device_t dev);
static struct xe_vendor_table *xe_vendor_lookup(u_int32_t devid,
struct xe_vendor_table *tbl);
static struct xe_card_type_table *xe_card_type_lookup(u_int32_t devid,
struct xe_card_type_table *tbl);
/*
- * Fixing for RealPort cards - they need a little furtling to get the
- * ethernet working. But this codes don't work well in NEWCARD.
+ * Fixing for CEM2, CEM3 and CEM56/REM56 cards. These need some magic to
+ * enable the Ethernet function, which isn't mentioned anywhere in the CIS.
+ * Despite the register names, most of this isn't Dingo-specific.
*/
static int
-xe_cem56fix(device_t dev)
+xe_cemfix(device_t dev)
{
struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev);
bus_space_tag_t bst;
@@ -139,10 +140,10 @@
int ioport;
#if XE_DEBUG > 1
- device_printf(dev, "cem56fix\n");
+ device_printf(dev, "cemfix\n");
#endif
- device_printf(dev, "Realport port 0x%0lx, size 0x%0lx\n",
+ device_printf(dev, "CEM I/O port 0x%0lx, size 0x%0lx\n",
bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid));
@@ -168,12 +169,14 @@
bus_space_write_1(bst, bsh, DINGO_EBAR0, ioport & 0xff);
bus_space_write_1(bst, bsh, DINGO_EBAR1, (ioport >> 8) & 0xff);
- bus_space_write_1(bst, bsh, DINGO_DCOR0, DINGO_DCOR0_SF_INT);
- bus_space_write_1(bst, bsh, DINGO_DCOR1, DINGO_DCOR1_INT_LEVEL |
- DINGO_DCOR1_EEDIO);
- bus_space_write_1(bst, bsh, DINGO_DCOR2, 0x00);
- bus_space_write_1(bst, bsh, DINGO_DCOR3, 0x00);
- bus_space_write_1(bst, bsh, DINGO_DCOR4, 0x00);
+ if (sc->dingo) {
+ bus_space_write_1(bst, bsh, DINGO_DCOR0, DINGO_DCOR0_SF_INT);
+ bus_space_write_1(bst, bsh, DINGO_DCOR1, DINGO_DCOR1_INT_LEVEL |
+ DINGO_DCOR1_EEDIO);
+ bus_space_write_1(bst, bsh, DINGO_DCOR2, 0x00);
+ bus_space_write_1(bst, bsh, DINGO_DCOR3, 0x00);
+ bus_space_write_1(bst, bsh, DINGO_DCOR4, 0x00);
+ }
bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
@@ -313,8 +316,9 @@
return (err);
/* Hack RealPorts into submission */
- if (scp->dingo && xe_cem56fix(dev) < 0) {
- device_printf(dev, "Unable to fix your RealPort\n");
+ if (scp->modem && xe_cemfix(dev) < 0) {
+ device_printf(dev, "Unable to fix your %s combo card\n",
+ scp->card_type);
xe_deactivate(dev);
return (ENODEV);
}
Index: src/sys/dev/xe/if_xevar.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/xe/if_xevar.h,v
retrieving revision 1.3.10000.2
diff -u -r1.3.10000.2 if_xevar.h
--- src/sys/dev/xe/if_xevar.h 24 May 2003 17:04:06 -0000 1.3.10000.2
+++ src/sys/dev/xe/if_xevar.h 24 May 2003 17:53:36 -0000
@@ -49,6 +49,8 @@
int irq_rid;
struct resource *port_res;
int port_rid;
+ struct resource *ce2_port_res;
+ int ce2_port_rid;
int srev; /* Silicon revision */
int tx_queued; /* Packets currently waiting to transmit */
int tx_tpr; /* Last value of TPR reg on card */
More information about the freebsd-bugs
mailing list