freebsd_network: Apply empty size and type check to IO ports.

Factor out the conversion to BAR index and hand the pci_info to both
memory and IO port allocation functions. Then apply the same checks
in the IO port case as are done for memory.

This aligns with what is done on FreeBSD.

Change-Id: Ib4bd28fd861959a467ba676de22efb1f97e5a27c
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3025
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Michael Lotz 2020-07-11 23:05:22 +02:00 committed by waddlesplash
parent 733e150b74
commit 8827bb6d89

View File

@ -110,29 +110,19 @@ bus_alloc_irq_resource(device_t dev, struct resource *res)
static int static int
bus_alloc_mem_resource(device_t dev, struct resource *res, int regid) bus_alloc_mem_resource(device_t dev, struct resource *res, pci_info *info,
int bar_index)
{ {
pci_info *info = &((struct root_device_softc *)dev->root->softc)->pci_info; uint32 addr = info->u.h0.base_registers[bar_index];
uint32 size = info->u.h0.base_register_sizes[bar_index];
// check the offset really is of a BAR uchar flags = info->u.h0.base_register_flags[bar_index];
if (regid < PCI_base_registers || (regid % sizeof(uint32) != 0)
|| (regid >= PCI_base_registers + 6 * (int)sizeof(uint32)))
return -1;
// turn offset into array index
regid -= PCI_base_registers;
regid /= sizeof(uint32);
uint32 addr = info->u.h0.base_registers[regid];
uint32 size = info->u.h0.base_register_sizes[regid];
uchar flags = info->u.h0.base_register_flags[regid];
// reject empty regions // reject empty regions
if (size == 0) if (size == 0)
return -1; return -1;
// reject I/O space // reject I/O space
if (flags & PCI_address_space) if ((flags & PCI_address_space) != 0)
return -1; return -1;
// TODO: check flags & PCI_address_prefetchable ? // TODO: check flags & PCI_address_prefetchable ?
@ -155,18 +145,46 @@ bus_alloc_mem_resource(device_t dev, struct resource *res, int regid)
static int static int
bus_alloc_ioport_resource(device_t dev, struct resource *res, int regid) bus_alloc_ioport_resource(device_t dev, struct resource *res, pci_info *info,
int bar_index)
{ {
uint32 size = info->u.h0.base_register_sizes[bar_index];
uchar flags = info->u.h0.base_register_flags[bar_index];
// reject empty regions
if (size == 0)
return -1;
// reject memory space
if ((flags & PCI_address_space) == 0)
return -1;
// enable this I/O resource // enable this I/O resource
if (pci_enable_io(dev, SYS_RES_IOPORT) != 0) if (pci_enable_io(dev, SYS_RES_IOPORT) != 0)
return -1; return -1;
res->r_bustag = X86_BUS_SPACE_IO; res->r_bustag = X86_BUS_SPACE_IO;
res->r_bushandle = pci_read_config(dev, regid, 4) & PCI_address_io_mask; res->r_bushandle = info->u.h0.base_registers[bar_index];
return 0; return 0;
} }
static int
bus_register_to_bar_index(pci_info *info, int regid)
{
// check the offset really is of a BAR
if (regid < PCI_base_registers || (regid % sizeof(uint32) != 0)
|| (regid >= PCI_base_registers + 6 * (int)sizeof(uint32))) {
return -1;
}
// turn offset into array index
regid -= PCI_base_registers;
regid /= sizeof(uint32);
return regid;
}
struct resource * struct resource *
bus_alloc_resource(device_t dev, int type, int *rid, unsigned long start, bus_alloc_resource(device_t dev, int type, int *rid, unsigned long start,
unsigned long end, unsigned long count, uint32 flags) unsigned long end, unsigned long count, uint32 flags)
@ -198,10 +216,17 @@ bus_alloc_resource(device_t dev, int type, int *rid, unsigned long start,
res->r_bushandle = info->u.h0.interrupt_line + *rid - 1; res->r_bushandle = info->u.h0.interrupt_line + *rid - 1;
result = 0; result = 0;
} }
} else if (type == SYS_RES_MEMORY) } else if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
result = bus_alloc_mem_resource(dev, res, *rid); pci_info *info
else if (type == SYS_RES_IOPORT) = &((struct root_device_softc *)dev->root->softc)->pci_info;
result = bus_alloc_ioport_resource(dev, res, *rid); int bar_index = bus_register_to_bar_index(info, *rid);
if (bar_index >= 0) {
if (type == SYS_RES_MEMORY)
result = bus_alloc_mem_resource(dev, res, info, bar_index);
else
result = bus_alloc_ioport_resource(dev, res, info, bar_index);
}
}
if (result < 0) { if (result < 0) {
free(res); free(res);