summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2003-12-29 23:51:59 +0000
committerwpaul <wpaul@FreeBSD.org>2003-12-29 23:51:59 +0000
commit5319092108879a7923e91f3e92090baf459d07ac (patch)
treeb45388e6cd933496160d1ab817fa9d54743a77a6
parentd6b72f0aa31100a5dba05f84a26aef9bce30fecb (diff)
downloadFreeBSD-src-5319092108879a7923e91f3e92090baf459d07ac.zip
FreeBSD-src-5319092108879a7923e91f3e92090baf459d07ac.tar.gz
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 <foo>" messages that are sometimes emitted during driver load.
-rw-r--r--sys/compat/ndis/kern_ndis.c56
-rw-r--r--sys/dev/if_ndis/if_ndis.c134
2 files changed, 105 insertions, 85 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index c88ea30..14d46da 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 e9e756d..46ead8d 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);
- }
-
- 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;
+ 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++;
+ }
}
- 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);
OpenPOWER on IntegriCloud