From owner-freebsd-drivers@FreeBSD.ORG Mon Apr 3 14:49:10 2006 Return-Path: X-Original-To: freebsd-drivers@freebsd.org Delivered-To: freebsd-drivers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C989816A420 for ; Mon, 3 Apr 2006 14:49:10 +0000 (UTC) (envelope-from jackie7691@yahoo.com.mx) Received: from web33101.mail.mud.yahoo.com (web33101.mail.mud.yahoo.com [68.142.206.82]) by mx1.FreeBSD.org (Postfix) with SMTP id 6274F43D5A for ; Mon, 3 Apr 2006 14:49:10 +0000 (GMT) (envelope-from jackie7691@yahoo.com.mx) Received: (qmail 23795 invoked by uid 60001); 3 Apr 2006 14:49:09 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.com.mx; h=Message-ID:Received:Date:From:Subject:To:MIME-Version:Content-Type:Content-Transfer-Encoding; b=mmBB+oC1R/h1Q78lRMwkNWiifPiE8VeLGJzkYvLFAJ53Q6fQ6ikhf+6ktPNAzkYvX0dcs5nZDVGWf5dDuVOi+Qnc5N9VPVgr10YXs5wZ6WPVZucNjfzy4ro3y9iedZFFRFSe5BVHXAZBrpNdpugYu7IDASkucG+M03NI2vtSLvg= ; Message-ID: <20060403144909.23793.qmail@web33101.mail.mud.yahoo.com> Received: from [83.64.77.210] by web33101.mail.mud.yahoo.com via HTTP; Mon, 03 Apr 2006 09:49:09 CDT Date: Mon, 3 Apr 2006 09:49:09 -0500 (CDT) From: Jacqueline P To: freebsd-drivers@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Subject: Driver for PCCARD / PCMCIA X-BeenThere: freebsd-drivers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Writing device drivers for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Apr 2006 14:49:10 -0000 Hi all I'm new to FreeBSD (5.3) and must develop (porting from Linux) a driver for a PCCARD smartcardreader. But the documentation I found was poor. :-( (Architecture handbook, BSD Handbook,..) Could someone give me some hints about other documentation related to this topic ? Is there an example driver ? The only examples I came along were drivers for PCCARD - network cards. Thanks in advance, Jacqueline --------------------------------- Do You Yahoo!? La mejor conexión a Internet y 2GB extra a tu correo por $100 al mes. http://net.yahoo.com.mx From owner-freebsd-drivers@FreeBSD.ORG Mon Apr 3 15:52:29 2006 Return-Path: X-Original-To: freebsd-drivers@freebsd.org Delivered-To: freebsd-drivers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id AAF9516A400 for ; Mon, 3 Apr 2006 15:52:29 +0000 (UTC) (envelope-from imp@bsdimp.com) Received: from harmony.bsdimp.com (vc4-2-0-87.dsl.netrack.net [199.45.160.85]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4B9AE43D6D for ; Mon, 3 Apr 2006 15:52:25 +0000 (GMT) (envelope-from imp@bsdimp.com) Received: from localhost (localhost.village.org [127.0.0.1] (may be forged)) by harmony.bsdimp.com (8.13.4/8.13.4) with ESMTP id k33FoINC019875; Mon, 3 Apr 2006 09:50:18 -0600 (MDT) (envelope-from imp@bsdimp.com) Date: Mon, 03 Apr 2006 09:51:08 -0600 (MDT) Message-Id: <20060403.095108.23089926.imp@bsdimp.com> To: jackie7691@yahoo.com.mx From: "M. Warner Losh" In-Reply-To: <20060403144909.23793.qmail@web33101.mail.mud.yahoo.com> References: <20060403144909.23793.qmail@web33101.mail.mud.yahoo.com> X-Mailer: Mew version 3.3 on Emacs 21.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Cc: freebsd-drivers@freebsd.org Subject: Re: Driver for PCCARD / PCMCIA X-BeenThere: freebsd-drivers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Writing device drivers for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Apr 2006 15:52:29 -0000 In message: <20060403144909.23793.qmail@web33101.mail.mud.yahoo.com> Jacqueline P writes: : I'm new to FreeBSD (5.3) and must develop (porting from Linux) a : driver for a PCCARD smartcardreader. But the documentation I found : was poor. :-( Unlike Linux, FreeBSD's PC Card driver integration is easy. In Linux, you have to worry about all of the card services-like routines and getting them into place. On FreeBSD, you just allocate your resources like you would for any other driver and you are basically done. : Could someone give me some hints about other documentation related : to this topic ? Is there an example driver ? The only examples I : came along were drivers for PCCARD - network cards. Actually, network drivers are quite instructive. Take the ex driver, for instance. It is a driver that supports a limited number of cards, so should be easy to cut and paste here. I've annotated it with C++ style comments. As you can see, it is pretty straight forward to create a front end. Warner /*- * Copyright (c) 2000 Mitsuru IWASAKI * All rights reserved. ... omitted, please see the source */ // The following includes are boilerplate for just about any driver // the FreeBSD ID is there if you ever want to integrate it into // FreeBSD. #include __FBSDID("$FreeBSD: src/sys/dev/ex/if_ex_pccard.c,v 1.17 2005/09/13 19:28:03 imp Exp $"); #include #include #include #include #include #include #include #include #include // The following includes are network specific, you'll likely not need them. #include #include #include // The following includes are for the base part of the device. This // is the part of the device that's not dependent on its bus // attachment. Coming from Linux, there's a tendancy to comingle the // bus dependent stuff from the bus independent stuff. #include #include // The following 3 includes are to interact with the pccard system // headers. #include #include // pccarddevs.h is generated from pccarddevs. It is a design pattern // that we use in FreeBSD. The card's manufacturer ID and product ID // are placed there. The following macros expand to the symbols // defined there, making the table easy to populate and read. #include "pccarddevs.h" static const struct pccard_product ex_pccard_products[] = { PCMCIA_CARD(OLICOM, OC2220), PCMCIA_CARD(OLICOM, OC2231), PCMCIA_CARD(OLICOM, OC2232), PCMCIA_CARD(INTEL, ETHEREXPPRO), { NULL } }; /* Bus Front End Functions */ static int ex_pccard_probe(device_t); static int ex_pccard_attach(device_t); // This function you'll likely not need, since it just performs a // sanity check on the MAC address. static int ex_pccard_enet_ok(u_char *enaddr) { int i; u_char sum; if (enaddr[0] == 0xff) return (0); for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) sum |= enaddr[i]; return (sum != 0); } // Silicom products need special treatment, so ignore this static int ex_pccard_silicom_cb(const struct pccard_tuple *tuple, void *arg) { u_char *enaddr = arg; int i; if (tuple->code != CISTPL_FUNCE) return (0); if (tuple->length != 15) return (0); if (pccard_tuple_read_1(tuple, 6) != 6) return (0); for (i = 0; i < 6; i++) enaddr[i] = pccard_tuple_read_1(tuple, 7 + i); return (1); } // Silicom products need special treatment, so ignore this static void ex_pccard_get_silicom_mac(device_t dev, u_char *ether_addr) { pccard_cis_scan(dev, ex_pccard_silicom_cb, ether_addr); } // Probe the card. Make sure that it is a network device and that it // exists in the table. Chances are good you'll not want to have a // device type check in your dirver since the check is there for MFC // cards. If you have the right table, the following routine should // just be a few lines. static int ex_pccard_probe(device_t dev) { const struct pccard_product *pp; int error; uint32_t fcn = PCCARD_FUNCTION_UNSPEC; /* Make sure we're a network function */ error = pccard_get_function(dev, &fcn); if (error != 0) return (error); if (fcn != PCCARD_FUNCTION_NETWORK) return (ENXIO); if ((pp = pccard_product_lookup(dev, ex_pccard_products, sizeof(ex_pccard_products[0]), NULL)) != NULL) { if (pp->pp_name != NULL) device_set_desc(dev, pp->pp_name); return 0; } return EIO; } // Attach fills in the bus front end stuff. static int ex_pccard_attach(device_t dev) { struct ex_softc * sc = device_get_softc(dev); int error = 0; // won't need ethernet for smart card reader. u_char ether_addr[ETHER_ADDR_LEN]; sc->dev = dev; sc->ioport_rid = 0; sc->irq_rid = 0; // ex_alloc_resources is a routine in the base driver that // does bus_alloc_resource for all the necessary resources // for this card to operate. if ((error = ex_alloc_resources(dev)) != 0) { device_printf(dev, "ex_alloc_resources() failed!\n"); goto bad; } /* * Fill in several fields of the softc structure: * - Hardware Ethernet address. * - IRQ number. */ sc->irq_no = rman_get_start(sc->irq); // Won't need any of this stuff to find the MAC address for // this part. Ignore it for now. /* Try to get the ethernet address from the chip, then the CIS */ ex_get_address(sc, ether_addr); if (!ex_pccard_enet_ok(ether_addr)) pccard_get_ether(dev, ether_addr); if (!ex_pccard_enet_ok(ether_addr)) ex_pccard_get_silicom_mac(dev, ether_addr); if (!ex_pccard_enet_ok(ether_addr)) { device_printf(dev, "No NIC address found.\n"); error = ENXIO; goto bad; } bcopy(ether_addr, sc->enaddr, ETHER_ADDR_LEN); // ex_attach does the bus independent attaching of the code. if ((error = ex_attach(dev)) != 0) { device_printf(dev, "ex_attach() failed!\n"); goto bad; } // ex_attach doesn't setup an interrupt. Looking at the // different bus front ends, maybe it should be moved up into // ex_attach. It is likely this // is just a left-over from when we thought establishing // interrupt handlers in the bus dependent code was better // than in the bus independent code. Since these cards are // rare, no one has optimized it. error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, ex_intr, (void *)sc, &sc->ih); if (error) { device_printf(dev, "bus_setup_intr() failed!\n"); goto bad; } // Success, return 0. return(0); bad: // Failure cleanup and return the error ex_release_resources(dev); return (error); } static device_method_t ex_pccard_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ex_pccard_probe), DEVMETHOD(device_attach, ex_pccard_attach), DEVMETHOD(device_detach, ex_detach), { 0, 0 } }; static driver_t ex_pccard_driver = { "ex", ex_pccard_methods, sizeof(struct ex_softc), }; DRIVER_MODULE(ex, pccard, ex_pccard_driver, ex_devclass, 0, 0); From owner-freebsd-drivers@FreeBSD.ORG Wed Apr 5 11:48:12 2006 Return-Path: X-Original-To: freebsd-drivers@freebsd.org Delivered-To: freebsd-drivers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id AD1D716A400 for ; Wed, 5 Apr 2006 11:48:12 +0000 (UTC) (envelope-from jackie7691@yahoo.com.mx) Received: from web33114.mail.mud.yahoo.com (web33114.mail.mud.yahoo.com [68.142.206.95]) by mx1.FreeBSD.org (Postfix) with SMTP id 143F843D45 for ; Wed, 5 Apr 2006 11:48:11 +0000 (GMT) (envelope-from jackie7691@yahoo.com.mx) Received: (qmail 43710 invoked by uid 60001); 5 Apr 2006 11:48:10 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.com.mx; h=Message-ID:Received:Date:From:Subject:To:Cc:In-Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding; b=LcuP3Wd9YaOdxGONiroCuLn5idPZTBt9nt8pBkgsKeAYIVOqSOCktTgFe+IWGkBibYRATGCqA3x/+8oSVLcmuW7bjcFCRmZRjGdMTmAOoNpLDv1nTMNT8LPOx86931D5eluTA1dcwDHcOD8MY1bqCvjxPU2Em25FrUj44oUNe2k= ; Message-ID: <20060405114810.43708.qmail@web33114.mail.mud.yahoo.com> Received: from [83.64.77.210] by web33114.mail.mud.yahoo.com via HTTP; Wed, 05 Apr 2006 06:48:10 CDT Date: Wed, 5 Apr 2006 06:48:10 -0500 (CDT) From: Jacqueline P To: "M. Warner Losh" In-Reply-To: <20060403.095108.23089926.imp@bsdimp.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Cc: freebsd-drivers@freebsd.org Subject: Re: Driver for PCCARD / PCMCIA X-BeenThere: freebsd-drivers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Writing device drivers for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Apr 2006 11:48:12 -0000 Hello Warner, thanks for your help. Now I've created a skeleton driver (see above). How is the resource management (mapping) done ? Furthermore I'm missing my debug output when I first KLDload the driver and then insert the pccard. Which process gets the output ? #include #include #include // uprintf #include #include // types used in kernel.h #include // types used in module initialization #include // cdevsw structure #include // Permision flags #include #include #include #include #include #include #include "pccarddevs.h" #include "cm4040_cs.h" #define DEBUG_LEVEL_COM 1 #define DEBUG_LEVEL_INFO 2 #define PCCARD_DEBUG DEBUG_LEVEL_COM | DEBUG_LEVEL_INFO #ifdef PCCARD_DEBUG #define DEBUG(n, args...) if ((PCCARD_DEBUG) & (n)) uprintf(args) #else #define DEBUG(n, args...) #endif // // Supported products // static const struct pccard_product cmx_pccard_products[] = { PCMCIA_CARD(OMNIKEY, CARDMAN_4040, 0), { NULL } }; // // Bus Front End Functions // static int cmx_pccard_match(device_t); static int cmx_pccard_probe(device_t); static int cmx_pccard_attach(device_t); static int cmx_pccard_detach(device_t); static device_method_t cmx_pccard_methods[] = { // Device interface // DEVMETHOD(device_probe,pccard_compat_probe), // DEVMETHOD(device_attach, pccard_compat_attach), // DEVMETHOD(device_detach, cmx_pccard_detach), DEVMETHOD(device_probe,cmx_pccard_probe), DEVMETHOD(device_attach, cmx_pccard_attach), DEVMETHOD(device_detach, cmx_pccard_detach), // Card interface // DEVMETHOD(card_compat_match, cmx_pccard_match), // DEVMETHOD(card_compat_probe,cmx_pccard_probe), // DEVMETHOD(card_compat_attach, cmx_pccard_attach), { 0, 0 } }; // // Private data // struct cmx_softc { // struct ifmedia ifmedia; device_t dev; //struct resource *ioport; //int ioport_rid; //bus_space_tag_t bst; //bus_space_handle_t bsh; }; static driver_t cmx_pccard_driver = { "cmx", cmx_pccard_methods, sizeof(struct cmx_softc), }; static int cmx_loader(struct module *m, int reason, void *arg); devclass_t cmx_devclass; //DRIVER_MODULE(ex, pccard, ex_pccard_driver, ex_devclass, 0, 0); DRIVER_MODULE(cmx, pccard, cmx_pccard_driver, cmx_devclass, cmx_loader, 0); // // Character driver function prototypes // static d_open_t cmx_open; static d_close_t cmx_close; static d_read_t cmx_read; static d_write_t cmx_write; // // Character device entry points // static struct cdevsw cmx_cdevsw = { .d_version = D_VERSION, .d_open = cmx_open, .d_close = cmx_close, .d_read = cmx_read, .d_write = cmx_write, .d_name = MODULE_NAME }; // // Variables // static dev_t sdev; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cmx_pccard_match /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int cmx_pccard_match(device_t dev) { const struct pccard_product *pp; int err = EIO; DEBUG(DEBUG_LEVEL_COM,"cmx_pccard_match ->\n"); if ((pp = pccard_product_lookup(dev, cmx_pccard_products, sizeof(cmx_pccard_products[0]), NULL)) != NULL) { if (pp->pp_name != NULL) device_set_desc(dev, pp->pp_name); DEBUG(DEBUG_LEVEL_INFO,"pp->pp_name = %s\n", pp->pp_name); err = 0; } DEBUG(DEBUG_LEVEL_COM,"cmx_pccard_match <- returned 0x%x\n", err); return err; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cmx_pccard_probe /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int cmx_pccard_probe(device_t dev) { u_int iobase; u_int count; u_int irq; int err = 0; DEBUG(DEBUG_LEVEL_COM,"cmx_pccard_probe ->\n"); iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0); count = bus_get_resource_count(dev, SYS_RES_IOPORT, 0); DEBUG(DEBUG_LEVEL_INFO,"iobase = 0x%x\n", iobase); DEBUG(DEBUG_LEVEL_INFO,"count = 0x%x\n", count); /* if (!iobase) { printf("ex: no iobase?\n"); return(ENXIO); } if (bootverbose) printf("ex: ex_pccard_probe() found card at 0x%03x\n", iobase); irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0); if (irq == 0) { printf("ex: invalid IRQ.\n"); return(ENXIO); } */ DEBUG(DEBUG_LEVEL_COM,"cmx_pccard_probe <- returned 0x%x\n", err); return(err); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cmx_pccard_attach /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int cmx_pccard_attach(device_t dev) { struct cmx_softc * sc = device_get_softc(dev); int err = 0; DEBUG(DEBUG_LEVEL_COM,"cmx_pccard_attach ->\n"); /* sc->dev = dev; sc->ioport_rid = 0; sc->irq_rid = 0; if ((error = ex_alloc_resources(dev)) != 0) { device_printf(dev, "ex_alloc_resources() failed!\n"); goto bad; } // Try to get the ethernet address from the chip, then the CIS ex_get_address(sc, ether_addr); if (!ex_pccard_enet_ok(ether_addr)) pccard_get_ether(dev, ether_addr); if (!ex_pccard_enet_ok(ether_addr)) ex_pccard_get_silicom_mac(dev, ether_addr); if (!ex_pccard_enet_ok(ether_addr)) { device_printf(dev, "No NIC address found.\n"); error = ENXIO; goto bad; } bcopy(ether_addr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); if ((error = ex_attach(dev)) != 0) { device_printf(dev, "ex_attach() failed!\n"); goto bad; } error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, ex_intr, (void *)sc, &sc->ih); if (error) { device_printf(dev, "bus_setup_intr() failed!\n"); goto bad; } */ err = 0; DEBUG(DEBUG_LEVEL_COM,"cmx_pccard_attach <- returned 0x%x\n", err); return (err); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cmx_detach /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int cmx_pccard_detach(device_t dev) { int err = 0; struct cmx_softc *sc; DEBUG(DEBUG_LEVEL_COM,"cmx_detach ->\n"); // ex_release_resources(dev); DEBUG(DEBUG_LEVEL_COM,"cmx_detach <- returned 0x%x\n", err); return (err); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cmx_loader /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int cmx_loader(struct module *m, int reason, void *arg) { int err = 0; switch (reason) { case MOD_LOAD: sdev = make_dev(& cmx_cdevsw, 0, // Minor UID_ROOT, GID_WHEEL, S_IRUSR | S_IWUSR, DEVICE_NAME); DEBUG(DEBUG_LEVEL_COM,"Driver %s loaded\n",MODULE_NAME); break; case MOD_UNLOAD: destroy_dev(sdev); DEBUG(DEBUG_LEVEL_COM,"Driver %s unloaded\n",MODULE_NAME); break; default: err = EINVAL; break; } return err; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cmx_open /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int cmx_open(struct cdev *dev, int oflags, int devtype, struct thread *p) { int err = 0; DEBUG(DEBUG_LEVEL_COM,"cmx_open ->\n"); DEBUG(DEBUG_LEVEL_COM,"cmx_open <- returned 0x%x\n", err); return err; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cmx_close /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int cmx_close(struct cdev *dev, int fflag, int devtype, struct thread *p) { int err = 0; DEBUG(DEBUG_LEVEL_COM,"cmx_close ->\n"); DEBUG(DEBUG_LEVEL_COM,"cmx_close <- returned 0x%x\n", err); return err; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cmx_read /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int cmx_read(struct cdev *dev, struct uio *uio, int ioflag) { int err = 0; DEBUG(DEBUG_LEVEL_COM,"cmx_read ->\n"); DEBUG(DEBUG_LEVEL_COM,"cmx_read <- returned 0x%x\n", err); return err; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cmx_write /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int cmx_write(struct cdev *dev, struct uio *uio, int ioflag) { int err = 0; DEBUG(DEBUG_LEVEL_COM,"cmx_write ->\n"); DEBUG(DEBUG_LEVEL_COM,"cmx_write <- returned 0x%x\n", err); return err; } //DEV_MODULE(CM4040, cmx_loader, NULL); --------------------------------- Do You Yahoo!? La mejor conexión a Internet y 2GB extra a tu correo por $100 al mes. http://net.yahoo.com.mx From owner-freebsd-drivers@FreeBSD.ORG Fri Apr 7 23:44:17 2006 Return-Path: X-Original-To: freebsd-drivers@freebsd.org Delivered-To: freebsd-drivers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 68FF216A402 for ; Fri, 7 Apr 2006 23:44:17 +0000 (UTC) (envelope-from dave@randomparity.com) Received: from fed1rmmtao08.cox.net (fed1rmmtao08.cox.net [68.230.241.31]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0963A43D55 for ; Fri, 7 Apr 2006 23:44:16 +0000 (GMT) (envelope-from dave@randomparity.com) Received: from gateway.randomparity.com ([68.4.169.57]) by fed1rmmtao08.cox.net (InterMail vM.6.01.05.02 201-2131-123-102-20050715) with ESMTP id <20060407234415.OIIT26964.fed1rmmtao08.cox.net@gateway.randomparity.com> for ; Fri, 7 Apr 2006 19:44:15 -0400 Received: by gateway.randomparity.com (Postfix, from userid 429) id 9CDC731BC83; Fri, 7 Apr 2006 14:21:39 -0700 (PDT) Received: from snoopy.randomparity.com (snoopy.randomparity.com [10.1.1.4]) by gateway.randomparity.com (Postfix) with ESMTP id 6649831BBEB for ; Fri, 7 Apr 2006 14:21:36 -0700 (PDT) Content-class: urn:content-classes:message MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: quoted-printable X-MimeOLE: Produced By Microsoft Exchange V6.5.6944.0 Date: Fri, 7 Apr 2006 16:43:59 -0700 Message-ID: <22C21BFBEB52B340A1F422CB0D88F5872E17@snoopy.randomparity.com> X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: How Do I Allocate Less Than the Entire BAR for a PCI Device? Thread-Index: AcZanSRE5zPkULDlQFG7cwwpCMElqw== From: "David Christensen" To: X-Spam-Checker-Version: SpamAssassin 3.0.4 (2005-06-05) on gateway.randomparity.com X-Spam-Level: X-Spam-Status: No, score=-2.3 required=4.0 tests=AWL,BAYES_00 autolearn=ham version=3.0.4 Subject: How Do I Allocate Less Than the Entire BAR for a PCI Device? X-BeenThere: freebsd-drivers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Writing device drivers for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 07 Apr 2006 23:44:17 -0000 The Ethernet driver I'm working on has a very large PCI BAR mapping=20 for memory (32MB), but I only need 128KB of that BAR memory for use by the driver. How can I map only the amount of memory I need with bus_alloc_resource()? It looks like I can specify the size if I also know the BAR starting address, but I'm not sure how to find that. Has anyone done this or know of any existing code that does this? All of the examples I looked at used all of BAR mapped memory. David Christensen From owner-freebsd-drivers@FreeBSD.ORG Sat Apr 8 00:52:00 2006 Return-Path: X-Original-To: freebsd-drivers@freebsd.org Delivered-To: freebsd-drivers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1806A16A402 for ; Sat, 8 Apr 2006 00:52:00 +0000 (UTC) (envelope-from jmg@hydrogen.funkthat.com) Received: from hydrogen.funkthat.com (gate.funkthat.com [69.17.45.168]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8478F43D48 for ; Sat, 8 Apr 2006 00:51:59 +0000 (GMT) (envelope-from jmg@hydrogen.funkthat.com) Received: from hydrogen.funkthat.com (zqgfs9i3ttum38vp@localhost.funkthat.com [127.0.0.1]) by hydrogen.funkthat.com (8.13.4/8.13.3) with ESMTP id k380pwjR098257; Fri, 7 Apr 2006 17:51:58 -0700 (PDT) (envelope-from jmg@hydrogen.funkthat.com) Received: (from jmg@localhost) by hydrogen.funkthat.com (8.13.4/8.13.3/Submit) id k380ptPR098255; Fri, 7 Apr 2006 17:51:55 -0700 (PDT) (envelope-from jmg) Date: Fri, 7 Apr 2006 17:51:55 -0700 From: John-Mark Gurney To: David Christensen Message-ID: <20060408005155.GF72485@funkthat.com> References: <22C21BFBEB52B340A1F422CB0D88F5872E17@snoopy.randomparity.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <22C21BFBEB52B340A1F422CB0D88F5872E17@snoopy.randomparity.com> User-Agent: Mutt/1.4.2.1i X-Operating-System: FreeBSD 5.4-RELEASE-p6 i386 X-PGP-Fingerprint: B7 EC EF F8 AE ED A7 31 96 7A 22 B3 D8 56 36 F4 X-Files: The truth is out there X-URL: http://resnet.uoregon.edu/~gurney_j/ X-Resume: http://resnet.uoregon.edu/~gurney_j/resume.html Cc: freebsd-drivers@freebsd.org Subject: Re: How Do I Allocate Less Than the Entire BAR for a PCI Device? X-BeenThere: freebsd-drivers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: John-Mark Gurney List-Id: Writing device drivers for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 08 Apr 2006 00:52:00 -0000 David Christensen wrote this message on Fri, Apr 07, 2006 at 16:43 -0700: > The Ethernet driver I'm working on has a very large PCI BAR mapping > for memory (32MB), but I only need 128KB of that BAR memory for use > by the driver. How can I map only the amount of memory I need with > bus_alloc_resource()? It looks like I can specify the size if I > also know the BAR starting address, but I'm not sure how to find that. > Has anyone done this or know of any existing code that does this? All > of the examples I looked at used all of BAR mapped memory. start and end should be relative to the resource.. so if you need to map 128kb at 1meg of the resource, you would do: rid = PCIR_BAR(0); /* or what ever bar the memory map is at */ bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 1024*1024, 1024*1024+128*1024 - 1, 128*1024, RF_ACTIVE); I believe this will work, I haven't tried it.. though my tracing of the code seems to imply it might not... also, most systems provide complete direct access to the pci address space.. and on platforms like i386 w/ direct mapped pci space, even if you want to only map 128k, the resource will still consume 32megs, since you cannot map less than the resource lets you... (on archs like sparc64, w/ 64bit address space, you don't have to worry about consuming address space).. so, if you were only trying to map 128k to save kernel memory, etc, don't bother, map the whole thing and use only the parts you need.. -- John-Mark Gurney Voice: +1 415 225 5579 "All that I will do, has been done, All that I have, has not." From owner-freebsd-drivers@FreeBSD.ORG Sat Apr 8 01:31:26 2006 Return-Path: X-Original-To: freebsd-drivers@freebsd.org Delivered-To: freebsd-drivers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id DDA6316A401 for ; Sat, 8 Apr 2006 01:31:26 +0000 (UTC) (envelope-from imp@bsdimp.com) Received: from harmony.bsdimp.com (vc4-2-0-87.dsl.netrack.net [199.45.160.85]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7AE3B43D45 for ; Sat, 8 Apr 2006 01:31:26 +0000 (GMT) (envelope-from imp@bsdimp.com) Received: from localhost (localhost.village.org [127.0.0.1] (may be forged)) by harmony.bsdimp.com (8.13.4/8.13.4) with ESMTP id k381TvGV097179; Fri, 7 Apr 2006 19:30:03 -0600 (MDT) (envelope-from imp@bsdimp.com) Date: Fri, 07 Apr 2006 19:29:56 -0600 (MDT) Message-Id: <20060407.192956.78709670.imp@bsdimp.com> To: gurney_j@resnet.uoregon.edu From: "M. Warner Losh" In-Reply-To: <20060408005155.GF72485@funkthat.com> References: <22C21BFBEB52B340A1F422CB0D88F5872E17@snoopy.randomparity.com> <20060408005155.GF72485@funkthat.com> X-Mailer: Mew version 3.3 on Emacs 21.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Cc: freebsd-drivers@freebsd.org Subject: Re: How Do I Allocate Less Than the Entire BAR for a PCI Device? X-BeenThere: freebsd-drivers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Writing device drivers for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 08 Apr 2006 01:31:26 -0000 In message: <20060408005155.GF72485@funkthat.com> John-Mark Gurney writes: : David Christensen wrote this message on Fri, Apr 07, 2006 at 16:43 -0700: : > The Ethernet driver I'm working on has a very large PCI BAR mapping : > for memory (32MB), but I only need 128KB of that BAR memory for use : > by the driver. How can I map only the amount of memory I need with : > bus_alloc_resource()? It looks like I can specify the size if I : > also know the BAR starting address, but I'm not sure how to find that. : > Has anyone done this or know of any existing code that does this? All : > of the examples I looked at used all of BAR mapped memory. : : start and end should be relative to the resource.. so if you need to map : 128kb at 1meg of the resource, you would do: : rid = PCIR_BAR(0); /* or what ever bar the memory map is at */ : bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 1024*1024, : 1024*1024+128*1024 - 1, 128*1024, RF_ACTIVE); : : I believe this will work, I haven't tried it.. though my tracing of : the code seems to imply it might not... 0 and ~0UL should be used instead. However, I'm pretty sure that we ignore the size in the pci code. : also, most systems provide complete direct access to the pci address : space.. and on platforms like i386 w/ direct mapped pci space, even : if you want to only map 128k, the resource will still consume 32megs, : since you cannot map less than the resource lets you... (on archs like : sparc64, w/ 64bit address space, you don't have to worry about consuming : address space).. The problem is that in the phyiscal address space (on i386 at least), the BAR does take up 32MB. The card decodes that entire range, so no other cards can be in that range. : so, if you were only trying to map 128k to save kernel memory, etc, : don't bother, map the whole thing and use only the parts you need.. Agreed. Warner