From owner-freebsd-mobile@FreeBSD.ORG Sun May 2 04:01:31 2004 Return-Path: Delivered-To: freebsd-mobile@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3EE5516A4D0; Sun, 2 May 2004 04:01:31 -0700 (PDT) Received: from smtp.newipnet.com (5.Red-80-32-157.pooles.rima-tde.net [80.32.157.5]) by mx1.FreeBSD.org (Postfix) with ESMTP id B1EF743D31; Sun, 2 May 2004 04:01:27 -0700 (PDT) (envelope-from freebsd@newipnet.com) Received: by smtp.newipnet.com (ESMTP Server, from userid 511) id EDAC820519; Sun, 2 May 2004 13:01:25 +0200 (CEST) Received: from madre (madre.newipnet.com [192.168.128.4]) by smtp.newipnet.com (ESMTP Server) with ESMTP id 462A12051A; Sun, 2 May 2004 13:01:11 +0200 (CEST) Message-ID: <200405021259230046.12648609@192.168.128.16> X-Mailer: Courier 3.50.00.09.1097 (http://www.rosecitysoftware.com) (P) Date: Sun, 02 May 2004 12:59:23 +0200 From: "Carlos Velasco" To: "M. Warner Losh" , scott@uk.freebsd.org Content-Type: text/plain; charset="ISO-8859-1" X-Spam-Checker-Version: SpamAssassin 2.63 (2004-01-11) on atlas.newipnet.com X-Spam-Level: X-Spam-Status: No, hits=-104.9 required=5.0 tests=BAYES_00,USER_IN_WHITELIST autolearn=ham version=2.63 cc: freebsd-current@freebsd.org cc: freebsd-mobile@freebsd.org Subject: Modem + Network in Xircom cards, and maybe others X-BeenThere: freebsd-mobile@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Mobile computing with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 May 2004 11:01:31 -0000 Xircom cards with multiple functions are not MFC compliant, that makes them to fail in CURRENT and only one function works (last one in the CIS, Network). I have patched pccard to provide support for both functions. I have followed this behaviour: /* We have a non-MFC compliant card, it puts more * than 1 FUNCID in the CIS without LONGLINK. * a) We put the functions in the list ala MFC. * b) Copy last CFG entry for previous function, * not sure if this is right, but usually works. */ Also I have needed to tweak if_xe_pccard because it was claiming itself as the right driver when the function was serial and also another tweak to proper handling of matches. Patch works, however I'm seeing buffer overflows in sio when I issue a "ATI11" command with minicom (WinXP works fine wth this): sio4: 118 more interrupt-level buffer overflows (total 118) sio4: 162 more interrupt-level buffer overflows (total 280) In my laptop, cbb is taking irq11: sio4: at port 0x2e8-0x2ef irq 11 function 0 config 39 on pccard0 sio4: type 16550A sio4: unable to activate interrupt in fast mode - using normal mode ... xe0: at port 0x100-0x107 irq 11 function 1 config 63 on pccard0 xe0: [GIANT-LOCKED] xe0: Xircom CreditCard Ethernet 10/100 + Modem 56, version 0x55/0x05, 100Mbps capable, with modem xe0: Ethernet address: 00:10:a4:f6:2f:73 Issuing vmstat -i, I don't think irq11 is handling too many interrupts: interrupt total rate irq0: clk 9735 98 irq1: atkbd0 410 4 irq3: sio1 24 0 irq4: sio0 2 0 irq5: pcm0 1 0 irq6: fdc0 2 0 irq7: ppc0 1 0 irq8: rtc 12461 125 irq9: acpi0 1 0 irq11: cbb0 cbb1+ 167 1 irq13: npx0 1 0 irq14: ata0 2863 28 irq15: ata1 58 0 Total 25726 259 Also, I thought that it could be the network function to be the cause of overflow problem, so I hacked the code to leave only the sio alone, it didn't show any difference. I would need some help with this problem. Warner, I still needed to patch pccard to force 64k alignment for my TI1225 for this to work as my laptop hangs-up if i don't do it. Here's the patch, so long... diff -ru sys/dev/pccard/pccard.c sysnew/dev/pccard/pccard.c --- sys/dev/pccard/pccard.c Wed Mar 17 17:50:38 2004 +++ sysnew/dev/pccard/pccard.c Sat May 1 09:47:57 2004 @@ -955,8 +955,8 @@ struct pccard_softc *sc = PCCARD_SOFTC(bus); device_printf(bus, ""); - printf(" (manufacturer=0x%04x, product=0x%04x) at function %d\n", - sc->card.manufacturer, sc->card.product, func->number); + printf(" (manufacturer=0x%04x, product=0x%04x, prodext=0x%02x) at function %d\n", + sc->card.manufacturer, sc->card.product, sc->card.prodext, func->number); device_printf(bus, " CIS info: %s, %s, %s\n", sc->card.cis1_info[0], sc->card.cis1_info[1], sc->card.cis1_info[2]); return; @@ -1075,6 +1075,7 @@ int passthrough = (device_get_parent(child) != dev); int isdefault = (start == 0 && end == ~0UL && count == 1); struct resource *r = NULL; + u_int align; /* XXX I'm no longer sure this is right */ if (passthrough) { @@ -1090,8 +1091,15 @@ if (rle == NULL || rle->res == NULL) { /* Do we want this device to own it? */ /* XXX I think so, but that might be lame XXX */ + + /* force 64k page align */ + if (type == SYS_RES_MEMORY) + align = (flags & ~RF_ALIGNMENT_MASK) | + rman_make_alignment_flags(64*1024); + else + align = flags; r = bus_alloc_resource(dev, type, rid, start, end, - count, flags /* XXX aligment? */); + count, align); if (r == NULL) goto bad; resource_list_add(&dinfo->resources, type, *rid, diff -ru sys/dev/pccard/pccard_cis.c sysnew/dev/pccard/pccard_cis.c --- sys/dev/pccard/pccard_cis.c Mon Apr 12 20:56:34 2004 +++ sysnew/dev/pccard/pccard_cis.c Sat May 1 09:47:57 2004 @@ -96,6 +96,8 @@ state.pf = NULL; + state.card->mfc = 0; + tsleep(&state, 0, "pccard", hz); if (pccard_scan_cis(sc->dev, pccard_parse_cis_tuple, &state) == -1) @@ -663,6 +665,7 @@ * up. */ state->gotmfc = 1; + state->card->mfc = 1; break; #ifdef PCCARDCISDEBUG case CISTPL_DEVICE: @@ -803,6 +806,42 @@ STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf, pf_list); + } else if (state->pf->function != PCCARD_FUNCTION_UNSPEC) { + /* We have a non-MFC compliant card, it puts more + * than 1 FUNCID in the CIS without LONGLINK. + * a) We put the functions in the list ala MFC. + * b) Copy last CFG entry for previous function, + * not sure if this is right, but usually works. + */ + struct pccard_config_entry *cfe, *qcfe; + uint32_t ccr_base = state->pf->ccr_base; + uint32_t ccr_mask = state->pf->ccr_mask; + + cfe = NULL; + STAILQ_FOREACH(qcfe, &state->pf->cfe_head, cfe_list) { + if (qcfe->number == state->pf->last_config_index) { + cfe = (struct pccard_config_entry *) + malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT); + *cfe = *qcfe; + break; + } + } + + state->pf = malloc(sizeof(*state->pf), M_DEVBUF, + M_NOWAIT | M_ZERO); + state->pf->number = state->count++; + state->pf->last_config_index = cfe->number; + state->pf->ccr_base = ccr_base; + state->pf->ccr_mask = ccr_mask; + + STAILQ_INIT(&state->pf->cfe_head); + if (cfe) + STAILQ_INSERT_TAIL(&state->pf->cfe_head, + cfe, cfe_list); + + STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf, + pf_list); + } state->pf->function = pccard_tuple_read_1(tuple, 0); diff -ru sys/dev/pccard/pccardvar.h sysnew/dev/pccard/pccardvar.h --- sys/dev/pccard/pccardvar.h Sun Nov 2 20:18:19 2003 +++ sysnew/dev/pccard/pccardvar.h Sat May 1 09:47:57 2004 @@ -179,6 +179,7 @@ int32_t product; #define PCMCIA_PRODUCT_INVALID -1 int16_t prodext; + int mfc; uint16_t error; #define PCMCIA_CIS_INVALID { NULL, NULL, NULL, NULL } STAILQ_HEAD(, pccard_function) pf_head; @@ -284,8 +285,9 @@ #define PCCARD_SPACE_IO 2 #define pccard_mfc(sc) \ - (STAILQ_FIRST(&(sc)->card.pf_head) && \ - STAILQ_NEXT(STAILQ_FIRST(&(sc)->card.pf_head),pf_list)) + (sc->card.mfc) +/* (STAILQ_FIRST(&(sc)->card.pf_head) && \ + STAILQ_NEXT(STAILQ_FIRST(&(sc)->card.pf_head),pf_list)) */ #define pccard_io_alloc(pf, start, size, align, pciop) \ (pccard_chip_io_alloc((pf)->sc->pct, pf->sc->pch, (start), \ diff -ru sys/dev/xe/if_xe_pccard.c sysnew/dev/xe/if_xe_pccard.c --- sys/dev/xe/if_xe_pccard.c Sun Apr 11 16:34:29 2004 +++ sysnew/dev/xe/if_xe_pccard.c Sat May 1 09:48:24 2004 @@ -402,6 +402,7 @@ const struct xe_pccard_product* xpp; u_int16_t prodext; + DEVPRINTF(2, (dev, "pccard_product_match\n")); xpp = (const struct xe_pccard_product*)ent; @@ -409,6 +410,8 @@ if (xpp->prodext != prodext) vpfmatch = 0; + else + vpfmatch++; return (vpfmatch); } @@ -416,8 +419,19 @@ static int xe_pccard_match(device_t dev) { + int error = 0; + u_int32_t fcn = PCCARD_FUNCTION_UNSPEC; const struct pccard_product *pp; + error = pccard_get_function(dev, &fcn); + if (error != 0) + return (error); + /* + * If not a network card, we are not the right driver. + */ + if (fcn != PCCARD_FUNCTION_NETWORK) + return (ENXIO); + DEVPRINTF(2, (dev, "pccard_match\n")); pp = (const struct pccard_product*)xe_pccard_products; @@ -425,7 +439,6 @@ if ((pp = pccard_product_lookup(dev, pp, sizeof(xe_pccard_products[0]), xe_pccard_product_match)) != NULL) return (0); - return (EIO); } Regards, Carlos Velasco