Date: Sun, 15 Jun 2003 05:10:17 -0700 (PDT) From: Scott Mitchell <scott+freebsd@fishballoon.org> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/50644: [PATCH] Update xe driver: multicast, hardware setup, etc. Message-ID: <200306151210.h5FCAHhS063485@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/50644; it has been noted by GNATS. From: Scott Mitchell <scott+freebsd@fishballoon.org> To: FreeBSD-gnats-submit@FreeBSD.org Cc: scott+freebsd@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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200306151210.h5FCAHhS063485>