* Changed get_boot_item() API: it now also can retrieve the size of the boot

item entry.
* The bios_ia32 video platform code now stores the available VESA modes in
  the new vesa_modes kernel_args field.
* When configuring a VESA mode via settings file, it's no longer needed to
  specify the exact mode - the closest available mode is now used. This should
  help with bug #1962.
* frame_buffer_console_init() now also creates a boot_item for the VESA modes
  in the kernel_args.
* The VESA accelerant now filters the mode list to only contain modes that
  are actually supported.
* Moved non-shared vesa driver data into its own file vesa_private.h.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24675 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-03-30 11:01:41 +00:00
parent 5de171daf3
commit 6328832fba
16 changed files with 241 additions and 88 deletions
+4 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007, Axel Dörfler, [email protected].
* Copyright 2002-2008, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@@ -71,6 +71,9 @@ typedef struct kernel_args {
bool enabled;
} frame_buffer;
void *vesa_modes;
uint32 vesa_modes_size;
void *debug_output;
uint32 debug_size;
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_BOOT_ITEM_H
@@ -15,7 +15,7 @@ extern "C" {
extern status_t boot_item_init(void);
extern status_t add_boot_item(const char *name, void *data, size_t size);
extern void *get_boot_item(const char *name);
extern void *get_boot_item(const char *name, size_t *_size);
#ifdef __cplusplus
}
+4 -4
View File
@@ -110,14 +110,15 @@ init_common(int device, bool isClone)
return status;
}
gInfo->vesa_modes = (vesa_mode *)((uint8 *)gInfo->shared_info
+ gInfo->shared_info->vesa_mode_offset);
sharedCloner.Keep();
return B_OK;
}
/** Cleans up everything done by a successful init_common().
*/
/*! Cleans up everything done by a successful init_common(). */
static void
uninit_common(void)
{
@@ -138,7 +139,6 @@ uninit_common(void)
/*! Init primary accelerant */
status_t
vesa_init_accelerant(int device)
{
+6 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef VESA_ACCELERANT_H
@@ -10,14 +10,17 @@
typedef struct accelerant_info {
int device; // file descriptor of kernel device
int device;
bool is_clone;
area_id shared_info_area;
vesa_shared_info *shared_info;
area_id mode_list_area; // cloned list of standard display modes
area_id mode_list_area;
// cloned list of standard display modes
display_mode *mode_list;
vesa_mode *vesa_modes;
} accelerant_info;
extern accelerant_info *gInfo;
+49 -5
View File
@@ -21,6 +21,48 @@ extern "C" void _sPrintf(const char *format, ...);
#endif
static uint32
get_color_space_for_depth(uint32 depth)
{
switch (depth) {
case 4:
return B_GRAY8;
// the app_server is smart enough to translate this to VGA mode
case 8:
return B_CMAP8;
case 15:
return B_RGB15;
case 16:
return B_RGB16;
case 24:
return B_RGB24;
case 32:
return B_RGB32;
}
return 0;
}
/*! Checks if the specified \a mode can be set using VESA. */
static bool
is_mode_supported(display_mode *mode)
{
vesa_mode *modes = gInfo->vesa_modes;
for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) {
// search mode in VESA mode list
// TODO: list is ordered, we could use binary search
if (modes[i].width == mode->virtual_width
&& modes[i].height == mode->virtual_height
&& get_color_space_for_depth(modes[i].bits_per_pixel)
== mode->space)
return true;
}
return false;
}
/*! Creates the initial mode list of the primary accelerant.
It's called from vesa_init_accelerant().
@@ -28,11 +70,12 @@ extern "C" void _sPrintf(const char *format, ...);
status_t
create_mode_list(void)
{
// ToDo: basically, the boot loader should pass a list of all supported
// VESA modes to us.
const color_space kVesaSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE,
B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8};
gInfo->mode_list_area = create_display_modes("vesa modes", NULL, NULL, 0,
NULL, 0, NULL, &gInfo->mode_list, &gInfo->shared_info->mode_count);
kVesaSpaces, sizeof(kVesaSpaces) / sizeof(kVesaSpaces[0]),
is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count);
if (gInfo->mode_list_area < B_OK)
return gInfo->mode_list_area;
@@ -56,7 +99,8 @@ status_t
vesa_get_mode_list(display_mode *modeList)
{
TRACE(("vesa_get_mode_info()\n"));
memcpy(modeList, gInfo->mode_list, gInfo->shared_info->mode_count * sizeof(display_mode));
memcpy(modeList, gInfo->mode_list,
gInfo->shared_info->mode_count * sizeof(display_mode));
return B_OK;
}
@@ -1,26 +1,28 @@
/*
* Copyright 2005-2006, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "device.h"
#include "driver.h"
#include "utility.h"
#include "vesa_info.h"
#include "vga.h"
#include <OS.h>
#include <KernelExport.h>
#include <Drivers.h>
#include <PCI.h>
#include <SupportDefs.h>
#include <graphic_driver.h>
#include <image.h>
#include <stdlib.h>
#include <string.h>
#include <Drivers.h>
#include <graphic_driver.h>
#include <image.h>
#include <KernelExport.h>
#include <OS.h>
#include <PCI.h>
#include <SupportDefs.h>
#include "driver.h"
#include "utility.h"
#include "vesa_info.h"
#include "vesa_private.h"
#include "vga.h"
//#define TRACE_DEVICE
#ifdef TRACE_DEVICE
@@ -128,8 +130,11 @@ device_ioctl(void *cookie, uint32 msg, void *buffer, size_t bufferLength)
switch (msg) {
case B_GET_ACCELERANT_SIGNATURE:
user_strlcpy((char *)buffer, VESA_ACCELERANT_NAME, B_FILE_NAME_LENGTH);
dprintf(DEVICE_NAME ": acc: %s\n", VESA_ACCELERANT_NAME);
if (user_strlcpy((char *)buffer, VESA_ACCELERANT_NAME,
B_FILE_NAME_LENGTH) < B_OK)
return B_BAD_ADDRESS;
return B_OK;
// needed to share data between kernel and accelerant
@@ -138,8 +143,10 @@ device_ioctl(void *cookie, uint32 msg, void *buffer, size_t bufferLength)
// needed for cloning
case VESA_GET_DEVICE_NAME:
if (user_strlcpy((char *)buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH) < B_OK)
if (user_strlcpy((char *)buffer, gDeviceNames[info->id],
B_PATH_NAME_LENGTH) < B_OK)
return B_BAD_ADDRESS;
return B_OK;
case VGA_SET_INDEXED_COLORS:
@@ -1,5 +1,5 @@
/*
* Copyright 2005-2006, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
@@ -75,7 +75,7 @@ init_hardware(void)
{
TRACE((DEVICE_NAME ": init_hardware()\n"));
return get_boot_item(FRAME_BUFFER_BOOT_INFO) != NULL ? B_OK : B_ERROR;
return get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL) != NULL ? B_OK : B_ERROR;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2005-2006, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef DRIVER_H
@@ -9,7 +9,7 @@
#include <KernelExport.h>
#include <ISA.h>
#include "vesa_info.h"
#include "vesa_private.h"
#include "lock.h"
@@ -1,20 +1,21 @@
/*
* Copyright 2005-2006, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <boot_item.h>
#include <frame_buffer_console.h>
#include "vesa_info.h"
#include "driver.h"
#include "utility.h"
#include "util/kernel_cpp.h"
#include "vesa_private.h"
#include <string.h>
#include <boot_item.h>
#include <frame_buffer_console.h>
#include <util/kernel_cpp.h>
#include "driver.h"
#include "utility.h"
#include "vesa_info.h"
class PhysicalMemoryMapper {
public:
@@ -65,55 +66,77 @@ PhysicalMemoryMapper::Keep()
// #pragma mark -
static uint32
get_color_space_for_depth(uint32 depth)
{
switch (depth) {
case 4:
return B_GRAY8;
// the app_server is smart enough to translate this to VGA mode
case 8:
return B_CMAP8;
case 15:
return B_RGB15;
case 16:
return B_RGB16;
case 24:
return B_RGB24;
case 32:
return B_RGB32;
}
return 0;
}
// #pragma mark -
status_t
vesa_init(vesa_info &info)
{
frame_buffer_boot_info *bufferInfo
= (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO);
= (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL);
if (bufferInfo == NULL)
return B_ERROR;
info.shared_area = create_area("vesa shared info", (void **)&info.shared_info,
B_ANY_KERNEL_ADDRESS, ROUND_TO_PAGE_SIZE(sizeof(vesa_shared_info)),
B_FULL_LOCK,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
size_t modesSize = 0;
vesa_mode *modes = (vesa_mode *)get_boot_item(VESA_MODES_BOOT_INFO,
&modesSize);
size_t sharedSize = (sizeof(vesa_shared_info) + 7) & ~7;
info.shared_area = create_area("vesa shared info",
(void **)&info.shared_info, B_ANY_KERNEL_ADDRESS,
ROUND_TO_PAGE_SIZE(sharedSize + modesSize), B_FULL_LOCK,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
if (info.shared_area < B_OK)
return info.shared_area;
memset((void *)info.shared_info, 0, sizeof(vesa_shared_info));
vesa_shared_info &sharedInfo = *info.shared_info;
info.shared_info->frame_buffer_area = bufferInfo->area;
info.shared_info->frame_buffer = (uint8 *)bufferInfo->frame_buffer;
memset(/*(void *)*/&sharedInfo, 0, sizeof(vesa_shared_info));
info.shared_info->current_mode.virtual_width = bufferInfo->width;
info.shared_info->current_mode.virtual_height = bufferInfo->height;
switch (bufferInfo->depth) {
case 4:
info.shared_info->current_mode.space = B_GRAY8;
// the app_server is smart enough to translate this to VGA mode
break;
case 8:
info.shared_info->current_mode.space = B_CMAP8;
break;
case 15:
info.shared_info->current_mode.space = B_RGB15;
break;
case 16:
info.shared_info->current_mode.space = B_RGB16;
break;
case 24:
info.shared_info->current_mode.space = B_RGB24;
break;
case 32:
info.shared_info->current_mode.space = B_RGB32;
break;
if (modes != NULL) {
sharedInfo.vesa_mode_offset = sharedSize;
sharedInfo.vesa_mode_count = modesSize / sizeof(vesa_mode);
memcpy((uint8*)&sharedInfo + sharedSize, modes, modesSize);
}
info.shared_info->bytes_per_row = bufferInfo->bytes_per_row;
sharedInfo.frame_buffer_area = bufferInfo->area;
sharedInfo.frame_buffer = (uint8 *)bufferInfo->frame_buffer;
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;
physical_entry mapping;
get_memory_map((void *)info.shared_info->frame_buffer, B_PAGE_SIZE,
get_memory_map((void *)sharedInfo.frame_buffer, B_PAGE_SIZE,
&mapping, 1);
info.shared_info->physical_frame_buffer = (uint8 *)mapping.address;
sharedInfo.physical_frame_buffer = (uint8 *)mapping.address;
dprintf(DEVICE_NAME ": vesa_init() completed successfully!\n");
return B_OK;
@@ -0,0 +1,32 @@
/*
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef VESA_PRIVATE_H
#define VESA_PRIVATE_H
#include <Drivers.h>
#include <Accelerant.h>
#include <PCI.h>
#define DEVICE_NAME "vesa"
#define VESA_ACCELERANT_NAME "vesa.accelerant"
struct vesa_get_supported_modes;
struct vesa_info {
uint32 cookie_magic;
int32 open_count;
int32 id;
pci_info *pci;
struct vesa_shared_info *shared_info;
area_id shared_area;
};
extern status_t vesa_init(vesa_info &info);
extern void vesa_uninit(vesa_info &info);
#endif /* VESA_PRIVATE_H */
+1
View File
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src system boot ;
local librootFunctions =
abs.o
byteorder.o
ctype.o
qsort.o
+34 -8
View File
@@ -7,6 +7,7 @@
#include "video.h"
#include "bios.h"
#include "vesa.h"
#include "vesa_info.h"
#include "vga.h"
#include "mmu.h"
@@ -44,7 +45,8 @@ struct video_mode {
static vbe_info_block sInfo;
static video_mode *sMode, *sDefaultMode;
static bool sVesaCompatible;
struct list sModeList;
static struct list sModeList;
static uint32 sModeCount;
static addr_t sFrameBuffer;
static bool sModeChosen;
static bool sSettingsLoaded;
@@ -86,6 +88,7 @@ add_video_mode(video_mode *videoMode)
}
list_insert_item_before(&sModeList, mode, videoMode);
sModeCount++;
}
@@ -113,19 +116,24 @@ find_video_mode(int32 width, int32 height, bool allowPalette)
static video_mode *
find_video_mode(int32 width, int32 height, int32 depth)
closest_video_mode(int32 width, int32 height, int32 depth)
{
video_mode *bestMode = NULL;
uint32 bestDiff = 0;
video_mode *mode = NULL;
while ((mode = (video_mode *)list_get_next_item(&sModeList, mode))
!= NULL) {
if (mode->width == width
&& mode->height == height
&& mode->bits_per_pixel == depth) {
return mode;
uint32 diff = 2 * abs(mode->width - width) + abs(mode->height - height)
+ abs(mode->bits_per_pixel - depth);
if (bestMode == NULL || bestDiff > diff) {
bestMode = mode;
bestDiff = diff;
}
}
return NULL;
return bestMode;
}
@@ -196,7 +204,7 @@ get_mode_from_settings(void)
// search mode that fits
video_mode *mode = find_video_mode(width, height, depth);
video_mode *mode = closest_video_mode(width, height, depth);
if (mode != NULL) {
found = true;
sMode = mode;
@@ -905,6 +913,24 @@ platform_init_video(void)
TRACE(("VESA compatible graphics!\n"));
// store VESA modes into kernel args
vesa_mode *modes = (vesa_mode *)kernel_args_malloc(
sModeCount * sizeof(vesa_mode));
if (modes != NULL) {
video_mode *mode = NULL;
uint32 i = 0;
while ((mode = (video_mode *)list_get_next_item(&sModeList, mode))
!= NULL) {
modes[i].width = mode->width;
modes[i].height = mode->height;
modes[i].bits_per_pixel = mode->bits_per_pixel;
i++;
}
gKernelArgs.vesa_modes = modes;
gKernelArgs.vesa_modes_size = sModeCount * sizeof(vesa_mode);
}
edid1_info info;
if (vesa_get_edid(&info) == B_OK) {
// we got EDID information from the monitor, try to find a new default
+7 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
@@ -44,7 +44,7 @@ add_boot_item(const char *name, void *data, size_t size)
void *
get_boot_item(const char *name)
get_boot_item(const char *name, size_t *_size)
{
if (name == NULL || name[0] == '\0')
return NULL;
@@ -53,8 +53,12 @@ get_boot_item(const char *name)
for (ItemList::Iterator it = sItemList.GetIterator(); it.HasNext();) {
boot_item *item = it.Next();
if (!strcmp(name, item->name))
if (!strcmp(name, item->name)) {
if (_size != NULL)
*_size = item->size;
return item->data;
}
}
return NULL;
+2 -1
View File
@@ -176,7 +176,8 @@ boot_splash_init(void)
if (debug_screen_output_enabled())
return;
sInfo = (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO);
sInfo = (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO,
NULL);
}
+1
View File
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src system kernel debug ;
UsePrivateHeaders [ FDirName kernel debug ] syslog_daemon ;
UsePrivateHeaders [ FDirName graphics vesa ] ;
KernelMergeObject kernel_debug.o :
blue_screen.cpp
@@ -11,6 +11,7 @@
#include <vm.h>
#include <fs/devfs.h>
#include <boot/kernel_args.h>
#include <vesa_info.h>
#include <frame_buffer_console.h>
#include "font.h"
@@ -68,6 +69,7 @@ static uint32 sPalette32[] = {
static struct console_info sConsole;
static struct frame_buffer_boot_info sBootInfo;
static struct vesa_mode *sVesaModes;
static inline uint8
@@ -416,6 +418,12 @@ frame_buffer_console_init(kernel_args *args)
add_boot_item(FRAME_BUFFER_BOOT_INFO, &sBootInfo,
sizeof(frame_buffer_boot_info));
sVesaModes = (vesa_mode *)malloc(args->vesa_modes_size);
if (sVesaModes != NULL) {
memcpy(sVesaModes, args->vesa_modes, args->vesa_modes_size);
add_boot_item(VESA_MODES_BOOT_INFO, sVesaModes, args->vesa_modes_size);
}
return B_OK;
}