From 7a42ffc3827e0909266974acea6d4b243a8f11b7 Mon Sep 17 00:00:00 2001 From: wpaul Date: Sun, 7 Mar 2004 02:49:06 +0000 Subject: Add preliminary support for PCMCIA devices in addition to PCI/cardbus. if_ndis.c has been split into if_ndis_pci.c and if_ndis_pccard.c. The ndiscvt(8) utility should be able to parse device info for PCMCIA devices now. The ndis_alloc_amem() has moved from kern_ndis.c to if_ndis_pccard.c so that kern_ndis.c no longer depends on pccard. NOTE: this stuff is not guaranteed to work 100% correctly yet. So far I have been able to load/init my PCMCIA Cisco Aironet 340 card, but it crashes in the interrupt handler. The existing support for PCI/cardbus devices should still work as before. --- sys/compat/ndis/kern_ndis.c | 47 ------ sys/dev/if_ndis/if_ndis.c | 240 +++-------------------------- sys/dev/if_ndis/if_ndis_pccard.c | 307 ++++++++++++++++++++++++++++++++++++++ sys/dev/if_ndis/if_ndis_pci.c | 315 +++++++++++++++++++++++++++++++++++++++ sys/dev/if_ndis/if_ndisvar.h | 8 +- sys/modules/if_ndis/Makefile | 2 +- sys/modules/ndis/Makefile | 2 +- usr.sbin/ndiscvt/inf.c | 162 +++++++++++++++++++- usr.sbin/ndiscvt/ndiscvt.c | 6 +- 9 files changed, 809 insertions(+), 280 deletions(-) create mode 100644 sys/dev/if_ndis/if_ndis_pccard.c create mode 100644 sys/dev/if_ndis/if_ndis_pci.c diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index 68c7ef3..ec771c6 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -66,9 +66,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include "card_if.h" - #include #include #include @@ -536,50 +533,6 @@ ndis_resetdone_func(adapter, status, addressingreset) return; } -#define NDIS_AM_RID 3 - -int -ndis_alloc_amem(arg) - void *arg; -{ - struct ndis_softc *sc; - int error, rid; - - if (arg == NULL) - return(EINVAL); - - sc = arg; - rid = NDIS_AM_RID; - sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY, - &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE); - - if (sc->ndis_res_am == NULL) { - device_printf(sc->ndis_dev, - "failed to allocate attribute memory\n"); - return(ENXIO); - } - - error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev), - sc->ndis_dev, rid, 0, NULL); - - if (error) { - device_printf(sc->ndis_dev, - "CARD_SET_MEMORY_OFFSET() returned 0x%x\n", error); - return(error); - } - - error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev), - sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); - - if (error) { - device_printf(sc->ndis_dev, - "CARD_SET_RES_FLAGS() returned 0x%x\n", error); - return(error); - } - - return(0); -} - int ndis_create_sysctls(arg) void *arg; diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index f70d2ec..e9edb8b 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -75,29 +75,16 @@ __FBSDID("$FreeBSD$"); #include #include -#include "ndis_driver_data.h" - -MODULE_DEPEND(ndis, pci, 1, 1, 1); -MODULE_DEPEND(ndis, ether, 1, 1, 1); -MODULE_DEPEND(ndis, wlan, 1, 1, 1); -MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); +#define NDIS_IMAGE +#define NDIS_REGVALS -/* - * Various supported device vendors/types and their names. - * These are defined in the ndis_driver_data.h file. - */ -static struct ndis_type ndis_devs[] = { -#ifdef NDIS_DEV_TABLE - NDIS_DEV_TABLE -#endif - { 0, 0, 0, NULL } -}; +#include "ndis_driver_data.h" -static int ndis_probe (device_t); -static int ndis_attach (device_t); -static int ndis_detach (device_t); -static int ndis_suspend (device_t); -static int ndis_resume (device_t); +int ndis_attach (device_t); +int ndis_detach (device_t); +int ndis_suspend (device_t); +int ndis_resume (device_t); +void ndis_shutdown (device_t); static __stdcall void ndis_txeof (ndis_handle, ndis_packet *, ndis_status); @@ -119,7 +106,6 @@ static int ndis_wi_ioctl_set (struct ifnet *, u_long, caddr_t); static void ndis_init (void *); static void ndis_stop (struct ndis_softc *); static void ndis_watchdog (struct ifnet *); -static void ndis_shutdown (device_t); static int ndis_ifmedia_upd (struct ifnet *); static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *); static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex *); @@ -135,42 +121,6 @@ static void ndis_map_sclist (void *, bus_dma_segment_t *, extern struct mtx_pool *ndis_mtxpool; -static device_method_t ndis_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ndis_probe), - DEVMETHOD(device_attach, ndis_attach), - DEVMETHOD(device_detach, ndis_detach), - DEVMETHOD(device_shutdown, ndis_shutdown), - DEVMETHOD(device_suspend, ndis_suspend), - DEVMETHOD(device_resume, ndis_resume), - - { 0, 0 } -}; - -static driver_t ndis_driver = { -#ifdef NDIS_DEVNAME - NDIS_DEVNAME, -#else - "ndis", -#endif - ndis_methods, - sizeof(struct ndis_softc) -}; - -static devclass_t ndis_devclass; - -#ifdef NDIS_MODNAME -#define NDIS_MODNAME_OVERRIDE_PCI(x) \ - DRIVER_MODULE(x, pci, ndis_driver, ndis_devclass, 0, 0) -#define NDIS_MODNAME_OVERRIDE_CARDBUS(x) \ - DRIVER_MODULE(x, cardbus, ndis_driver, ndis_devclass, 0, 0) -NDIS_MODNAME_OVERRIDE_PCI(NDIS_MODNAME); -NDIS_MODNAME_OVERRIDE_CARDBUS(NDIS_MODNAME); -#else -DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, 0, 0); -DRIVER_MODULE(ndis, cardbus, ndis_driver, ndis_devclass, 0, 0); -#endif - /* * Program the 64-bit multicast hash filter. */ @@ -246,32 +196,6 @@ out: return; } -/* - * Probe for an NDIS device. Check the PCI vendor and device - * IDs against our list and return a device name if we find a match. - */ -static int -ndis_probe(dev) - device_t dev; -{ - struct ndis_type *t; - - t = ndis_devs; - - while(t->ndis_name != NULL) { - if ((pci_get_vendor(dev) == t->ndis_vid) && - (pci_get_device(dev) == t->ndis_did) && - ((pci_read_config(dev, PCIR_SUBVEND_0, 4) == - t->ndis_subsys) || t->ndis_subsys == 0)) { - device_set_desc(dev, t->ndis_name); - return(0); - } - t++; - } - - return(ENXIO); -} - static int ndis_set_offload(sc) struct ndis_softc *sc; @@ -428,105 +352,22 @@ ndis_probe_offload(sc) * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. */ -static int +int ndis_attach(dev) device_t dev; { u_char eaddr[ETHER_ADDR_LEN]; - struct ndis_softc *sc; + struct ndis_softc *sc; struct ifnet *ifp = NULL; - int unit, error = 0, rid, len; void *img; - struct ndis_type *t; - int i, devidx = 0, defidx = 0; - struct resource_list *rl; - struct resource_list_entry *rle; + int error = 0, len; + int i; sc = device_get_softc(dev); - unit = device_get_unit(dev); - sc->ndis_dev = dev; sc->ndis_mtx = mtx_pool_alloc(ndis_mtxpool); sc->ndis_intrmtx = mtx_pool_alloc(ndis_mtxpool); - /* - * Map control/status registers. - */ - - pci_enable_busmaster(dev); - - rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); - if (rl != NULL) { - SLIST_FOREACH(rle, rl, link) { - switch (rle->type) { - case SYS_RES_IOPORT: - sc->ndis_io_rid = rle->rid; - sc->ndis_res_io = bus_alloc_resource(dev, - SYS_RES_IOPORT, &sc->ndis_io_rid, - 0, ~0, 1, RF_ACTIVE); - if (sc->ndis_res_io == NULL) { - device_printf(dev, - "couldn't map iospace\n"); - error = ENXIO; - goto fail; - } - break; - case SYS_RES_MEMORY: - if (sc->ndis_res_altmem != NULL && - sc->ndis_res_mem != NULL) { - device_printf(dev, - "too many memory resources\n"); - error = ENXIO; - goto fail; - } - if (rle->rid == PCIR_BAR(2)) { - sc->ndis_altmem_rid = rle->rid; - sc->ndis_res_altmem = - bus_alloc_resource(dev, - SYS_RES_MEMORY, - &sc->ndis_altmem_rid, - 0, ~0, 1, RF_ACTIVE); - if (sc->ndis_res_altmem == NULL) { - device_printf(dev, - "couldn't map alt " - "memory\n"); - error = ENXIO; - goto fail; - } - } else { - sc->ndis_mem_rid = rle->rid; - sc->ndis_res_mem = - bus_alloc_resource(dev, - SYS_RES_MEMORY, - &sc->ndis_mem_rid, - 0, ~0, 1, RF_ACTIVE); - if (sc->ndis_res_mem == NULL) { - device_printf(dev, - "couldn't map memory\n"); - error = ENXIO; - goto fail; - } - } - break; - case SYS_RES_IRQ: - rid = rle->rid; - sc->ndis_irq = bus_alloc_resource(dev, - SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE); - if (sc->ndis_irq == NULL) { - device_printf(dev, - "couldn't map interrupt\n"); - error = ENXIO; - goto fail; - } - break; - default: - break; - } - sc->ndis_rescnt++; - } - } - /* * Hook interrupt early, since calling the driver's * init routine may trigger an interrupt. @@ -540,51 +381,7 @@ ndis_attach(dev) goto fail; } - /* - * Allocate the parent bus DMA tag appropriate for PCI. - */ -#define NDIS_NSEG_NEW 32 - error = bus_dma_tag_create(NULL, /* parent */ - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - MAXBSIZE, NDIS_NSEG_NEW,/* maxsize, nsegments */ - BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->ndis_parent_tag); - - if (error) - goto fail; - - img = drv_data; sc->ndis_regvals = ndis_regvals; - sc->ndis_iftype = PCIBus; - - /* Figure out exactly which device we matched. */ - - t = ndis_devs; - - while(t->ndis_name != NULL) { - if ((pci_get_vendor(dev) == t->ndis_vid) && - (pci_get_device(dev) == t->ndis_did)) { - if (t->ndis_subsys == 0) - defidx = devidx; - else { - if (t->ndis_subsys == - pci_read_config(dev, PCIR_SUBVEND_0, 4)) - break; - } - } - t++; - devidx++; - } - - if (ndis_devs[devidx].ndis_name == NULL) - sc->ndis_devidx = defidx; - else - sc->ndis_devidx = devidx; sysctl_ctx_init(&sc->ndis_ctx); @@ -592,6 +389,7 @@ ndis_attach(dev) ndis_create_sysctls(sc); /* Set up driver image in memory. */ + img = drv_data; ndis_load_driver((vm_offset_t)img, sc); /* Tell the user what version of the API the driver is using. */ @@ -622,7 +420,6 @@ ndis_attach(dev) len = sizeof(eaddr); ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len); - sc->ndis_unit = unit; bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); /* @@ -900,7 +697,7 @@ fail: * to be careful about only freeing resources that have actually been * allocated. */ -static int +int ndis_detach(dev) device_t dev; { @@ -947,14 +744,15 @@ ndis_detach(dev) ndis_unload_driver((void *)ifp); - bus_dma_tag_destroy(sc->ndis_parent_tag); + if (sc->ndis_iftype == PCIBus) + bus_dma_tag_destroy(sc->ndis_parent_tag); sysctl_ctx_free(&sc->ndis_ctx); return(0); } -static int +int ndis_suspend(dev) device_t dev; { @@ -972,7 +770,7 @@ ndis_suspend(dev) return(0); } -static int +int ndis_resume(dev) device_t dev; { @@ -2241,7 +2039,7 @@ ndis_stop(sc) * Stop all chip I/O so that the kernel's probe routines don't * get confused by errant DMAs when rebooting. */ -static void +void ndis_shutdown(dev) device_t dev; { diff --git a/sys/dev/if_ndis/if_ndis_pccard.c b/sys/dev/if_ndis/if_ndis_pccard.c new file mode 100644 index 0000000..5919ae7 --- /dev/null +++ b/sys/dev/if_ndis/if_ndis_pccard.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2003 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "card_if.h" + +#include "ndis_driver_data.h" + +#ifdef NDIS_PCMCIA_DEV_TABLE + +MODULE_DEPEND(ndis, pccard, 1, 1, 1); +MODULE_DEPEND(ndis, ether, 1, 1, 1); +MODULE_DEPEND(ndis, wlan, 1, 1, 1); +MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); + +/* + * Various supported device vendors/types and their names. + * These are defined in the ndis_driver_data.h file. + */ +static struct ndis_pccard_type ndis_devs[] = { +#ifdef NDIS_PCMCIA_DEV_TABLE + NDIS_PCMCIA_DEV_TABLE +#endif + { NULL, NULL, NULL } +}; + +static int ndis_probe_pccard (device_t); +static int ndis_attach_pccard (device_t); +extern int ndis_attach (device_t); +extern int ndis_shutdown (device_t); +extern int ndis_detach (device_t); +extern int ndis_suspend (device_t); +extern int ndis_resume (device_t); + +static int my_strcasecmp (const char *, const char *, int); + +extern struct mtx_pool *ndis_mtxpool; + +static device_method_t ndis_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ndis_probe_pccard), + DEVMETHOD(device_attach, ndis_attach_pccard), + DEVMETHOD(device_detach, ndis_detach), + DEVMETHOD(device_shutdown, ndis_shutdown), + DEVMETHOD(device_suspend, ndis_suspend), + DEVMETHOD(device_resume, ndis_resume), + + { 0, 0 } +}; + +static driver_t ndis_driver = { +#ifdef NDIS_DEVNAME + NDIS_DEVNAME, +#else + "ndis", +#endif + ndis_methods, + sizeof(struct ndis_softc) +}; + +static devclass_t ndis_devclass; + +#ifdef NDIS_MODNAME +#define NDIS_MODNAME_OVERRIDE_PCMCIA(x) \ + DRIVER_MODULE(x, pccard, ndis_driver, ndis_devclass, 0, 0) +NDIS_MODNAME_OVERRIDE_PCMCIA(NDIS_MODNAME); +#else +DRIVER_MODULE(ndis, pccard, ndis_driver, ndis_devclass, 0, 0); +#endif + +static int my_strcasecmp(s1, s2, len) + const char *s1; + const char *s2; + int len; +{ + int i; + + for (i = 0; i < len; i++) { + if (toupper(s1[i]) != toupper(s2[i])) + return(0); + } + + return(1); +} + + +/* + * Probe for an NDIS device. Check the PCI vendor and device + * IDs against our list and return a device name if we find a match. + */ +static int +ndis_probe_pccard(dev) + device_t dev; +{ + struct ndis_pccard_type *t; + const char *prodstr, *vendstr; + int error; + + t = ndis_devs; + + error = pccard_get_product_str(dev, &prodstr); + if (error) + return(error); + error = pccard_get_vendor_str(dev, &vendstr); + if (error) + return(error); + + while(t->ndis_name != NULL) { + if (my_strcasecmp(vendstr, t->ndis_vid, strlen(vendstr)) && + my_strcasecmp(prodstr, t->ndis_did, strlen(prodstr))) { + device_set_desc(dev, t->ndis_name); + return(0); + } + t++; + } + + return(ENXIO); +} + +/* + * Attach the interface. Allocate softc structures, do ifmedia + * setup and ethernet/BPF attach. + */ +static int +ndis_attach_pccard(dev) + device_t dev; +{ + struct ndis_softc *sc; + int unit, error = 0, rid; + struct ndis_pccard_type *t; + int devidx = 0; + const char *prodstr, *vendstr; + struct resource_list *rl; + struct resource_list_entry *rle; + + sc = device_get_softc(dev); + unit = device_get_unit(dev); + sc->ndis_dev = dev; + + sc->ndis_io_rid = 0; + sc->ndis_res_io = bus_alloc_resource(dev, + SYS_RES_IOPORT, &sc->ndis_io_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->ndis_res_io == NULL) { + device_printf(dev, + "couldn't map iospace\n"); + error = ENXIO; + goto fail; + } + sc->ndis_rescnt++; + + rid = 0; + sc->ndis_irq = bus_alloc_resource(dev, + SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (sc->ndis_irq == NULL) { + device_printf(dev, + "couldn't map interrupt\n"); + error = ENXIO; + goto fail; + } + sc->ndis_rescnt++; + + sc->ndis_iftype = PCMCIABus; + + /* Figure out exactly which device we matched. */ + + t = ndis_devs; + + error = pccard_get_product_str(dev, &prodstr); + if (error) + return(error); + error = pccard_get_vendor_str(dev, &vendstr); + if (error) + return(error); + + while(t->ndis_name != NULL) { + if (my_strcasecmp(vendstr, t->ndis_vid, strlen(vendstr)) && + my_strcasecmp(prodstr, t->ndis_did, strlen(prodstr))) + break; + t++; + devidx++; + } + + sc->ndis_devidx = devidx; + + error = ndis_attach(dev); + +fail: + return(error); +} + +#endif /* NDIS_PCI_DEV_TABLE */ + +#define NDIS_AM_RID 3 + +int +ndis_alloc_amem(arg) + void *arg; +{ + struct ndis_softc *sc; + int error, rid; + + if (arg == NULL) + return(EINVAL); + + sc = arg; + rid = NDIS_AM_RID; + sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY, + &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE); + + if (sc->ndis_res_am == NULL) { + device_printf(sc->ndis_dev, + "failed to allocate attribute memory\n"); + return(ENXIO); + } + + error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev), + sc->ndis_dev, rid, 0, NULL); + + if (error) { + device_printf(sc->ndis_dev, + "CARD_SET_MEMORY_OFFSET() returned 0x%x\n", error); + return(error); + } + + error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev), + sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); + + if (error) { + device_printf(sc->ndis_dev, + "CARD_SET_RES_FLAGS() returned 0x%x\n", error); + return(error); + } + + return(0); +} diff --git a/sys/dev/if_ndis/if_ndis_pci.c b/sys/dev/if_ndis/if_ndis_pci.c new file mode 100644 index 0000000..6b293e5 --- /dev/null +++ b/sys/dev/if_ndis/if_ndis_pci.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2003 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ndis_driver_data.h" + +#ifdef NDIS_PCI_DEV_TABLE + +MODULE_DEPEND(ndis, pci, 1, 1, 1); +MODULE_DEPEND(ndis, ether, 1, 1, 1); +MODULE_DEPEND(ndis, wlan, 1, 1, 1); +MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); + +/* + * Various supported device vendors/types and their names. + * These are defined in the ndis_driver_data.h file. + */ +static struct ndis_pci_type ndis_devs[] = { +#ifdef NDIS_PCI_DEV_TABLE + NDIS_PCI_DEV_TABLE +#endif + { 0, 0, 0, NULL } +}; + +static int ndis_probe_pci (device_t); +static int ndis_attach_pci (device_t); +extern int ndis_attach (device_t); +extern int ndis_shutdown (device_t); +extern int ndis_detach (device_t); +extern int ndis_suspend (device_t); +extern int ndis_resume (device_t); + +extern struct mtx_pool *ndis_mtxpool; + +static device_method_t ndis_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ndis_probe_pci), + DEVMETHOD(device_attach, ndis_attach_pci), + DEVMETHOD(device_detach, ndis_detach), + DEVMETHOD(device_shutdown, ndis_shutdown), + DEVMETHOD(device_suspend, ndis_suspend), + DEVMETHOD(device_resume, ndis_resume), + + { 0, 0 } +}; + +static driver_t ndis_driver = { +#ifdef NDIS_DEVNAME + NDIS_DEVNAME, +#else + "ndis", +#endif + ndis_methods, + sizeof(struct ndis_softc) +}; + +static devclass_t ndis_devclass; + +#ifdef NDIS_MODNAME +#define NDIS_MODNAME_OVERRIDE_PCI(x) \ + DRIVER_MODULE(x, pci, ndis_driver, ndis_devclass, 0, 0) +#define NDIS_MODNAME_OVERRIDE_CARDBUS(x) \ + DRIVER_MODULE(x, cardbus, ndis_driver, ndis_devclass, 0, 0) +NDIS_MODNAME_OVERRIDE_PCI(NDIS_MODNAME); +NDIS_MODNAME_OVERRIDE_CARDBUS(NDIS_MODNAME); +#else +DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, 0, 0); +DRIVER_MODULE(ndis, cardbus, ndis_driver, ndis_devclass, 0, 0); +#endif + +/* + * Probe for an NDIS device. Check the PCI vendor and device + * IDs against our list and return a device name if we find a match. + */ +static int +ndis_probe_pci(dev) + device_t dev; +{ + struct ndis_pci_type *t; + + t = ndis_devs; + + while(t->ndis_name != NULL) { + if ((pci_get_vendor(dev) == t->ndis_vid) && + (pci_get_device(dev) == t->ndis_did) && + ((pci_read_config(dev, PCIR_SUBVEND_0, 4) == + t->ndis_subsys) || t->ndis_subsys == 0)) { + device_set_desc(dev, t->ndis_name); + return(0); + } + t++; + } + + return(ENXIO); +} + +/* + * Attach the interface. Allocate softc structures, do ifmedia + * setup and ethernet/BPF attach. + */ +static int +ndis_attach_pci(dev) + device_t dev; +{ + struct ndis_softc *sc; + int unit, error = 0, rid; + struct ndis_pci_type *t; + int devidx = 0, defidx = 0; + struct resource_list *rl; + struct resource_list_entry *rle; + + sc = device_get_softc(dev); + unit = device_get_unit(dev); + sc->ndis_dev = dev; + + /* + * Map control/status registers. + */ + + pci_enable_busmaster(dev); + + rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); + if (rl != NULL) { + SLIST_FOREACH(rle, rl, link) { + switch (rle->type) { + case SYS_RES_IOPORT: + sc->ndis_io_rid = rle->rid; + sc->ndis_res_io = bus_alloc_resource(dev, + SYS_RES_IOPORT, &sc->ndis_io_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->ndis_res_io == NULL) { + device_printf(dev, + "couldn't map iospace\n"); + error = ENXIO; + goto fail; + } + break; + case SYS_RES_MEMORY: + if (sc->ndis_res_altmem != NULL && + sc->ndis_res_mem != NULL) { + device_printf(dev, + "too many memory resources\n"); + error = ENXIO; + goto fail; + } + if (rle->rid == PCIR_BAR(2)) { + sc->ndis_altmem_rid = rle->rid; + sc->ndis_res_altmem = + bus_alloc_resource(dev, + SYS_RES_MEMORY, + &sc->ndis_altmem_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->ndis_res_altmem == NULL) { + device_printf(dev, + "couldn't map alt " + "memory\n"); + error = ENXIO; + goto fail; + } + } else { + sc->ndis_mem_rid = rle->rid; + sc->ndis_res_mem = + bus_alloc_resource(dev, + SYS_RES_MEMORY, + &sc->ndis_mem_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->ndis_res_mem == NULL) { + device_printf(dev, + "couldn't map memory\n"); + error = ENXIO; + goto fail; + } + } + break; + case SYS_RES_IRQ: + rid = rle->rid; + sc->ndis_irq = bus_alloc_resource(dev, + SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (sc->ndis_irq == NULL) { + device_printf(dev, + "couldn't map interrupt\n"); + error = ENXIO; + goto fail; + } + break; + default: + break; + } + sc->ndis_rescnt++; + } + } + + /* + * Allocate the parent bus DMA tag appropriate for PCI. + */ +#define NDIS_NSEG_NEW 32 + error = bus_dma_tag_create(NULL, /* parent */ + 1, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + MAXBSIZE, NDIS_NSEG_NEW,/* maxsize, nsegments */ + BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ + BUS_DMA_ALLOCNOW, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc->ndis_parent_tag); + + if (error) + goto fail; + + sc->ndis_iftype = PCIBus; + + /* Figure out exactly which device we matched. */ + + t = ndis_devs; + + while(t->ndis_name != NULL) { + if ((pci_get_vendor(dev) == t->ndis_vid) && + (pci_get_device(dev) == t->ndis_did)) { + if (t->ndis_subsys == 0) + defidx = devidx; + else { + if (t->ndis_subsys == + pci_read_config(dev, PCIR_SUBVEND_0, 4)) + break; + } + } + t++; + devidx++; + } + + if (ndis_devs[devidx].ndis_name == NULL) + sc->ndis_devidx = defidx; + else + sc->ndis_devidx = devidx; + + error = ndis_attach(dev); + +fail: + return(error); +} + +#endif /* NDIS_PCI_DEV_TABLE */ diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h index e98aa0b..c2bc6b6 100644 --- a/sys/dev/if_ndis/if_ndisvar.h +++ b/sys/dev/if_ndis/if_ndisvar.h @@ -32,13 +32,19 @@ * $FreeBSD$ */ -struct ndis_type { +struct ndis_pci_type { uint16_t ndis_vid; uint16_t ndis_did; uint32_t ndis_subsys; char *ndis_name; }; +struct ndis_pccard_type { + const char *ndis_vid; + const char *ndis_did; + char *ndis_name; +}; + struct ndis_shmem { bus_dma_tag_t ndis_stag; bus_dmamap_t ndis_smap; diff --git a/sys/modules/if_ndis/Makefile b/sys/modules/if_ndis/Makefile index 40ff238..47c3bb1 100644 --- a/sys/modules/if_ndis/Makefile +++ b/sys/modules/if_ndis/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../dev/if_ndis KMOD= if_ndis -SRCS= if_ndis.c +SRCS= if_ndis.c if_ndis_pci.c if_ndis_pccard.c SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h card_if.h .include diff --git a/sys/modules/ndis/Makefile b/sys/modules/ndis/Makefile index fe9d308..9d5380b 100644 --- a/sys/modules/ndis/Makefile +++ b/sys/modules/ndis/Makefile @@ -4,6 +4,6 @@ KMOD= ndis SRCS= subr_pe.c subr_ndis.c subr_hal.c subr_ntoskrnl.c kern_ndis.c -SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h card_if.h vnode_if.h +SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h vnode_if.h .include diff --git a/usr.sbin/ndiscvt/inf.c b/usr.sbin/ndiscvt/inf.c index 100fd90..de6c342 100644 --- a/usr.sbin/ndiscvt/inf.c +++ b/usr.sbin/ndiscvt/inf.c @@ -57,8 +57,10 @@ static struct assign *find_assign (const char *, const char *); static struct section *find_section (const char *); -static void dump_deviceids (void); +static void dump_deviceids_pci (void); +static void dump_deviceids_pcmcia (void); static void dump_pci_id (const char *); +static void dump_pcmcia_id (const char *); static void dump_regvals (void); static void dump_paramreg (const struct section *, const struct reg *, int); @@ -76,8 +78,11 @@ inf_parse (FILE *fp, FILE *outfp) yyin = fp; yyparse(); - dump_deviceids(); + dump_deviceids_pci(); + dump_deviceids_pcmcia(); + fprintf(outfp, "#ifdef NDIS_REGVALS\n"); dump_regvals(); + fprintf(outfp, "#endif /* NDIS_REGVALS */\n"); return (0); } @@ -145,6 +150,54 @@ find_section (const char *s) } static void +dump_pcmcia_id(const char *s) +{ + char *manstr, *devstr; + char *p0, *p; + + p0 = __DECONST(char *, s); + + p = strchr(p0, '\\'); + if (p == NULL) + return; + p0 = p + 1; + + p = strchr(p0, '-'); + if (p == NULL) + return; + *p = '\0'; + + manstr = p0; + + /* Convert any underscores to spaces. */ + + while (*p0 != '\0') { + if (*p0 == '_') + *p0 = ' '; + p0++; + } + + p0 = p + 1; + p = strchr(p0, '-'); + if (p == NULL) + return; + *p = '\0'; + + devstr = p0; + + /* Convert any underscores to spaces. */ + + while (*p0 != '\0') { + if (*p0 == '_') + *p0 = ' '; + p0++; + } + + fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr); + return; +} + +static void dump_pci_id(const char *s) { char *p; @@ -178,7 +231,7 @@ dump_pci_id(const char *s) } static void -dump_deviceids() +dump_deviceids_pci() { struct assign *manf, *dev; struct section *sec; @@ -201,8 +254,25 @@ dump_deviceids() } else sec = find_section(manf->vals[0]); - /* Emit start of device table */ - fprintf (ofp, "#define NDIS_DEV_TABLE"); + /* See if there are any PCI device definitions. */ + + TAILQ_FOREACH(assign, &ah, link) { + if (assign->section == sec) { + dev = find_assign("strings", assign->key); + if (strcasestr(assign->vals[1], "PCI") != NULL) { + found++; + break; + } + } + } + + if (found == 0) + return; + + found = 0; + + /* Emit start of PCI device table */ + fprintf (ofp, "#define NDIS_PCI_DEV_TABLE"); retry: @@ -218,11 +288,87 @@ retry: /* Emit device IDs. */ if (strcasestr(assign->vals[1], "PCI") != NULL) dump_pci_id(assign->vals[1]); - else if (strcasestr(assign->vals[1], "PCMCIA") != NULL) + else continue; -#ifdef notdef + /* Emit device description */ + fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]); + found++; + } + } + + /* Someone tried to fool us. Shame on them. */ + if (!found) { + found++; + sec = find_section(manf->vals[0]); + goto retry; + } + + /* Emit end of table */ + + fprintf(ofp, "\n\n"); + +} + +static void +dump_deviceids_pcmcia() +{ + struct assign *manf, *dev; + struct section *sec; + struct assign *assign; + char xpsec[256]; + int found = 0; + + /* Find manufacturer name */ + manf = find_assign("Manufacturer", NULL); + + /* Find manufacturer section */ + if (manf->vals[1] != NULL && + (strcasecmp(manf->vals[1], "NT.5.1") == 0 || + strcasecmp(manf->vals[1], "NTx86") == 0 || + strcasecmp(manf->vals[1], "NTx86.5.1") == 0)) { + /* Handle Windows XP INF files. */ + snprintf(xpsec, sizeof(xpsec), "%s.%s", + manf->vals[0], manf->vals[1]); + sec = find_section(xpsec); + } else + sec = find_section(manf->vals[0]); + + /* See if there are any PCMCIA device definitions. */ + + TAILQ_FOREACH(assign, &ah, link) { + if (assign->section == sec) { + dev = find_assign("strings", assign->key); + if (strcasestr(assign->vals[1], "PCMCIA") != NULL) { + found++; + break; + } + } + } + + if (found == 0) + return; + + found = 0; + + /* Emit start of PCMCIA device table */ + fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE"); + +retry: + + /* + * Now run through all the device names listed + * in the manufacturer section and dump out the + * device descriptions and vendor/device IDs. + */ + + TAILQ_FOREACH(assign, &ah, link) { + if (assign->section == sec) { + dev = find_assign("strings", assign->key); + /* Emit device IDs. */ + if (strcasestr(assign->vals[1], "PCMCIA") != NULL) dump_pcmcia_id(assign->vals[1]); -#endif + else + continue; /* Emit device description */ fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]); found++; diff --git a/usr.sbin/ndiscvt/ndiscvt.c b/usr.sbin/ndiscvt/ndiscvt.c index 58068aa..d1a29b3 100644 --- a/usr.sbin/ndiscvt/ndiscvt.c +++ b/usr.sbin/ndiscvt/ndiscvt.c @@ -236,8 +236,10 @@ main(int argc, char *argv[]) } if (inffile == NULL) { + fprintf (outfp, "#ifdef NDIS_REGVALS\n"); fprintf (outfp, "ndis_cfg ndis_regvals[] = {\n"); fprintf (outfp, "\t{ NULL, NULL, { 0 }, 0 }\n"); + fprintf (outfp, "#endif /* NDIS_REGVALS */\n"); fprintf (outfp, "};\n\n"); } else { @@ -250,7 +252,8 @@ main(int argc, char *argv[]) fclose(fp); } - fprintf(outfp, "\n\nextern unsigned char drv_data[];\n\n"); + fprintf(outfp, "\n#ifdef NDIS_IMAGE\n"); + fprintf(outfp, "\nextern unsigned char drv_data[];\n\n"); fprintf(outfp, "__asm__(\".data\");\n"); fprintf(outfp, "__asm__(\".type drv_data, @object\");\n"); @@ -278,6 +281,7 @@ main(int argc, char *argv[]) done: + fprintf(outfp, "#endif /* NDIS_IMAGE */\n"); if (fp != NULL) fclose(fp); fclose(outfp); -- cgit v1.1