diff --git a/headers/private/kernel/boot/kernel_args.h b/headers/private/kernel/boot/kernel_args.h index c6ce809e00..a36ec90a63 100644 --- a/headers/private/kernel/boot/kernel_args.h +++ b/headers/private/kernel/boot/kernel_args.h @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. * 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; diff --git a/headers/private/kernel/boot_item.h b/headers/private/kernel/boot_item.h index 1dd05670df..30553cf3db 100644 --- a/headers/private/kernel/boot_item.h +++ b/headers/private/kernel/boot_item.h @@ -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. */ #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 } diff --git a/src/add-ons/accelerants/vesa/accelerant.cpp b/src/add-ons/accelerants/vesa/accelerant.cpp index 168ef012fa..77875efd37 100644 --- a/src/add-ons/accelerants/vesa/accelerant.cpp +++ b/src/add-ons/accelerants/vesa/accelerant.cpp @@ -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) { diff --git a/src/add-ons/accelerants/vesa/accelerant.h b/src/add-ons/accelerants/vesa/accelerant.h index f541555158..51bf68cd40 100644 --- a/src/add-ons/accelerants/vesa/accelerant.h +++ b/src/add-ons/accelerants/vesa/accelerant.h @@ -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. */ #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; diff --git a/src/add-ons/accelerants/vesa/mode.cpp b/src/add-ons/accelerants/vesa/mode.cpp index 07683b42b5..a862db3398 100644 --- a/src/add-ons/accelerants/vesa/mode.cpp +++ b/src/add-ons/accelerants/vesa/mode.cpp @@ -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; } diff --git a/src/add-ons/kernel/drivers/graphics/vesa/device.cpp b/src/add-ons/kernel/drivers/graphics/vesa/device.cpp index dd9653ab3c..e7f288ccba 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/device.cpp +++ b/src/add-ons/kernel/drivers/graphics/vesa/device.cpp @@ -1,26 +1,28 @@ /* - * Copyright 2005-2006, 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. */ #include "device.h" -#include "driver.h" -#include "utility.h" -#include "vesa_info.h" -#include "vga.h" - -#include -#include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include +#include + +#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: diff --git a/src/add-ons/kernel/drivers/graphics/vesa/driver.cpp b/src/add-ons/kernel/drivers/graphics/vesa/driver.cpp index 7d376b8a67..2a4dfecf5b 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/vesa/driver.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006, 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. */ @@ -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; } diff --git a/src/add-ons/kernel/drivers/graphics/vesa/driver.h b/src/add-ons/kernel/drivers/graphics/vesa/driver.h index 45d17c1ebf..aa4528c4b3 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/driver.h +++ b/src/add-ons/kernel/drivers/graphics/vesa/driver.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006, 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. */ #ifndef DRIVER_H @@ -9,7 +9,7 @@ #include #include -#include "vesa_info.h" +#include "vesa_private.h" #include "lock.h" diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp index 720ba052a1..fa33c2f000 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp +++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp @@ -1,20 +1,21 @@ /* - * Copyright 2005-2006, 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. */ -#include -#include - -#include "vesa_info.h" -#include "driver.h" -#include "utility.h" - -#include "util/kernel_cpp.h" +#include "vesa_private.h" #include +#include +#include +#include + +#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; diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h b/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h new file mode 100644 index 0000000000..15e6d48145 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h @@ -0,0 +1,32 @@ +/* + * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef VESA_PRIVATE_H +#define VESA_PRIVATE_H + + +#include +#include +#include + + +#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 */ diff --git a/src/system/boot/Jamfile b/src/system/boot/Jamfile index 5e47d6b8b0..21a720216c 100644 --- a/src/system/boot/Jamfile +++ b/src/system/boot/Jamfile @@ -1,6 +1,7 @@ SubDir HAIKU_TOP src system boot ; local librootFunctions = + abs.o byteorder.o ctype.o qsort.o diff --git a/src/system/boot/platform/bios_ia32/video.cpp b/src/system/boot/platform/bios_ia32/video.cpp index b242aab1a0..28c5ea0c74 100644 --- a/src/system/boot/platform/bios_ia32/video.cpp +++ b/src/system/boot/platform/bios_ia32/video.cpp @@ -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 diff --git a/src/system/kernel/boot_item.cpp b/src/system/kernel/boot_item.cpp index 24b5625ae6..332f266b3e 100644 --- a/src/system/kernel/boot_item.cpp +++ b/src/system/kernel/boot_item.cpp @@ -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; diff --git a/src/system/kernel/boot_splash.cpp b/src/system/kernel/boot_splash.cpp index c917a8cc9b..ecc0249eef 100644 --- a/src/system/kernel/boot_splash.cpp +++ b/src/system/kernel/boot_splash.cpp @@ -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); } diff --git a/src/system/kernel/debug/Jamfile b/src/system/kernel/debug/Jamfile index d3c30fdada..b6bcad14bf 100644 --- a/src/system/kernel/debug/Jamfile +++ b/src/system/kernel/debug/Jamfile @@ -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 diff --git a/src/system/kernel/debug/frame_buffer_console.cpp b/src/system/kernel/debug/frame_buffer_console.cpp index 957d4f2f4c..8634f727f4 100644 --- a/src/system/kernel/debug/frame_buffer_console.cpp +++ b/src/system/kernel/debug/frame_buffer_console.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #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; }