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.
This commit is contained in:
Bill Paul 2003-12-29 23:51:59 +00:00
parent 4560f4f0b1
commit 265745a5bf
2 changed files with 105 additions and 85 deletions

View File

@ -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;

View File

@ -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);