* 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. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34206 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4ea01167bd
commit
5472c0c23e
@ -17,6 +17,7 @@ struct kernel_args;
|
||||
|
||||
struct frame_buffer_boot_info {
|
||||
area_id area;
|
||||
addr_t physical_frame_buffer;
|
||||
addr_t frame_buffer;
|
||||
int32 width;
|
||||
int32 height;
|
||||
|
@ -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 @@ vbe_set_bits_per_gun(vesa_info& info, uint8 bits)
|
||||
}
|
||||
|
||||
|
||||
/*! 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,6 +301,12 @@ vesa_init(vesa_info& info)
|
||||
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,
|
||||
@ -227,7 +322,7 @@ vesa_init(vesa_info& info)
|
||||
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 @@ vesa_init(vesa_info& info)
|
||||
}
|
||||
|
||||
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 @@ vesa_init(vesa_info& info)
|
||||
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 @@ vesa_set_display_mode(vesa_info& info, uint32 mode)
|
||||
return status;
|
||||
}
|
||||
|
||||
area_id frameBufferArea;
|
||||
frame_buffer_boot_info* bufferInfo;
|
||||
struct vbe_mode_info modeInfo;
|
||||
|
||||
// Get mode information
|
||||
struct vbe_mode_info modeInfo;
|
||||
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,39 +404,17 @@ vesa_set_display_mode(vesa_info& info, uint32 mode)
|
||||
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);
|
||||
|
@ -29,6 +29,11 @@ struct vesa_info {
|
||||
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);
|
||||
|
@ -413,7 +413,7 @@ frame_buffer_console_init(kernel_args* args)
|
||||
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 @@ frame_buffer_console_init(kernel_args* args)
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user