From 265745a5bf0757913d123848a4a36b967bd40a0a Mon Sep 17 00:00:00 2001 From: Bill Paul Date: Mon, 29 Dec 2003 23:51:59 +0000 Subject: [PATCH] Rework resource allocation. Replace the "feel around like a blind man" method with something a little more intelligent: use BUS_GET_RESOURCE_LIST() to run through all resources allocated to us and map them as needed. This way we know exactly what resources need to be mapped and what their RIDs are without having to guess. This simplifies both ndis_attach() and ndis_convert_res(), and eliminates the unfriendly "ndisX: couldn't map " messages that are sometimes emitted during driver load. --- sys/compat/ndis/kern_ndis.c | 56 ++++++++------- sys/dev/if_ndis/if_ndis.c | 134 ++++++++++++++++++++---------------- 2 files changed, 105 insertions(+), 85 deletions(-) diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index c88ea309eb3d..14d46da49eee 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -397,9 +397,13 @@ ndis_convert_res(arg) ndis_resource_list *rl = NULL; cm_partial_resource_desc *prd = NULL; ndis_miniport_block *block; + device_t dev; + struct resource_list *brl; + struct resource_list_entry *brle; sc = arg; block = &sc->ndis_block; + dev = sc->ndis_dev; rl = malloc(sizeof(ndis_resource_list) + (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)), @@ -411,33 +415,35 @@ ndis_convert_res(arg) rl->cprl_version = 5; rl->cprl_version = 1; rl->cprl_count = sc->ndis_rescnt; - prd = rl->cprl_partial_descs; - if (sc->ndis_res_io) { - prd->cprd_type = CmResourceTypePort; - prd->u.cprd_port.cprd_start.np_quad = - rman_get_start(sc->ndis_res_io); - prd->u.cprd_port.cprd_len = - rman_get_size(sc->ndis_res_io); - prd++; - } - if (sc->ndis_res_mem) { - prd->cprd_type = CmResourceTypeMemory; - prd->u.cprd_mem.cprd_start.np_quad = - rman_get_start(sc->ndis_res_mem); - prd->u.cprd_mem.cprd_len = - rman_get_size(sc->ndis_res_mem); - prd++; - } - - if (sc->ndis_irq) { - prd->cprd_type = CmResourceTypeInterrupt; - prd->u.cprd_intr.cprd_level = - rman_get_start(sc->ndis_irq); - prd->u.cprd_intr.cprd_vector = - rman_get_start(sc->ndis_irq); - prd->u.cprd_intr.cprd_affinity = 0; + brl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); + if (brl != NULL) { + SLIST_FOREACH(brle, brl, link) { + switch (brle->type) { + case SYS_RES_IOPORT: + prd->cprd_type = CmResourceTypePort; + prd->u.cprd_port.cprd_start.np_quad = + brle->start; + prd->u.cprd_port.cprd_len = brle->count; + break; + case SYS_RES_MEMORY: + prd->cprd_type = CmResourceTypeMemory; + prd->u.cprd_port.cprd_start.np_quad = + brle->start; + prd->u.cprd_port.cprd_len = brle->count; + break; + case SYS_RES_IRQ: + prd->cprd_type = CmResourceTypeInterrupt; + prd->u.cprd_intr.cprd_level = brle->start; + prd->u.cprd_intr.cprd_vector = brle->start; + prd->u.cprd_intr.cprd_affinity = 0; + break; + default: + break; + } + prd++; + } } block->nmb_rlist = rl; diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index e9e756dafacb..46ead8d5cee0 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -215,10 +215,13 @@ ndis_attach(dev) void *img; struct ndis_type *t; int i, 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; mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); @@ -228,67 +231,76 @@ ndis_attach(dev) */ pci_enable_busmaster(dev); - /* Try to map iospace */ - - sc->ndis_io_rid = NDIS_PCI_LOIO; - sc->ndis_res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sc->ndis_io_rid, 0, ~0, 1, RF_ACTIVE); - - /* - * Sometimes the iospace and memspace BARs are swapped. - * Make one more try to map I/O space using a different - * RID. - */ - if (sc->ndis_res_io == NULL) { - sc->ndis_io_rid = NDIS_PCI_LOMEM; - sc->ndis_res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sc->ndis_io_rid, 0, ~0, 1, RF_ACTIVE); + 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) { + printf("ndis%d: couldn't map " + "iospace\n", unit); + error = ENXIO; + goto fail; + } + break; + case SYS_RES_MEMORY: + if (sc->ndis_res_altmem != NULL) { + printf ("ndis%d: too many memory " + "resources", sc->ndis_unit); + error = ENXIO; + goto fail; + } + if (sc->ndis_res_mem == NULL) { + 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) { + printf("ndis%d: couldn't map " + "memory\n", unit); + error = ENXIO; + goto fail; + } + } else { + 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) { + printf("ndis%d: couldn't map " + "alt memory\n", unit); + 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) { + printf("ndis%d: couldn't map " + "interrupt\n", unit); + error = ENXIO; + goto fail; + } + break; + default: + break; + } + sc->ndis_rescnt++; + } } - if (sc->ndis_res_io != NULL) - sc->ndis_rescnt++; - - /* Now try to mem memory space */ - sc->ndis_mem_rid = NDIS_PCI_LOMEM; - sc->ndis_res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, - &sc->ndis_mem_rid, 0, ~0, 1, RF_ACTIVE); - - /* - * If the first attempt fails, try again with another - * BAR. - */ - if (sc->ndis_res_mem == NULL) { - sc->ndis_mem_rid = NDIS_PCI_LOIO; - 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) - sc->ndis_rescnt++; - - if (!sc->ndis_rescnt) { - printf("ndis%d: couldn't map ports/memory\n", unit); - error = ENXIO; - goto fail; - } -#ifdef notdef - sc->ndis_btag = rman_get_bustag(sc->ndis_res); - sc->ndis_bhandle = rman_get_bushandle(sc->ndis_res); -#endif - - /* Allocate interrupt */ - 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) { - printf("ndis%d: couldn't map interrupt\n", unit); - error = ENXIO; - goto fail; - } - - sc->ndis_rescnt++; - /* * Hook interrupt early, since calling the driver's * init routine may trigger an interrupt. @@ -321,7 +333,6 @@ ndis_attach(dev) goto fail; img = drv_data; - sc->ndis_dev = dev; sc->ndis_regvals = ndis_regvals; sc->ndis_iftype = PCIBus; @@ -615,6 +626,9 @@ ndis_detach(dev) if (sc->ndis_res_mem) bus_release_resource(dev, SYS_RES_MEMORY, sc->ndis_mem_rid, sc->ndis_res_mem); + if (sc->ndis_res_altmem) + bus_release_resource(dev, SYS_RES_MEMORY, + sc->ndis_altmem_rid, sc->ndis_res_altmem); if (sc->ndis_sc) ndis_destroy_dma(sc);