On 29.08.2013 16:07, John Baldwin wrote: > Here is an untested cut at this, it only changes these functions and doesn't > fix the callers to work with the returned struct resource, etc.:
I attached an updated patch including changes to pcivar.h and radeon. However, BUS_ALLOC_RESOURCE() returns NULL in my tests. -- Jean-Sébastien Pédron
diff --git a/sys/dev/drm2/radeon/radeon_bios.c b/sys/dev/drm2/radeon/radeon_bios.c index b9ee4d1..11e9be4 100644 --- a/sys/dev/drm2/radeon/radeon_bios.c +++ b/sys/dev/drm2/radeon/radeon_bios.c @@ -100,6 +100,7 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev) static bool radeon_read_bios(struct radeon_device *rdev) { + struct resource *res; uint8_t __iomem *bios; size_t size; @@ -107,10 +108,13 @@ static bool radeon_read_bios(struct radeon_device *rdev) rdev->bios = NULL; /* XXX: some cards may return 0 for rom size? ddx has a workaround */ - bios = vga_pci_map_bios(rdev->dev, &size); - if (!bios) { + res = vga_pci_map_bios(rdev->dev); + DRM_INFO("%s: res=%p\n", __func__, res); + if (!res) { return false; } + bios = rman_get_virtual(res); + size = rman_get_size(res); DRM_INFO("%s: Map address: %p (%zu bytes)\n", __func__, bios, size); if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { @@ -120,11 +124,11 @@ static bool radeon_read_bios(struct radeon_device *rdev) DRM_INFO("%s: Incorrect BIOS signature: 0x%02X%02X\n", __func__, bios[0], bios[1]); } - vga_pci_unmap_bios(rdev->dev, bios); + vga_pci_unmap_bios(rdev->dev, res); } rdev->bios = malloc(size, DRM_MEM_DRIVER, M_WAITOK); memcpy(rdev->bios, bios, size); - vga_pci_unmap_bios(rdev->dev, bios); + vga_pci_unmap_bios(rdev->dev, res); return true; } diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index d733e3b..a8148e9 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -520,8 +520,8 @@ int pci_bar_enabled(device_t dev, struct pci_map *pm); #define VGA_PCI_BIOS_SHADOW_ADDR 0xC0000 #define VGA_PCI_BIOS_SHADOW_SIZE 131072 -int vga_pci_is_boot_display(device_t dev); -void * vga_pci_map_bios(device_t dev, size_t *size); -void vga_pci_unmap_bios(device_t dev, void *bios); +int vga_pci_is_boot_display(device_t dev); +struct resource * vga_pci_map_bios(device_t dev); +void vga_pci_unmap_bios(device_t dev, struct resource *res); #endif /* _PCIVAR_H_ */ diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c index 94c64c0..59c954e 100644 --- a/sys/dev/pci/vga_pci.c +++ b/sys/dev/pci/vga_pci.c @@ -46,11 +46,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/systm.h> -#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) -#include <vm/vm.h> -#include <vm/pmap.h> -#endif - #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -72,95 +67,6 @@ TUNABLE_INT("hw.pci.default_vgapci_unit", &vga_pci_default_unit); SYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RDTUN, &vga_pci_default_unit, -1, "Default VGA-compatible display"); -int -vga_pci_is_boot_display(device_t dev) -{ - - /* - * Return true if the given device is the default display used - * at boot time. - */ - - return ( - (pci_get_class(dev) == PCIC_DISPLAY || - (pci_get_class(dev) == PCIC_OLD && - pci_get_subclass(dev) == PCIS_OLD_VGA)) && - device_get_unit(dev) == vga_pci_default_unit); -} - -void * -vga_pci_map_bios(device_t dev, size_t *size) -{ - int rid; - struct resource *res; - -#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) - if (vga_pci_is_boot_display(dev)) { - /* - * On x86, the System BIOS copy the default display - * device's Video BIOS at a fixed location in system - * memory (0xC0000, 128 kBytes long) at boot time. - * - * We use this copy for the default boot device, because - * the original ROM may not be valid after boot. - */ - - *size = VGA_PCI_BIOS_SHADOW_SIZE; - return (pmap_mapbios(VGA_PCI_BIOS_SHADOW_ADDR, *size)); - } -#endif - - rid = PCIR_BIOS; - res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (res == NULL) { - return (NULL); - } - - *size = rman_get_size(res); - return (rman_get_virtual(res)); -} - -void -vga_pci_unmap_bios(device_t dev, void *bios) -{ - int rid; - struct resource *res; - - if (bios == NULL) { - return; - } - -#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) - if (vga_pci_is_boot_display(dev)) { - /* We mapped the BIOS shadow copy located at 0xC0000. */ - pmap_unmapdev((vm_offset_t)bios, VGA_PCI_BIOS_SHADOW_SIZE); - - return; - } -#endif - - /* - * FIXME: We returned only the virtual address of the resource - * to the caller. Now, to get the resource struct back, we - * allocate it again: the struct exists once in memory in - * device softc. Therefore, we release twice now to release the - * reference we just obtained to get the structure back and the - * caller's reference. - */ - - rid = PCIR_BIOS; - res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - - KASSERT(res != NULL, - ("%s: Can't get BIOS resource back", __func__)); - KASSERT(bios == rman_get_virtual(res), - ("%s: Given BIOS address doesn't match " - "resource virtual address", __func__)); - - bus_release_resource(dev, SYS_RES_MEMORY, rid, bios); - bus_release_resource(dev, SYS_RES_MEMORY, rid, bios); -} - static int vga_pci_probe(device_t dev) { @@ -327,6 +233,75 @@ vga_pci_release_resource(device_t dev, device_t child, int type, int rid, return (bus_release_resource(dev, type, rid, r)); } +int +vga_pci_is_boot_display(device_t dev) +{ + + /* + * Return true if the given device is the default display used + * at boot time. + */ + + return ( + (pci_get_class(dev) == PCIC_DISPLAY || + (pci_get_class(dev) == PCIC_OLD && + pci_get_subclass(dev) == PCIS_OLD_VGA)) && + device_get_unit(dev) == vga_pci_default_unit); +} + +struct resource * +vga_pci_map_bios(device_t dev) +{ + int rid; + +#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) + if (vga_pci_is_boot_display(dev)) { + /* + * On x86, the System BIOS copy the default display + * device's Video BIOS at a fixed location in system + * memory (0xC0000, 128 kBytes long) at boot time. + * + * We use this copy for the default boot device, because + * the original ROM may not be valid after boot. + * + * Allocate this from our grandparent to by-pass the + * checks for a valid rid in the PCI bus driver as this + * is not a BAR. + */ + rid = 1; + return (BUS_ALLOC_RESOURCE(device_get_parent( + device_get_parent(dev)), dev, SYS_RES_MEMORY, &rid, + VGA_PCI_BIOS_SHADOW_ADDR, + VGA_PCI_BIOS_SHADOW_ADDR + VGA_PCI_BIOS_SHADOW_SIZE - 1, + VGA_PCI_BIOS_SHADOW_SIZE, RF_ACTIVE)); + } +#endif + + rid = PCIR_BIOS; + return (vga_pci_alloc_resource(dev, NULL, SYS_RES_MEMORY, &rid, 0ul, + ~0ul, 1, RF_ACTIVE)); +} + +void +vga_pci_unmap_bios(device_t dev, struct resource *res) +{ + + if (res == NULL) { + return; + } + +#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) + if (vga_pci_is_boot_display(dev)) { + /* We mapped the BIOS shadow copy located at 0xC0000. */ + BUS_RELEASE_RESOURCE(device_get_parent( + device_get_parent(dev)), dev, SYS_RES_MEMORY, 1, res); + + return; + } +#endif + vga_pci_release_resource(dev, NULL, SYS_RES_MEMORY, PCIR_BIOS, res); +} + /* PCI interface. */ static uint32_t
signature.asc
Description: OpenPGP digital signature