[haiku-commits] r34206 - in haiku/trunk: headers/private/kernel src/add-ons/kernel/drivers/graphics/vesa src/system/kernel/debug

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 24 Nov 2009 16:26:52 +0100 (CET)

Author: axeld
Date: 2009-11-24 16:26:52 +0100 (Tue, 24 Nov 2009)
New Revision: 34206
Changeset: http://dev.haiku-os.org/changeset/34206/haiku

Modified:
   haiku/trunk/headers/private/kernel/frame_buffer_console.h
   haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
   haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h
   haiku/trunk/src/system/kernel/debug/frame_buffer_console.cpp
Log:
* The VESA driver now tries to find the PCI card that it is controlling by
  checking the physical frame buffer location.
* This allows us to map the whole frame buffer at once, which means there is no
  need anymore to remap the memory on mode change.
* Also, this will ease the burden of the MTRRs, as the memory size will be
  properly aligned.


Modified: haiku/trunk/headers/private/kernel/frame_buffer_console.h
===================================================================
--- haiku/trunk/headers/private/kernel/frame_buffer_console.h   2009-11-24 
14:53:22 UTC (rev 34205)
+++ haiku/trunk/headers/private/kernel/frame_buffer_console.h   2009-11-24 
15:26:52 UTC (rev 34206)
@@ -17,6 +17,7 @@
 
 struct frame_buffer_boot_info {
        area_id area;
+       addr_t  physical_frame_buffer;
        addr_t  frame_buffer;
        int32   width;
        int32   height;

Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp       
2009-11-24 14:53:22 UTC (rev 34205)
+++ haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp       
2009-11-24 15:26:52 UTC (rev 34206)
@@ -20,6 +20,40 @@
 #include "vesa_info.h"
 
 
+static status_t
+find_graphics_card(addr_t frameBuffer, addr_t& base, size_t& size)
+{
+       // TODO: when we port this over to the new driver API, this mechanism 
can be
+       // used to find the right device_node
+       pci_module_info* pci;
+       if (get_module(B_PCI_MODULE_NAME, (module_info**)&pci) != B_OK)
+               return B_ERROR;
+
+       pci_info info;
+       for (int32 index = 0; pci->get_nth_pci_info(index, &info) == B_OK; 
index++) {
+               if (info.class_base != PCI_display)
+                       continue;
+
+               // check PCI BARs
+               for (uint32 i = 0; i < 6; i++) {
+                       if (info.u.h0.base_registers[i] <= frameBuffer
+                               && info.u.h0.base_registers[i] + 
info.u.h0.base_register_sizes[i]
+                                       > frameBuffer) {
+                               // found it!
+                               base = info.u.h0.base_registers[i];
+                               size = info.u.h0.base_register_sizes[i];
+
+                               put_module(B_PCI_MODULE_NAME);
+                               return B_OK;
+                       }
+               }
+       }
+
+       put_module(B_PCI_MODULE_NAME);
+       return B_ENTRY_NOT_FOUND;
+}
+
+
 static uint32
 get_color_space_for_depth(uint32 depth)
 {
@@ -200,6 +234,61 @@
 }
 
 
+/*!    Remaps the frame buffer if necessary; if we've already mapped the 
complete
+       frame buffer, there is no need to map it again.
+*/
+static status_t
+remap_frame_buffer(vesa_info& info, addr_t physicalBase,
+       uint32 bytesPerRow, uint32 height, bool initializing)
+{
+       vesa_shared_info& sharedInfo = *info.shared_info;
+       addr_t frameBuffer;
+
+       if (!info.complete_frame_buffer_mapped) {
+               addr_t base = physicalBase;
+               size_t size = bytesPerRow * height;
+               bool remap = !initializing;
+
+               if (info.physical_frame_buffer_size != 0) {
+                       // we can map the complete frame buffer
+                       base = info.physical_frame_buffer;
+                       size = info.physical_frame_buffer_size;
+                       remap = true;
+               }
+
+               if (remap) {
+                       area_id area = map_physical_memory("vesa frame buffer", 
(void*)base,
+                               size, B_ANY_KERNEL_ADDRESS, B_READ_AREA | 
B_WRITE_AREA,
+                               (void**)&frameBuffer);
+                       if (area < 0)
+                               return area;
+
+                       delete_area(info.shared_info->frame_buffer_area);
+
+                       info.frame_buffer = frameBuffer;
+                       sharedInfo.frame_buffer_area = area;
+
+                       // Turn on write combining for the area
+                       vm_set_area_memory_type(area, base, B_MTR_WC);
+
+                       if (info.physical_frame_buffer_size != 0)
+                               info.complete_frame_buffer_mapped = true;
+               }
+       } else
+               frameBuffer = info.frame_buffer;
+
+       if (info.complete_frame_buffer_mapped)
+               frameBuffer += physicalBase - info.physical_frame_buffer;
+
+       // Update shared frame buffer information
+       sharedInfo.frame_buffer = (uint8*)frameBuffer;
+       sharedInfo.physical_frame_buffer = (uint8*)physicalBase;
+       sharedInfo.bytes_per_row = bytesPerRow;
+
+       return B_OK;
+}
+
+
 //     #pragma mark -
 
 
@@ -212,7 +301,13 @@
                return B_ERROR;
 
        info.vbe_capabilities = bufferInfo->vesa_capabilities;
+       info.complete_frame_buffer_mapped = false;
 
+       // Find out which PCI device we belong to, so that we know its frame 
buffer
+       // size
+       find_graphics_card(bufferInfo->physical_frame_buffer,
+               info.physical_frame_buffer, info.physical_frame_buffer_size);
+
        size_t modesSize = 0;
        vesa_mode* modes = (vesa_mode*)get_boot_item(VESA_MODES_BOOT_INFO,
                &modesSize);
@@ -227,7 +322,7 @@
        if (info.shared_area < 0)
                return info.shared_area;
 
-       vesa_shared_info &sharedInfo = *info.shared_info;
+       vesa_shared_info& sharedInfo = *info.shared_info;
 
        memset(&sharedInfo, 0, sizeof(vesa_shared_info));
 
@@ -239,13 +334,16 @@
        }
 
        sharedInfo.frame_buffer_area = bufferInfo->area;
-       sharedInfo.frame_buffer = (uint8*)bufferInfo->frame_buffer;
 
+       remap_frame_buffer(info, bufferInfo->physical_frame_buffer,
+               bufferInfo->bytes_per_row, bufferInfo->height, true);
+               // Does not matter if this fails - the frame buffer was already 
mapped
+               // before.
+
        sharedInfo.current_mode.virtual_width = bufferInfo->width;
        sharedInfo.current_mode.virtual_height = bufferInfo->height;
        sharedInfo.current_mode.space = get_color_space_for_depth(
                bufferInfo->depth);
-       sharedInfo.bytes_per_row = bufferInfo->bytes_per_row;
 
        edid1_info* edidInfo = (edid1_info*)get_boot_item(VESA_EDID_BOOT_INFO,
                NULL);
@@ -259,10 +357,6 @@
        if (bufferInfo->depth <= 8)
                vbe_set_bits_per_gun(info, 8);
 
-       physical_entry mapping;
-       get_memory_map((void*)sharedInfo.frame_buffer, B_PAGE_SIZE, &mapping, 
1);
-       sharedInfo.physical_frame_buffer = (uint8*)mapping.address;
-
        dprintf(DEVICE_NAME ": vesa_init() completed successfully!\n");
        return B_OK;
 }
@@ -292,11 +386,8 @@
                return status;
        }
 
-       area_id frameBufferArea;
-       frame_buffer_boot_info* bufferInfo;
+       // Get mode information
        struct vbe_mode_info modeInfo;
-
-       // Get mode information
        status = vbe_get_mode_info(vmState, info.modes[mode].mode, &modeInfo);
        if (status != B_OK) {
                dprintf(DEVICE_NAME": vesa_set_display_mode(): cannot get mode 
info\n");
@@ -313,40 +404,18 @@
        if (info.modes[mode].bits_per_pixel <= 8)
                vbe_set_bits_per_gun(vmState, info, 8);
 
-       // Map new frame buffer
-       void* frameBuffer;
-       frameBufferArea = map_physical_memory("vesa_fb",
-               (void*)modeInfo.physical_base, modeInfo.bytes_per_row * 
modeInfo.height,
-               B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA, &frameBuffer);
-       if (frameBufferArea < B_OK) {
-               status = (status_t)frameBufferArea;
-               goto out;
+       // Map new frame buffer if necessary
+
+       status = remap_frame_buffer(info, modeInfo.physical_base,
+               modeInfo.bytes_per_row, modeInfo.height, false);
+       if (status == B_OK) {
+               // Update shared frame buffer information
+               info.shared_info->current_mode.virtual_width = modeInfo.width;
+               info.shared_info->current_mode.virtual_height = modeInfo.height;
+               info.shared_info->current_mode.space = 
get_color_space_for_depth(
+                       modeInfo.bits_per_pixel);
        }
-       delete_area(info.shared_info->frame_buffer_area);
 
-       // Turn on write combining for the area
-       vm_set_area_memory_type(frameBufferArea, modeInfo.physical_base, 
B_MTR_WC);
-
-       // Update shared frame buffer information
-       info.shared_info->frame_buffer_area = frameBufferArea;
-       info.shared_info->frame_buffer = (uint8*)frameBuffer;
-       info.shared_info->physical_frame_buffer = 
(uint8*)modeInfo.physical_base;
-       info.shared_info->bytes_per_row = modeInfo.bytes_per_row;
-       info.shared_info->current_mode.virtual_width = modeInfo.width;
-       info.shared_info->current_mode.virtual_height = modeInfo.height;
-       info.shared_info->current_mode.space = get_color_space_for_depth(
-               modeInfo.bits_per_pixel);
-
-       // Update boot item as it's used in vesa_init()
-       bufferInfo
-               = 
(frame_buffer_boot_info*)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL);
-       bufferInfo->area = frameBufferArea;
-       bufferInfo->frame_buffer = (addr_t)frameBuffer;
-       bufferInfo->width = modeInfo.width;
-       bufferInfo->height = modeInfo.height;
-       bufferInfo->depth = modeInfo.bits_per_pixel;
-       bufferInfo->bytes_per_row = modeInfo.bytes_per_row;
-
 out:
        vm86_cleanup(&vmState);
        return status;

Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h 
2009-11-24 14:53:22 UTC (rev 34205)
+++ haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h 
2009-11-24 15:26:52 UTC (rev 34206)
@@ -29,6 +29,11 @@
        uint32                  vbe_dpms_capabilities;
        uint8                   vbe_capabilities;
        uint8                   bits_per_gun;
+
+       addr_t                  frame_buffer;
+       addr_t                  physical_frame_buffer;
+       size_t                  physical_frame_buffer_size;
+       bool                    complete_frame_buffer_mapped;
 };
 
 extern status_t vesa_init(vesa_info& info);

Modified: haiku/trunk/src/system/kernel/debug/frame_buffer_console.cpp
===================================================================
--- haiku/trunk/src/system/kernel/debug/frame_buffer_console.cpp        
2009-11-24 14:53:22 UTC (rev 34205)
+++ haiku/trunk/src/system/kernel/debug/frame_buffer_console.cpp        
2009-11-24 15:26:52 UTC (rev 34206)
@@ -413,7 +413,7 @@
        mutex_init(&sConsole.lock, "console_lock");
 
        void* frameBuffer;
-       sConsole.area = map_physical_memory("vesa_fb",
+       sConsole.area = map_physical_memory("vesa frame buffer",
                (void*)args->frame_buffer.physical_buffer.start,
                args->frame_buffer.physical_buffer.size, B_ANY_KERNEL_ADDRESS,
                B_READ_AREA | B_WRITE_AREA | B_USER_CLONEABLE_AREA, 
&frameBuffer);
@@ -425,6 +425,7 @@
                args->frame_buffer.bytes_per_row);
 
        sBootInfo.area = sConsole.area;
+       sBootInfo.physical_frame_buffer = 
args->frame_buffer.physical_buffer.start;
        sBootInfo.frame_buffer = (addr_t)frameBuffer;
        sBootInfo.width = args->frame_buffer.width;
        sBootInfo.height = args->frame_buffer.height;


Other related posts: