Here we move the code to map the PCI framebuffer into Forth. This is done by introducing a "pci-map-in" word on the /pci node to enable Forth code to perform memory-mapping as required.
This is a slight departure from the specification which requires a "map-in" word, but this is because the OpenBIOS PCI bus enumerator *always* configures BARs regardless of whether or not an FCode payload is detected. In order to avoid having to rewrite the bus enumeration code in Forth, we instead create a "pci-bar>pci-region" word which takes the BAR register as a parameter and returns the configured BAR bus address and size. This can then be passed to the "pci-map-in" word in order to do the work.
Finally with this in place, we can remove the mapping that takes place in vga_vbe_init().
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/drivers/pci.c | 56 ++++++++++++++++++++++----- openbios-devel/drivers/pci.fs | 77 ++++++++++++++++++++++++++++++++++++++ openbios-devel/drivers/vga.fs | 40 +++++++++++++++----- openbios-devel/drivers/vga_vbe.c | 8 ---- 4 files changed, 154 insertions(+), 27 deletions(-)
diff --git a/openbios-devel/drivers/pci.c b/openbios-devel/drivers/pci.c index 3f37fd8..368d7b5 100644 --- a/openbios-devel/drivers/pci.c +++ b/openbios-devel/drivers/pci.c @@ -17,6 +17,7 @@
#include "config.h" #include "libopenbios/bindings.h" +#include "libopenbios/ofmem.h" #include "kernel/kernel.h" #include "drivers/pci.h" #include "libc/byteorder.h" @@ -25,6 +26,7 @@ #include "drivers/drivers.h" #include "drivers/vga.h" #include "packages/video.h" +#include "libopenbios/video.h" #include "timer.h" #include "pci.h" #include "pci_database.h" @@ -139,6 +141,15 @@ static void dump_reg_property(const char* description, int nreg, u32 *reg) } #endif
+static unsigned long pci_bus_addr_to_host_addr(uint32_t ba) +{ +#ifdef CONFIG_SPARC64 + return arch->cfg_data + (unsigned long)ba; +#else + return (unsigned long)ba; +#endif +} + static void ob_pci_open(int *idx) { @@ -330,12 +341,48 @@ ob_pci_encode_unit(int *idx) ss, dev, fn, buf); }
+/* ( pci-addr.lo pci-addr.hi size -- virt ) */ + +static void +ob_pci_map_in(int *idx) +{ + phys_addr_t phys; + uint32_t ba; + ucell size, virt; + + PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx); + + size = POP(); + POP(); + ba = POP(); + + phys = pci_bus_addr_to_host_addr(ba); + +#if defined(CONFIG_OFMEM) + ofmem_claim_phys(phys, size, 0); + +#if defined(CONFIG_SPARC64) + /* Fix virtual address on SPARC64 somewhere else */ + virt = ofmem_claim_virt(0xfe000000ULL, size, 0); +#else + virt = ofmem_claim_virt(phys, size, 0); +#endif + + ofmem_map(phys, virt, size, ofmem_arch_io_translation_mode(phys)); + + PUSH(virt); +#else + PUSH(phys); +#endif +} + NODE_METHODS(ob_pci_bus_node) = { { NULL, ob_pci_initialize }, { "open", ob_pci_open }, { "close", ob_pci_close }, { "decode-unit", ob_pci_decode_unit }, { "encode-unit", ob_pci_encode_unit }, + { "pci-map-in", ob_pci_map_in }, };
NODE_METHODS(ob_pci_simple_node) = { @@ -485,15 +532,6 @@ static void pci_host_set_ranges(const pci_config_t *config) set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); }
-static unsigned long pci_bus_addr_to_host_addr(uint32_t ba) -{ -#ifdef CONFIG_SPARC64 - return arch->cfg_data + (unsigned long)ba; -#else - return (unsigned long)ba; -#endif -} - int host_config_cb(const pci_config_t *config) { //XXX this overrides "reg" property diff --git a/openbios-devel/drivers/pci.fs b/openbios-devel/drivers/pci.fs index e8d25a0..563b652 100644 --- a/openbios-devel/drivers/pci.fs +++ b/openbios-devel/drivers/pci.fs @@ -12,4 +12,81 @@ rot encode-int encode+ ;
+\ Get region offset for BAR reg +: pci-bar-offset@ ( bar-reg -- off.lo off.hi -1 | 0 ) + " reg" active-package get-package-property 0= if + begin + decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi ) + ff and 5 pick = if + >r >r 3drop r> r> + -1 exit + else + 2drop + then + \ Drop the size as we don't need it + decode-int drop decode-int drop + dup 0= + until + 3drop + 0 exit + else + 0 + then + ; + +\ Get region size for BAR reg +: pci-bar-size@ ( bar-reg -- size ) + " reg" active-package get-package-property 0= if + begin + decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi ) + ff and 5 pick = if + 2drop decode-int drop + decode-int + >r 3drop r> + exit + else + 2drop decode-int drop + decode-int drop + then + dup 0= + until + 3drop + 0 \ default size of 0 if BAR not found + then + ; + +\ Get base address for configured BAR reg +: pci-bar-base@ ( bar-reg -- addr.lo addr.hi -1 | 0 ) + " assigned-addresses" active-package get-package-property 0= if + begin + decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi ) + ff and 5 pick = if + >r >r 3drop r> r> + -1 exit + else + 2drop + then + \ Drop the size as we don't need it + decode-int drop decode-int drop + dup 0= + until + 3drop + 0 exit + else + 0 + then + ; + +\ Get PCI bus address and size for configured BAR reg +: pci-bar>pci-region ( bar-reg -- addr.lo addr.hi size ) + dup + >r pci-bar-offset@ if + swap r@ pci-bar-base@ if + swap d+ + then + swap r@ pci-bar-size@ + then + r> drop + ; + [THEN] diff --git a/openbios-devel/drivers/vga.fs b/openbios-devel/drivers/vga.fs index 43c8819..bf2ae60 100644 --- a/openbios-devel/drivers/vga.fs +++ b/openbios-devel/drivers/vga.fs @@ -106,6 +106,22 @@ h# 1 constant VBE_DISPI_ENABLED ;
\ +\ PCI +\ + +" pci-bar>pci-region" (find-xt) value pci-bar>pci-region-xt +: pci-bar>pci-region pci-bar>pci-region-xt execute ; + +h# 10 constant cfg-bar0 \ Framebuffer BAR +-1 value fb-addr + +: map-fb ( -- ) + cfg-bar0 pci-bar>pci-region \ ( pci-addr.lo pci-addr.hi size ) + " pci-map-in" $call-parent + to fb-addr +; + +\ \ Publically visible words \
@@ -165,23 +181,27 @@ headerless \
: qemu-vga-driver-install ( -- ) - openbios-video-addr to frame-buffer-adr - default-font set-font + fb-addr -1 = if + map-fb fb-addr to frame-buffer-adr + default-font set-font
- frame-buffer-adr encode-int " address" property - openbios-video-width encode-int " width" property - openbios-video-height encode-int " height" property - depth-bits encode-int " depth" property - line-bytes encode-int " linebytes" property + frame-buffer-adr encode-int " address" property
- openbios-video-width openbios-video-height over char-width / over char-height / - fb8-install + openbios-video-width openbios-video-height over char-width / over char-height / + fb8-install + then ;
: qemu-vga-driver-init + vbe-init + openbios-video-width encode-int " width" property + openbios-video-height encode-int " height" property + depth-bits encode-int " depth" property + line-bytes encode-int " linebytes" property + ['] qemu-vga-driver-install is-install - ; +;
qemu-vga-driver-init
diff --git a/openbios-devel/drivers/vga_vbe.c b/openbios-devel/drivers/vga_vbe.c index 8c224d6..2f845e7 100644 --- a/openbios-devel/drivers/vga_vbe.c +++ b/openbios-devel/drivers/vga_vbe.c @@ -98,12 +98,4 @@ void vga_vbe_init(const char *path, unsigned long fb, uint32_t fb_size, p + 8, size); } } - -#if defined(CONFIG_OFMEM) && defined(CONFIG_DRIVER_PCI) - size = ((VIDEO_DICT_VALUE(video.h) * VIDEO_DICT_VALUE(video.rb)) + 0xfff) & ~0xfff; - - ofmem_claim_phys( video.mphys, size, 0 ); - ofmem_claim_virt( VIDEO_DICT_VALUE(video.mvirt), size, 0 ); - ofmem_map( video.mphys, VIDEO_DICT_VALUE(video.mvirt), size, ofmem_arch_io_translation_mode(video.mphys) ); -#endif }