From owner-freebsd-bugs Fri Mar 1 15: 0:42 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 5576F37B41C for ; Fri, 1 Mar 2002 15:00:10 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id g21N0AI89385; Fri, 1 Mar 2002 15:00:10 -0800 (PST) (envelope-from gnats) Received: from selene.drwilco.net (docwilco.xs4all.nl [213.84.68.230]) by hub.freebsd.org (Postfix) with ESMTP id 9CD7737B402 for ; Fri, 1 Mar 2002 14:50:52 -0800 (PST) Received: (from root@localhost) by selene.drwilco.net (8.11.6/8.11.6) id g21MooW00753; Fri, 1 Mar 2002 23:50:50 +0100 (CET) (envelope-from drwilco) Message-Id: <200203012250.g21MooW00753@selene.drwilco.net> Date: Fri, 1 Mar 2002 23:50:50 +0100 (CET) From: "Rogier R. Mulhuijzen" Reply-To: "Rogier R. Mulhuijzen" To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.113 Subject: kern/35466: xe driver can not read CIS tuples Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >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 >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: 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: on pcic0 pcic1: 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: 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 #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -135,6 +137,8 @@ #include #include +#include +#include #include "card_if.h" #include @@ -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