Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 1 Mar 2002 23:50:50 +0100 (CET)
From:      "Rogier R. Mulhuijzen" <drwilco@drwilco.net>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/35466: xe driver can not read CIS tuples
Message-ID:  <200203012250.g21MooW00753@selene.drwilco.net>

next in thread | raw e-mail | index | archive | help

>Number:         35466
>Category:       kern
>Synopsis:       xe driver can not read CIS tuples
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Mar 01 15:00:10 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Rogier R. Mulhuijzen <drwilco@drwilco.net>
>Release:        FreeBSD 4.5-STABLE i386
>Organization:
>Environment:
OS: FreeBSD selene.drwilco.net 4.5-STABLE FreeBSD 4.5-STABLE #5: Fri Mar 1 22:22:44 CET 2002 root@selene.drwilco.net:/usr/src/sys/compile/SELENE i386
Hardware: IBM ThinkPad A22m, Xircom RealPort Ethernet 10/100+Modem 56 (REM56G-100)
Relevant dmesg output:
pcic0: <TI PCI-1450 PCI-CardBus Bridge> mem 0x50000000-0x50000fff irq 11 at device 2.0 on pci0
pcic0: TI12XX PCI Config Reg: [ring enable][speaker enable][pwr save][FUNC pci int + CSC serial isa irq]
pccard0: <PC Card bus (classic)> on pcic0
pcic1: <TI PCI-1450 PCI-CardBus Bridge> mem 0x50100000-0x50100fff irq 11 at device 2.1 on pci0
pcic1: TI12XX PCI Config Reg: [ring enable][speaker enable][pwr save][FUNC pci int + CSC serial isa irq]
pccard1: <PC Card bus (classic)> on pcic1

PCCARD Memory address set to 0xd4000

>Description:
Xircom NIC is detected, but driver cannot attach, because it fails to read the CIS on its own. 

>How-To-Repeat:
Insert a Xircom NIC in a machine running FreeBSD 4.5
Not sure whether setting pccardmem to 0xd4000 is related.

>Fix:

Replace the use of bus_alloc_resource() and bus_space_read() for reading CIS with reads on the right card device (as the ed driver does in ed_pccard_memread())

or

Apply the patch below (also available at http://www.bsdchicks.com/xe.patch). This patch also makes the driver aware of the bootverbose option and adds a few debugging lines.


--- sys/dev/xe/if_xe.c	Fri Mar  1 21:50:37 2002
+++ sys/dev/xe/if_xe.c	Fri Mar  1 23:01:57 2002
@@ -112,12 +112,14 @@
 #include <sys/cdefs.h>
 #include <sys/errno.h>
 #include <sys/kernel.h>
+#include <sys/conf.h>
 #include <sys/mbuf.h>
 #include <sys/select.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/systm.h>
 #include <sys/uio.h>
+#include <sys/types.h>
 
 #include <sys/module.h>
 #include <sys/bus.h>
@@ -135,6 +137,8 @@
 #include <net/bpf.h>
 
 #include <dev/pccard/pccardvar.h>
+#include <pccard/cardinfo.h>
+#include <pccard/slot.h>
 #include "card_if.h"
 
 #include <dev/xe/if_xereg.h>
@@ -163,6 +167,7 @@
 #define XE_AUTONEG_100TX	3	/* Trying to force 100baseTX link */
 #define XE_AUTONEG_FAIL		4	/* Autonegotiation failed */
 
+#define CARD_MAJOR		50
 
 /*
  * Prototypes start here
@@ -211,11 +216,71 @@
 #define XE_MII_DUMP(scp)		xe_mii_dump((scp))
 static void      xe_reg_dump		(struct xe_softc *scp);
 static void      xe_mii_dump		(struct xe_softc *scp);
+static int xe_debug = XE_DEBUG;
 #else
 #define XE_REG_DUMP(scp)
 #define XE_MII_DUMP(scp)
+static int xe_debug = 0;
 #endif
 
+static int
+xe_pccard_memread(device_t dev, off_t offset, u_char *buf, int size) 
+{
+        struct pccard_devinfo *devi;
+        dev_t d;
+        struct iovec iov;
+        struct uio uios;
+    
+        devi = device_get_ivars(dev);
+                        
+        iov.iov_base = buf;
+        iov.iov_len = size;
+                                           
+        uios.uio_iov = &iov;
+        uios.uio_iovcnt = 1;
+        uios.uio_offset = offset;
+        uios.uio_resid = size;
+        uios.uio_segflg = UIO_SYSSPACE;
+        uios.uio_rw = UIO_READ;
+        uios.uio_procp = 0;
+
+        d = makedev(CARD_MAJOR, devi->slt->slotnum);
+        return devsw(d)->d_read(d, &uios, 0);
+}
+
+static u_char
+xe_read_byte(device_t dev, off_t offset) {
+        u_char buf;
+
+	xe_pccard_memread(dev, offset, &buf, 1);
+	return buf;
+}
+
+static int
+xe_write_byte(device_t dev, off_t offset, u_char byte)
+{
+        struct pccard_devinfo *devi;
+        dev_t d;
+        struct iovec iov;
+        struct uio uios;
+
+        devi = device_get_ivars(dev);
+
+        iov.iov_base = &byte;
+        iov.iov_len = sizeof(byte);
+
+        uios.uio_iov = &iov;
+        uios.uio_iovcnt = 1;
+        uios.uio_offset = offset;
+        uios.uio_resid = sizeof(byte);
+        uios.uio_segflg = UIO_SYSSPACE;
+        uios.uio_rw = UIO_WRITE;
+        uios.uio_procp = 0;
+
+        d = makedev(CARD_MAJOR, devi->slt->slotnum);
+        return devsw(d)->d_write(d, &uios, 0);
+}
+
 /*
  * Fixing for RealPort cards - they need a little furtling to get the
  * ethernet working
@@ -224,53 +289,29 @@
 xe_cem56fix(device_t dev)
 {
   struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev);
-  bus_space_tag_t bst;
-  bus_space_handle_t bsh;
-  struct resource *r;
-  int rid;
   int ioport;
 
-#ifdef XE_DEBUG
-  device_printf(dev, "Hacking your Realport, master\n");
-#endif
- 
-#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
-
-  rid = 0;
-  r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 4 << 10, RF_ACTIVE);
-  if (!r) {
-#if XE_DEBUG > 0
-    device_printf(dev, "Can't map in attribute memory\n");
-#endif
-    return -1;
+  if (xe_debug || bootverbose) {
+    device_printf(dev, "Hacking your Realport, master\n");
+    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));
   }
 
-  bsh = rman_get_bushandle(r);
-  bst = rman_get_bustag(r);
-
-  CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid,
-      PCCARD_A_MEM_ATTR);
-
-  bus_space_write_1(bst, bsh, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL |
-					  DINGO_ECOR_INT_ENABLE |
-					  DINGO_ECOR_IOB_ENABLE |
-               				  DINGO_ECOR_ETH_ENABLE);
+  xe_write_byte(dev, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL |
+				  DINGO_ECOR_INT_ENABLE |
+				  DINGO_ECOR_IOB_ENABLE |
+       				  DINGO_ECOR_ETH_ENABLE);
   ioport = bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid);
-  bus_space_write_1(bst, bsh, DINGO_EBAR0, ioport & 0xff);
-  bus_space_write_1(bst, bsh, DINGO_EBAR1, (ioport >> 8) & 0xff);
+  xe_write_byte(dev, DINGO_EBAR0, ioport & 0xff);
+  xe_write_byte(dev, 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 |
+  xe_write_byte(dev, DINGO_DCOR0, DINGO_DCOR0_SF_INT);
+  xe_write_byte(dev, 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);
+  xe_write_byte(dev, DINGO_DCOR2, 0x00);
+  xe_write_byte(dev, DINGO_DCOR3, 0x00);
+  xe_write_byte(dev, DINGO_DCOR4, 0x00);
 
   /* success! */
   return 0;
@@ -286,36 +327,19 @@
 xe_probe(device_t dev)
 {
   struct xe_softc *scp = (struct xe_softc *) device_get_softc(dev);
-  bus_space_tag_t bst;
-  bus_space_handle_t bsh;
   int buf;
   u_char ver_str[CISTPL_BUFSIZE>>1];
   off_t offs;
   int success, rc, i;
-  int rid;
-  struct resource *r;
+  int nulltpls = 0;
 
   success = 0;
 
-#ifdef XE_DEBUG
-  device_printf(dev, "xe: Probing\n");
-#endif
-
-  /* Map in the CIS */
-  rid = 0;
-  r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 4 << 10, RF_ACTIVE);
-  if (!r) {
-#ifdef XE_DEBUG
-    device_printf(dev, "Can't map in cis\n");
-#endif
-    return ENOMEM;
+  if (xe_debug || bootverbose) {
+    device_printf(dev, "Probing\n");
   }
-  bsh = rman_get_bushandle(r);
-  bst = rman_get_bustag(r);
-  buf = 0;
 
-  CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid,
-      PCCARD_A_MEM_ATTR);
+  buf = 0;
 
   /* Grep through CIS looking for relevant tuples */
   offs = 0;
@@ -326,9 +350,9 @@
     switch (CISTPL_TYPE(buf)) {
 
     case 0x15:	/* Grab version string (needed to ID some weird CE2's) */
-#if XE_DEBUG > 1
-      device_printf(dev, "Got version string (0x15)\n");
-#endif
+      if (xe_debug || bootverbose) {
+        device_printf(dev, "Got version string (0x15)\n");
+      }
       for (i = 0; i < CISTPL_LEN(buf); ver_str[i] = CISTPL_DATA(buf, i++));
       ver_str[i] = '\0';
       ver_str[(CISTPL_BUFSIZE>>1) - 1] = CISTPL_LEN(buf);
@@ -336,9 +360,9 @@
       break;
 
     case 0x20:	/* Figure out what type of card we have */
-#if XE_DEBUG > 1
-      device_printf(dev, "Got card ID (0x20)\n");
-#endif
+      if (xe_debug || bootverbose) {
+        device_printf(dev, "Got card ID (0x20)\n");
+      }
       vendor = CISTPL_DATA(buf, 0) + (CISTPL_DATA(buf, 1) << 8);
       rev = CISTPL_DATA(buf, 2);
       media = CISTPL_DATA(buf, 3);
@@ -357,15 +381,15 @@
       }
 
       if (!((prod & 0x40) && (media & 0x01))) {
-#if XE_DEBUG > 1
-	device_printf(dev, "Not a PCMCIA Ethernet card!\n");
-#endif
+        if (xe_debug || bootverbose) {
+	  device_printf(dev, "Not a PCMCIA Ethernet card!\n");
+        }
 	rc = ENODEV;		/* Not a PCMCIA Ethernet device */
       } else {
 	if (media & 0x10) {	/* Ethernet/modem cards */
-#if XE_DEBUG > 1
-	  device_printf(dev, "Card is Ethernet/modem combo\n");
-#endif
+          if (xe_debug || bootverbose) {
+	    device_printf(dev, "Card is Ethernet/modem combo\n");
+          }
 	  scp->modem = 1;
 	  switch (prod & 0x0f) {
 	  case 1:
@@ -391,9 +415,9 @@
 	    rc = ENODEV;
 	  }
 	} else {		/* Ethernet-only cards */
-#if XE_DEBUG > 1
-	  device_printf(dev, "Card is Ethernet only\n");
-#endif
+          if (xe_debug || bootverbose) {
+	    device_printf(dev, "Card is Ethernet only\n");
+          }
 	  switch (prod & 0x0f) {
 	  case 1:
 	    scp->card_type = "CE"; break;
@@ -415,31 +439,46 @@
       if ((CISTPL_LEN(buf) == 8) &&
 	  (CISTPL_DATA(buf, 0) == 0x04) &&
 	  (CISTPL_DATA(buf, 1) == ETHER_ADDR_LEN)) {
-#if XE_DEBUG > 1
-	device_printf(dev, "Got MAC address (0x22)\n");
-#endif
+        if (xe_debug || bootverbose) {
+	  device_printf(dev, "Got MAC address (0x22)\n");
+        }
 	for (i = 0; i < ETHER_ADDR_LEN; i++)
           scp->arpcom.ac_enaddr[i] = CISTPL_DATA(buf, i+2);
       }
       success++;
       break;
+    case 0x00:
+      nulltpls++;
+      break;
     default:
+#if XE_DEBUG > 1
+      if (CISTPL_TYPE(buf) != 0xff) {
+        device_printf(dev, "Unkown or worthless CIS: %x\n", CISTPL_TYPE(buf));
+      }
+#endif
       break;
     }
 
-    if (CISTPL_TYPE(buf) == 0xff)
+    if (CISTPL_TYPE(buf) == 0xff) {
       break;
+#if XE_DEBUG > 1
+      device_printf(dev, "End of CIS\n");
+#endif    
+    }
     /* Skip to next tuple */
     buf += ((CISTPL_LEN(buf) + 2) << 1);
 
   } while (1);
-
-  /* unmap the cis */
-  bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
+#if XE_DEBUG > 1
+  if (nulltpls)
+    device_printf(dev, "CIS null tuples found: %d\n", nulltpls);
+#endif
 
   /* Die now if something went wrong above */
-  if (success < 3)
+  if (success < 3) {
+    device_printf(dev, "Cannot find the CIS tuples needed to initialize\n");
     return ENXIO;
+  }
 
   /* Check for certain strange CE2's that look like CE's */
   if (strcmp(scp->card_type, "CE") == 0) {
--- sys/dev/xe/if_xevar.h	Thu Jun  1 03:23:53 2000
+++ sys/dev/xe/if_xevar.h	Fri Mar  1 21:52:56 2002
@@ -78,8 +78,8 @@
  * Horrid stuff for accessing CIS tuples
  */
 #define CISTPL_BUFSIZE		512
-#define CISTPL_TYPE(tpl)	bus_space_read_1(bst, bsh, tpl + 0)
-#define CISTPL_LEN(tpl)		bus_space_read_1(bst, bsh, tpl + 2)
-#define CISTPL_DATA(tpl,pos)	bus_space_read_1(bst, bsh, tpl+ 4 + ((pos)<<1))
+#define CISTPL_TYPE(tpl)	xe_read_byte(dev, tpl + 0)
+#define CISTPL_LEN(tpl)		xe_read_byte(dev, tpl + 2)
+#define CISTPL_DATA(tpl,pos)	xe_read_byte(dev, tpl+ 4 + ((pos)<<1))
 
 #endif /* DEV_XE_IF_XEVAR_H */

>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200203012250.g21MooW00753>