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