From owner-svn-src-all@FreeBSD.ORG Sun Aug 25 18:09:12 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 7E15857D; Sun, 25 Aug 2013 18:09:12 +0000 (UTC) (envelope-from dumbbell@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 5BD3D2A3A; Sun, 25 Aug 2013 18:09:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r7PI9Cjs052981; Sun, 25 Aug 2013 18:09:12 GMT (envelope-from dumbbell@svn.freebsd.org) Received: (from dumbbell@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r7PI9CsE052978; Sun, 25 Aug 2013 18:09:12 GMT (envelope-from dumbbell@svn.freebsd.org) Message-Id: <201308251809.r7PI9CsE052978@svn.freebsd.org> From: Jean-Sebastien Pedron Date: Sun, 25 Aug 2013 18:09:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r254882 - head/sys/dev/pci X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 25 Aug 2013 18:09:12 -0000 Author: dumbbell Date: Sun Aug 25 18:09:11 2013 New Revision: 254882 URL: http://svnweb.freebsd.org/changeset/base/254882 Log: vga_pci: Add API to map the Video BIOS Here are two new functions to map and unmap the Video BIOS: void * vga_pci_map_bios(device_t dev, size_t *size); void vga_pci_unmap_bios(device_t dev, void *bios); The BIOS is either taken from the shadow copy made by the System BIOS at boot time if the given device was used for the default display (i386, amd64 and ia64 only), or from the PCI expansion ROM. Additionally, one can determine if a given device was the default display at boot time using the following new function: void vga_pci_unmap_bios(device_t dev, void *bios); Modified: head/sys/dev/pci/pcivar.h head/sys/dev/pci/vga_pci.c Modified: head/sys/dev/pci/pcivar.h ============================================================================== --- head/sys/dev/pci/pcivar.h Sun Aug 25 17:26:05 2013 (r254881) +++ head/sys/dev/pci/pcivar.h Sun Aug 25 18:09:11 2013 (r254882) @@ -517,4 +517,11 @@ extern uint32_t pci_generation; struct pci_map *pci_find_bar(device_t dev, int reg); 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); + #endif /* _PCIVAR_H_ */ Modified: head/sys/dev/pci/vga_pci.c ============================================================================== --- head/sys/dev/pci/vga_pci.c Sun Aug 25 17:26:05 2013 (r254881) +++ head/sys/dev/pci/vga_pci.c Sun Aug 25 18:09:11 2013 (r254882) @@ -46,6 +46,11 @@ __FBSDID("$FreeBSD$"); #include #include +#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) +#include +#include +#endif + #include #include @@ -67,6 +72,99 @@ TUNABLE_INT("hw.pci.default_vgapci_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. + */ + + printf("%s: Mapping BIOS shadow\n", __func__); + *size = VGA_PCI_BIOS_SHADOW_SIZE; + return (pmap_mapbios(VGA_PCI_BIOS_SHADOW_ADDR, *size)); + } +#endif + + printf("%s: Mapping PCI expansion ROM\n", __func__); + 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. */ + printf("%s: Unmapping BIOS shadow\n", __func__); + 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. + */ + + printf("%s: Unmapping PCI expansion ROM\n", __func__); + 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) {