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:
parent
4560f4f0b1
commit
265745a5bf
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user