diff --git a/headers/private/graphics/vesa/utility.h b/headers/private/graphics/vesa/utility.h new file mode 100644 index 0000000000..b8040c7aeb --- /dev/null +++ b/headers/private/graphics/vesa/utility.h @@ -0,0 +1,10 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef UTILITY_H +#define UTILITY_H + +#define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1)) + +#endif /* UTILITY_H */ diff --git a/headers/private/graphics/vesa/vesa_info.h b/headers/private/graphics/vesa/vesa_info.h new file mode 100644 index 0000000000..fbfe2c2a63 --- /dev/null +++ b/headers/private/graphics/vesa/vesa_info.h @@ -0,0 +1,59 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef VESA_INFO_H +#define VESA_INFO_H + + +#include +#include +#include + + +#define DEVICE_NAME "vesa" +#define VESA_ACCELERANT_NAME "vesa.accelerant" + + +struct vesa_shared_info { + int32 type; + area_id mode_list_area; // area containing display mode list + uint32 mode_count; + display_mode current_mode; + uint32 bytes_per_row; + + area_id registers_area; // area of memory mapped registers + area_id frame_buffer_area; // area of frame buffer + uint8 *frame_buffer; // pointer to frame buffer (visible by all apps!) + uint8 *physical_frame_buffer; +}; + +struct vesa_info { + uint32 cookie_magic; + int32 open_count; + int32 id; + pci_info *pci; + uint8 *registers; + area_id registers_area; + struct vesa_shared_info *shared_info; + area_id shared_area; + uint8 *frame_buffer; + area_id frame_buffer_area; + uint8 *reloc_io; + area_id reloc_io_area; +}; + +//----------------- ioctl() interface ---------------- + +// list ioctls +enum { + VESA_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1, + VESA_GET_DEVICE_NAME, +}; + +//---------------------------------------------------------- + +extern status_t vesa_init(vesa_info &info); +extern void vesa_uninit(vesa_info &info); + +#endif /* VESA_INFO_H */ diff --git a/src/add-ons/accelerants/Jamfile b/src/add-ons/accelerants/Jamfile index 8c78ca4b5c..b8c5b83811 100644 --- a/src/add-ons/accelerants/Jamfile +++ b/src/add-ons/accelerants/Jamfile @@ -8,5 +8,6 @@ SubInclude OBOS_TOP src add-ons accelerants nvidia ; SubInclude OBOS_TOP src add-ons accelerants radeon ; SubInclude OBOS_TOP src add-ons accelerants tdfx ; SubInclude OBOS_TOP src add-ons accelerants skeleton ; +SubInclude OBOS_TOP src add-ons accelerants vesa ; SubIncludeGPL OBOS_TOP src add-ons accelerants atimach64 ; diff --git a/src/add-ons/accelerants/vesa/Jamfile b/src/add-ons/accelerants/vesa/Jamfile new file mode 100644 index 0000000000..8bc04a8902 --- /dev/null +++ b/src/add-ons/accelerants/vesa/Jamfile @@ -0,0 +1,15 @@ +SubDir OBOS_TOP src add-ons accelerants vesa ; + +UsePrivateHeaders graphics ; +UsePrivateHeaders [ FDirName graphics vesa ] ; + +#AddResources vesa.accelerant : vesa.accelerant.rdef ; + +Addon vesa.accelerant : accelerants : + accelerant.cpp + dpms.cpp + engine.cpp + hooks.cpp + mode.cpp + : false # this add-on is not executable + ; diff --git a/src/add-ons/accelerants/vesa/accelerant.cpp b/src/add-ons/accelerants/vesa/accelerant.cpp new file mode 100644 index 0000000000..6dfec5d403 --- /dev/null +++ b/src/add-ons/accelerants/vesa/accelerant.cpp @@ -0,0 +1,252 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "accelerant_protos.h" +#include "accelerant.h" + +#include +#include +#include +#include + + +//#define TRACE_ACCELERANT +#ifdef TRACE_ACCELERANT +extern "C" void _sPrintf(const char *format, ...); +# define TRACE(x) _sPrintf x +#else +# define TRACE(x) ; +#endif + + +struct accelerant_info *gInfo; + + +class AreaCloner { + public: + AreaCloner(); + ~AreaCloner(); + + area_id Clone(const char *name, void **_address, uint32 spec, + uint32 protection, area_id sourceArea); + status_t InitCheck() { return fArea < B_OK ? (status_t)fArea : B_OK; } + void Keep(); + + private: + area_id fArea; +}; + + +AreaCloner::AreaCloner() + : + fArea(-1) +{ +} + + +AreaCloner::~AreaCloner() +{ + if (fArea >= B_OK) + delete_area(fArea); +} + + +area_id +AreaCloner::Clone(const char *name, void **_address, uint32 spec, + uint32 protection, area_id sourceArea) +{ + fArea = clone_area(name, _address, spec, protection, sourceArea); + return fArea; +} + + +void +AreaCloner::Keep() +{ + fArea = -1; +} + + +// #pragma mark - + + +/** This is the common accelerant_info initializer. It is called by + * both, the first accelerant and all clones. + */ + +static status_t +init_common(int device, bool isClone) +{ + // initialize global accelerant info structure + + gInfo = (accelerant_info *)malloc(sizeof(accelerant_info)); + if (gInfo == NULL) + return B_NO_MEMORY; + + memset(gInfo, 0, sizeof(accelerant_info)); + + gInfo->is_clone = isClone; + gInfo->device = device; + + // get basic info from driver + + area_id sharedArea; + if (ioctl(device, VESA_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id)) != 0) { + free(gInfo); + return B_ERROR; + } + + AreaCloner sharedCloner; + gInfo->shared_info_area = sharedCloner.Clone("vesa shared info", + (void **)&gInfo->shared_info, B_ANY_ADDRESS, + B_READ_AREA | B_WRITE_AREA, + sharedArea); + status_t status = sharedCloner.InitCheck(); + if (status < B_OK) { + free(gInfo); + return status; + } + + sharedCloner.Keep(); + return B_OK; +} + + +/** Cleans up everything done by a successful init_common(). + */ + +static void +uninit_common(void) +{ + delete_area(gInfo->shared_info_area); + gInfo->shared_info_area = -1; + gInfo->shared_info = NULL; + + // close the file handle ONLY if we're the clone + // (this is what Be tells us ;) + if (gInfo->is_clone) + close(gInfo->device); + + free(gInfo); +} + + +// #pragma mark - +// public accelerant functions + + +/** init primary accelerant */ + +status_t +vesa_init_accelerant(int device) +{ + TRACE(("vesa_init_accelerant()\n")); + + status_t status = init_common(device, false); + if (status != B_OK) + return status; + + status = create_mode_list(); + if (status != B_OK) { + uninit_common(); + return status; + } + + return B_OK; +} + + +ssize_t +vesa_accelerant_clone_info_size(void) +{ + // clone info is device name, so return its maximum size + return B_PATH_NAME_LENGTH; +} + + +void +vesa_get_accelerant_clone_info(void *info) +{ + ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH); +} + + +status_t +vesa_clone_accelerant(void *info) +{ + TRACE(("vesa_clone_accelerant()\n")); + + // create full device name + char path[MAXPATHLEN]; + strcpy(path, "/dev"); + strcat(path, (const char *)info); + + int fd = open(path, B_READ_WRITE); + if (fd < 0) + return fd; + + status_t status = init_common(fd, true); + if (status != B_OK) + goto err1; + + // get read-only clone of supported display modes + status = gInfo->mode_list_area = clone_area( + "vesa cloned modes", (void **)&gInfo->mode_list, + B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area); + if (status < B_OK) + goto err2; + + return B_OK; + +err2: + uninit_common(); +err1: + close(fd); + return status; +} + + +/** This function is called for both, the primary accelerant and all of + * its clones. + */ + +void +vesa_uninit_accelerant(void) +{ + TRACE(("vesa_uninit_accelerant()\n")); + + // delete accelerant instance data + delete_area(gInfo->mode_list_area); + gInfo->mode_list = NULL; + + uninit_common(); +} + + +status_t +vesa_get_accelerant_device_info(accelerant_device_info *info) +{ + info->version = B_ACCELERANT_VERSION; + strcpy(info->name, "VESA Driver"); + strcpy(info->chipset, "VESA"); + // ToDo: provide some more insight here... + strcpy(info->serial_no, "None"); + +#if 0 + info->memory = ??? + info->dac_speed = ??? +#endif + + return B_OK; +} + + +sem_id +vesa_accelerant_retrace_semaphore() +{ + return -1; +} + diff --git a/src/add-ons/accelerants/vesa/accelerant.h b/src/add-ons/accelerants/vesa/accelerant.h new file mode 100644 index 0000000000..f541555158 --- /dev/null +++ b/src/add-ons/accelerants/vesa/accelerant.h @@ -0,0 +1,27 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef VESA_ACCELERANT_H +#define VESA_ACCELERANT_H + + +#include "vesa_info.h" + + +typedef struct accelerant_info { + int device; // file descriptor of kernel 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 + display_mode *mode_list; +} accelerant_info; + +extern accelerant_info *gInfo; + +extern status_t create_mode_list(void); + +#endif /* VESA_ACCELERANT_H */ diff --git a/src/add-ons/accelerants/vesa/accelerant_protos.h b/src/add-ons/accelerants/vesa/accelerant_protos.h new file mode 100644 index 0000000000..845e2570ff --- /dev/null +++ b/src/add-ons/accelerants/vesa/accelerant_protos.h @@ -0,0 +1,77 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _ACCELERANT_PROTOS_H +#define _ACCELERANT_PROTOS_H + + +#include +#include "video_overlay.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +// general +status_t vesa_init_accelerant(int fd); +ssize_t vesa_accelerant_clone_info_size(void); +void vesa_get_accelerant_clone_info(void *data); +status_t vesa_clone_accelerant(void *data); +void vesa_uninit_accelerant(void); +status_t vesa_get_accelerant_device_info(accelerant_device_info *adi); +sem_id vesa_accelerant_retrace_semaphore(void); + +// modes & constraints +uint32 vesa_accelerant_mode_count(void); +status_t vesa_get_mode_list(display_mode *dm); +status_t vesa_propose_display_mode(display_mode *target, const display_mode *low, const display_mode *high); +status_t vesa_set_display_mode(display_mode *mode_to_set); +status_t vesa_get_display_mode(display_mode *current_mode); +status_t vesa_get_frame_buffer_config(frame_buffer_config *config); +status_t vesa_get_pixel_clock_limits(display_mode *dm, uint32 *low, uint32 *high); +status_t vesa_move_display(uint16 h_display_start, uint16 v_display_start); +status_t vesa_get_timing_constraints(display_timing_constraints *dtc); +void vesa_set_indexed_colors(uint count, uint8 first, uint8 *color_data, uint32 flags); + +// DPMS +uint32 vesa_dpms_capabilities(void); +uint32 vesa_dpms_mode(void); +status_t vesa_set_dpms_mode(uint32 dpms_flags); + +// cursor +status_t vesa_set_cursor_shape(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask); +void vesa_move_cursor(uint16 x, uint16 y); +void vesa_show_cursor(bool is_visible); + +// accelerant engine +uint32 vesa_accelerant_engine_count(void); +status_t vesa_acquire_engine(uint32 capabilities, uint32 max_wait, sync_token *st, engine_token **et); +status_t vesa_release_engine(engine_token *et, sync_token *st); +void vesa_wait_engine_idle(void); +status_t vesa_get_sync_token(engine_token *et, sync_token *st); +status_t vesa_sync_to_token(sync_token *st); + +// 2D acceleration +void vesa_screen_to_screen_blit(engine_token *et, blit_params *list, uint32 count); +void vesa_fill_rectangle(engine_token *et, uint32 color, fill_rect_params *list, uint32 count); +void vesa_invert_rectangle(engine_token *et, fill_rect_params *list, uint32 count); +void vesa_fill_span(engine_token *et, uint32 color, uint16 *list, uint32 count); + +// overlay +uint32 vesa_overlay_count(const display_mode *dm); +const uint32 *vesa_overlay_supported_spaces(const display_mode *dm); +uint32 vesa_overlay_supported_features(uint32 a_color_space); +const overlay_buffer *vesa_allocate_overlay_buffer(color_space cs, uint16 width, uint16 height); +status_t vesa_release_overlay_buffer(const overlay_buffer *ob); +status_t vesa_get_overlay_constraints(const display_mode *dm, const overlay_buffer *ob, overlay_constraints *oc); +overlay_token vesa_allocate_overlay(void); +status_t vesa_release_overlay(overlay_token ot); +status_t vesa_configure_overlay(overlay_token ot, const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov); + +#ifdef __cplusplus +} +#endif + +#endif /* _ACCELERANT_PROTOS_H */ diff --git a/src/add-ons/accelerants/vesa/dpms.cpp b/src/add-ons/accelerants/vesa/dpms.cpp new file mode 100644 index 0000000000..caff4d6a4f --- /dev/null +++ b/src/add-ons/accelerants/vesa/dpms.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "accelerant_protos.h" +#include "accelerant.h" + + +uint32 +vesa_dpms_capabilities(void) +{ + return B_DPMS_ON; +} + + +uint32 +vesa_dpms_mode(void) +{ + return B_DPMS_ON; +} + + +status_t +vesa_set_dpms_mode(uint32 dpms_flags) +{ + return B_ERROR; +} + diff --git a/src/add-ons/accelerants/vesa/engine.cpp b/src/add-ons/accelerants/vesa/engine.cpp new file mode 100644 index 0000000000..d1965f5743 --- /dev/null +++ b/src/add-ons/accelerants/vesa/engine.cpp @@ -0,0 +1,59 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "accelerant_protos.h" +#include "vesa_info.h" + + +static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL}; + + +uint32 +vesa_accelerant_engine_count(void) +{ + return 1; +} + + +status_t +vesa_acquire_engine(uint32 capabilities, uint32 max_wait, sync_token *syncToken, + engine_token **_engineToken) +{ + *_engineToken = &sEngineToken; + + return B_OK; +} + + +status_t +vesa_release_engine(engine_token *engineToken, sync_token *syncToken) +{ + if (syncToken != NULL) + syncToken->engine_id = engineToken->engine_id; + + return B_OK; +} + + +void +vesa_wait_engine_idle(void) +{ +} + + +status_t +vesa_get_sync_token(engine_token *engineToken, sync_token *syncToken) +{ + return B_OK; +} + + +status_t +vesa_sync_to_token(sync_token *syncToken) +{ + return B_OK; +} + diff --git a/src/add-ons/accelerants/vesa/hooks.cpp b/src/add-ons/accelerants/vesa/hooks.cpp new file mode 100644 index 0000000000..4fb42cd00c --- /dev/null +++ b/src/add-ons/accelerants/vesa/hooks.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "accelerant_protos.h" + + +// ToDo: these are some temporary dummy functions to see if this helps with our current app_server + +status_t +vesa_set_cursor_shape(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask) +{ + return B_OK; +} + + +void +vesa_move_cursor(uint16 x, uint16 y) +{ +} + + +void +vesa_show_cursor(bool is_visible) +{ +} + + +extern "C" void * +get_accelerant_hook(uint32 feature, void *data) +{ + switch (feature) { + /* general */ + case B_INIT_ACCELERANT: + return vesa_init_accelerant; + case B_UNINIT_ACCELERANT: + return vesa_uninit_accelerant; + case B_CLONE_ACCELERANT: + return vesa_clone_accelerant; + case B_ACCELERANT_CLONE_INFO_SIZE: + return vesa_accelerant_clone_info_size; + case B_GET_ACCELERANT_CLONE_INFO: + return vesa_get_accelerant_clone_info; + case B_GET_ACCELERANT_DEVICE_INFO: + return vesa_get_accelerant_device_info; + case B_ACCELERANT_RETRACE_SEMAPHORE: + return vesa_accelerant_retrace_semaphore; + + /* mode configuration */ + case B_ACCELERANT_MODE_COUNT: + return vesa_accelerant_mode_count; + case B_GET_MODE_LIST: + return vesa_get_mode_list; + case B_PROPOSE_DISPLAY_MODE: + return vesa_propose_display_mode; + case B_SET_DISPLAY_MODE: + return vesa_set_display_mode; + case B_GET_DISPLAY_MODE: + return vesa_get_display_mode; + case B_GET_FRAME_BUFFER_CONFIG: + return vesa_get_frame_buffer_config; + case B_GET_PIXEL_CLOCK_LIMITS: + return vesa_get_pixel_clock_limits; + case B_MOVE_DISPLAY: + return vesa_move_display; + case B_SET_INDEXED_COLORS: + return vesa_set_indexed_colors; + case B_GET_TIMING_CONSTRAINTS: + return vesa_get_timing_constraints; + + /* DPMS */ + case B_DPMS_CAPABILITIES: + return vesa_dpms_capabilities; + case B_DPMS_MODE: + return vesa_dpms_mode; + case B_SET_DPMS_MODE: + return vesa_set_dpms_mode; + + /* cursor managment */ + case B_SET_CURSOR_SHAPE: + return vesa_set_cursor_shape; + case B_MOVE_CURSOR: + return vesa_move_cursor; + case B_SHOW_CURSOR: + return vesa_show_cursor; + + /* engine/synchronization */ + case B_ACCELERANT_ENGINE_COUNT: + return vesa_accelerant_engine_count; + case B_ACQUIRE_ENGINE: + return vesa_acquire_engine; + case B_RELEASE_ENGINE: + return vesa_release_engine; + case B_WAIT_ENGINE_IDLE: + return vesa_wait_engine_idle; + case B_GET_SYNC_TOKEN: + return vesa_get_sync_token; + case B_SYNC_TO_TOKEN: + return vesa_sync_to_token; + } + + return NULL; +} + diff --git a/src/add-ons/accelerants/vesa/mode.cpp b/src/add-ons/accelerants/vesa/mode.cpp new file mode 100644 index 0000000000..57121b9192 --- /dev/null +++ b/src/add-ons/accelerants/vesa/mode.cpp @@ -0,0 +1,234 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "accelerant_protos.h" +#include "accelerant.h" +#include "utility.h" + + +#define TRACE_MODE +#ifdef TRACE_MODE +extern "C" void _sPrintf(const char *format, ...); +# define TRACE(x) _sPrintf x +#else +# define TRACE(x) ; +#endif + + +#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC) +#define MODE_FLAGS (B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS | B_DPMS /*| B_SUPPORTS_OVERLAYS*/) + +static const display_mode kBaseModeList[] = { +{ { 25175, 640, 656, 752, 800, 350, 387, 389, 449, B_POSITIVE_HSYNC}, B_CMAP8, 640, 350, 0, 0, MODE_FLAGS}, /* 640x350 - www.epanorama.net/documents/pc/vga_timing.html) */ +{ { 25175, 640, 656, 752, 800, 400, 412, 414, 449, B_POSITIVE_VSYNC}, B_CMAP8, 640, 400, 0, 0, MODE_FLAGS}, /* 640x400 - www.epanorama.net/documents/pc/vga_timing.html) */ +{ { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */ +{ { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */ +{ { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */ +{ { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */ +{ { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */ +{ { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */ +{ { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */ +{ { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */ +{ { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */ +{ { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(800X600X8.Z1) */ +{ { 56250, 800, 832, 896, 1048, 600, 601, 604, 631, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */ +{ { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */ +{ { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(1024X768X8.Z1) */ +{ { 78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */ +{ { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */ +{ { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */ +{ { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */ +{ { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */ +{ { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */ +{ { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */ +{ { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */ +{ { 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */ +{ { 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */ +{ { 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */ +{ { 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */ +{ { 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */ +{ { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */ +}; +static const uint32 kNumBaseModes = sizeof(kBaseModeList) / sizeof(display_mode); +static const uint32 kMaxNumModes = kNumBaseModes * 4; + + +/** Creates the initial mode list of the primary accelerant. + * It's called from vesa_init_accelerant(). + */ + +status_t +create_mode_list(void) +{ + // ToDo: basically, the boot loader should pass a list of all supported + // VESA modes to us. + color_space spaces[4] = {B_RGB32_LITTLE, B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; + size_t size = ROUND_TO_PAGE_SIZE(kMaxNumModes * sizeof(display_mode)); + display_mode *list; + + gInfo->mode_list_area = create_area("vesa modes", (void **)&list, B_ANY_ADDRESS, + size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + if (gInfo->mode_list_area < B_OK) + return gInfo->mode_list_area; + + // for now, just copy all of the modes with different color spaces + + const display_mode *source = kBaseModeList; + uint32 count = 0; + + for (uint32 i = 0; i < kNumBaseModes; i++) { + for (uint32 j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++) { + list[count] = *source; + list[count].space = spaces[j]; + + count++; + } + + source++; + } + + gInfo->mode_list = list; + gInfo->shared_info->mode_list_area = gInfo->mode_list_area; + gInfo->shared_info->mode_count = count; + + return B_OK; +} + + +// #pragma mark - + + +uint32 +vesa_accelerant_mode_count(void) +{ + TRACE(("vesa_accelerant_mode_count()\n")); + return gInfo->shared_info->mode_count; +} + + +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)); + return B_OK; +} + + +status_t +vesa_propose_display_mode(display_mode *target, const display_mode *low, + const display_mode *high) +{ + TRACE(("vesa_propose_display_mode()\n")); + + // just search for the specified mode in the list + + for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) { + display_mode *current = &gInfo->mode_list[i]; + + if (target->virtual_width != current->virtual_width + || target->virtual_height != current->virtual_height + || target->space != current->space) + continue; + + *target = *current; + return B_OK; + } + return B_BAD_VALUE; +} + + +status_t +vesa_set_display_mode(display_mode *_mode) +{ + TRACE(("vesa_set_display_mode()\n")); + + display_mode mode = *_mode; + if (vesa_propose_display_mode(&mode, &mode, &mode) != B_OK) + return B_BAD_VALUE; + + gInfo->shared_info->current_mode = mode; + + switch (mode.space) { + case B_RGB32_LITTLE: + gInfo->shared_info->bytes_per_row = mode.virtual_width * 4; + break; + case B_RGB16_LITTLE: + case B_RGB15_LITTLE: + gInfo->shared_info->bytes_per_row = mode.virtual_width * 2; + break; + case B_CMAP8: + gInfo->shared_info->bytes_per_row = mode.virtual_width; + break; + } + + return B_OK; +} + + +status_t +vesa_get_display_mode(display_mode *_currentMode) +{ + TRACE(("vesa_get_display_mode()\n")); + *_currentMode = gInfo->shared_info->current_mode; + return B_OK; +} + + +status_t +vesa_get_frame_buffer_config(frame_buffer_config *config) +{ + TRACE(("vesa_get_frame_buffer_config()\n")); + + config->frame_buffer = gInfo->shared_info->frame_buffer; + config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer; + config->bytes_per_row = gInfo->shared_info->bytes_per_row; + + return B_OK; +} + + +status_t +vesa_get_pixel_clock_limits(display_mode *mode, uint32 *low, uint32 *high) +{ + TRACE(("vesa_get_pixel_clock_limits()\n")); + + // ToDo: do some real stuff here (taken from radeon driver) + uint32 total_pix = (uint32)mode->timing.h_total * (uint32)mode->timing.v_total; + uint32 clock_limit = 2000000; + + /* lower limit of about 48Hz vertical refresh */ + *low = (total_pix * 48L) / 1000L; + if (*low > clock_limit) + return B_ERROR; + + *high = clock_limit; + return B_OK; +} + + +status_t +vesa_move_display(uint16 h_display_start, uint16 v_display_start) +{ + TRACE(("vesa_move_display()\n")); + return B_ERROR; +} + + +status_t +vesa_get_timing_constraints(display_timing_constraints *dtc) +{ + TRACE(("vesa_get_timing_constraints()\n")); + return B_ERROR; +} + + +void +vesa_set_indexed_colors(uint count, uint8 first, uint8 *color_data, uint32 flags) +{ + TRACE(("vesa_set_indexed_colors()\n")); +} + diff --git a/src/add-ons/kernel/drivers/graphics/Jamfile b/src/add-ons/kernel/drivers/graphics/Jamfile index 672f1690f5..9b355657d5 100644 --- a/src/add-ons/kernel/drivers/graphics/Jamfile +++ b/src/add-ons/kernel/drivers/graphics/Jamfile @@ -8,5 +8,6 @@ SubInclude OBOS_TOP src add-ons kernel drivers graphics nvidia ; SubInclude OBOS_TOP src add-ons kernel drivers graphics radeon ; SubInclude OBOS_TOP src add-ons kernel drivers graphics tdfx ; SubInclude OBOS_TOP src add-ons kernel drivers graphics skeleton ; +SubInclude OBOS_TOP src add-ons kernel drivers graphics vesa ; SubIncludeGPL OBOS_TOP src add-ons kernel drivers graphics atimach64 ; diff --git a/src/add-ons/kernel/drivers/graphics/vesa/Jamfile b/src/add-ons/kernel/drivers/graphics/vesa/Jamfile new file mode 100644 index 0000000000..fc17959c71 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vesa/Jamfile @@ -0,0 +1,18 @@ +SubDir OBOS_TOP src add-ons kernel drivers graphics vesa ; + +UsePrivateHeaders graphics ; +UsePrivateHeaders [ FDirName graphics vesa ] ; + +KernelAddon vesa : kernel drivers bin : + device.cpp + driver.cpp + vesa.cpp + ; + +# Link to kernel/drivers/dev/graphics +{ + local dir = [ FDirName $(OBOS_ADDON_DIR) kernel drivers dev graphics ] ; + local instDriver = vesa ; + MakeLocate $(instDriver) : $(dir) ; + RelSymLink $(instDriver) : vesa ; +} diff --git a/src/add-ons/kernel/drivers/graphics/vesa/device.cpp b/src/add-ons/kernel/drivers/graphics/vesa/device.cpp new file mode 100644 index 0000000000..f56175bab9 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vesa/device.cpp @@ -0,0 +1,174 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "driver.h" +#include "device.h" +#include "vesa_info.h" +#include "utility.h" + + +//#define TRACE_DEVICE +#ifdef TRACE_DEVICE +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +/* device hooks prototypes */ + +static status_t device_open(const char *, uint32, void **); +static status_t device_close(void *); +static status_t device_free(void *); +static status_t device_ioctl(void *, uint32, void *, size_t); +static status_t device_read(void *, off_t, void *, size_t *); +static status_t device_write(void *, off_t, const void *, size_t *); + + +device_hooks gDeviceHooks = { + device_open, + device_close, + device_free, + device_ioctl, + device_read, + device_write, + NULL, + NULL, + NULL, + NULL +}; + + +// #pragma mark - +// the device will be accessed through the following functions (a.k.a. device hooks) + + +static status_t +device_open(const char *name, uint32 flags, void **_cookie) +{ + int id; + + // find accessed device + { + char *thisName; + + // search for device name + for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) { + if (!strcmp(name, thisName)) + break; + } + if (!thisName) + return EINVAL; + } + + vesa_info *info = gDeviceInfo[id]; + *_cookie = info; + + acquire_lock(&gLock); + + status_t status = B_OK; + + if (info->open_count++ == 0) { + // this device has been opened for the first time, so + // we allocate needed resources and initialize the structure + + frame_buffer_boot_info *bufferInfo = (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO); + if (bufferInfo != NULL) { + info->frame_buffer = (uint8 *)bufferInfo->frame_buffer; + info->frame_buffer_area = bufferInfo->area; + } + + info->id = id; + + status = vesa_init(*info); + } + + release_lock(&gLock); + return status; +} + + +static status_t +device_close(void *cookie) +{ + return B_OK; +} + + +static status_t +device_free(void *cookie) +{ + struct vesa_info *info = (vesa_info *)cookie; + + acquire_lock(&gLock); + + if (info->open_count-- == 1) { + // release info structure + vesa_uninit(*info); + } + + release_lock(&gLock); + return B_OK; +} + + +static status_t +device_ioctl(void *cookie, uint32 msg, void *buffer, size_t bufferLength) +{ + struct vesa_info *info = (vesa_info *)cookie; + + 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); + return B_OK; + + // needed to share data between kernel and accelerant + case VESA_GET_PRIVATE_DATA: + return user_memcpy(buffer, &info->shared_area, sizeof(area_id)); + + // needed for cloning + case VESA_GET_DEVICE_NAME: + if (user_strlcpy((char *)buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH) < B_OK) + return B_BAD_ADDRESS; + return B_OK; + + default: + TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", msg, bufferLength)); + } + + return B_DEV_INVALID_IOCTL; +} + + +static status_t +device_read(void */*cookie*/, off_t /*pos*/, void */*buffer*/, size_t *_length) +{ + *_length = 0; + return B_NOT_ALLOWED; +} + + +static status_t +device_write(void */*cookie*/, off_t /*pos*/, const void */*buffer*/, size_t *_length) +{ + *_length = 0; + return B_NOT_ALLOWED; +} + diff --git a/src/add-ons/kernel/drivers/graphics/vesa/device.h b/src/add-ons/kernel/drivers/graphics/vesa/device.h new file mode 100644 index 0000000000..9ce0264531 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vesa/device.h @@ -0,0 +1,13 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef DEVICE_H +#define DEVICE_H + +#include + +// The device hooks for the published device +extern device_hooks gDeviceHooks; + +#endif /* DEVICE_H */ diff --git a/src/add-ons/kernel/drivers/graphics/vesa/driver.cpp b/src/add-ons/kernel/drivers/graphics/vesa/driver.cpp new file mode 100644 index 0000000000..c6ffdc32ad --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vesa/driver.cpp @@ -0,0 +1,127 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "driver.h" +#include "device.h" + +#define TRACE_DRIVER +#ifdef TRACE_DRIVER +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + +#define MAX_CARDS 1 + +int32 api_version = B_CUR_DRIVER_API_VERSION; + +char *gDeviceNames[MAX_CARDS + 1]; +vesa_info *gDeviceInfo[MAX_CARDS]; +lock gLock; + + +extern "C" { + status_t init_hardware(void); + status_t init_driver(void); + void uninit_driver(void); + const char **publish_devices(void); + device_hooks *find_device(const char *name); +} + +#if 0 +static status_t +get_next_graphics_card(int32 *_cookie, pci_info &info) +{ + int32 index = *_cookie; + + // find devices + for (; gPCI->get_nth_pci_info(index, &info) == B_OK; index++) { + if (info.class_base == PCI_display) { + *_cookie = index + 1; + return B_OK; + } + } + + return B_ENTRY_NOT_FOUND; +} +#endif + +const char ** +publish_devices(void) +{ + TRACE((DEVICE_NAME ": publish_devices()\n")); + return (const char **)gDeviceNames; +} + + +status_t +init_hardware(void) +{ + TRACE((DEVICE_NAME ": init_hardware()\n")); + + return get_boot_item(FRAME_BUFFER_BOOT_INFO) != NULL ? B_OK : B_ERROR; +} + + +status_t +init_driver(void) +{ + TRACE((DEVICE_NAME ": init_driver()\n")); + + if ((gDeviceInfo[0] = (vesa_info *)malloc(sizeof(vesa_info))) != NULL) + memset(gDeviceInfo[0], 0, sizeof(vesa_info)); + else + return B_NO_MEMORY; + + gDeviceNames[0] = strdup("graphics/vesa"); + gDeviceNames[1] = NULL; + + return init_lock(&gLock, "vesa lock"); +} + + +void +uninit_driver(void) +{ + TRACE((DEVICE_NAME ": uninit_driver()\n")); + + uninit_lock(&gLock); + + // free device related structures + char *name; + for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) { + free(gDeviceInfo[index]); + free(name); + } +} + + +device_hooks * +find_device(const char *name) +{ + int index; + + TRACE((DEVICE_NAME ": find_device()\n")); + + for (index = 0; gDeviceNames[index] != NULL; index++) + if (!strcmp(name, gDeviceNames[index])) + return &gDeviceHooks; + + return NULL; +} + diff --git a/src/add-ons/kernel/drivers/graphics/vesa/driver.h b/src/add-ons/kernel/drivers/graphics/vesa/driver.h new file mode 100644 index 0000000000..586117ed0f --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vesa/driver.h @@ -0,0 +1,20 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef DRIVER_H +#define DRIVER_H + + +#include +#include + +#include "vesa_info.h" +#include "lock.h" + + +extern char *gDeviceNames[]; +extern vesa_info *gDeviceInfo[]; +extern lock gLock; + +#endif /* DRIVER_H */ diff --git a/src/add-ons/kernel/drivers/graphics/vesa/lock.h b/src/add-ons/kernel/drivers/graphics/vesa/lock.h new file mode 100644 index 0000000000..e816870c6f --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vesa/lock.h @@ -0,0 +1,54 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef LOCK_H +#define LOCK_H + + +#include + + +typedef struct lock { + sem_id sem; + vint32 count; +} lock; + + +static inline status_t +init_lock(struct lock *lock, const char *name) +{ + lock->sem = create_sem(0, name); + lock->count = 0; + + return lock->sem < B_OK ? lock->sem : B_OK; +} + + +static inline void +uninit_lock(struct lock *lock) +{ + delete_sem(lock->sem); +} + + +static inline status_t +acquire_lock(struct lock *lock) +{ + if (atomic_add(&lock->count, 1) > 0) + return acquire_sem(lock->sem); + + return B_OK; +} + + +static inline status_t +release_lock(struct lock *lock) +{ + if (atomic_add(&lock->count, -1) > 1) + return release_sem(lock->sem); + + return B_OK; +} + +#endif /* LOCK_H */ diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp new file mode 100644 index 0000000000..f94b2665bb --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "vesa_info.h" +#include "driver.h" +#include "utility.h" + +#include "util/kernel_cpp.h" + +#include + + +class PhysicalMemoryMapper { + public: + PhysicalMemoryMapper(); + ~PhysicalMemoryMapper(); + + area_id Map(const char *name, void *physicalAddress, size_t numBytes, + uint32 spec, uint32 protection, void **virtualAddress); + status_t InitCheck() { return fArea < B_OK ? (status_t)fArea : B_OK; } + void Keep(); + + private: + area_id fArea; +}; + + +PhysicalMemoryMapper::PhysicalMemoryMapper() + : + fArea(-1) +{ +} + + +PhysicalMemoryMapper::~PhysicalMemoryMapper() +{ + if (fArea >= B_OK) + delete_area(fArea); +} + + +area_id +PhysicalMemoryMapper::Map(const char *name, void *physicalAddress, size_t numBytes, + uint32 spec, uint32 protection, void **virtualAddress) +{ + fArea = map_physical_memory(name, physicalAddress, numBytes, spec, protection, virtualAddress); + return fArea; +} + + +void +PhysicalMemoryMapper::Keep() +{ + fArea = -1; +} + + +// #pragma mark - + + +status_t +vesa_init(vesa_info &info) +{ + 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); + if (info.shared_area < B_OK) + return info.shared_area; + + memset((void *)info.shared_info, 0, sizeof(vesa_shared_info)); + + info.shared_info->frame_buffer_area = info.frame_buffer_area; + info.shared_info->frame_buffer = info.frame_buffer; + + physical_entry mapping; + get_memory_map((void *)info.frame_buffer, B_PAGE_SIZE, &mapping, 1); + info.shared_info->physical_frame_buffer = (uint8 *)mapping.address; + + dprintf(DEVICE_NAME "vesa_init() completed successfully!\n"); + return B_OK; +} + + +void +vesa_uninit(vesa_info &info) +{ + dprintf(DEVICE_NAME": vesa_uninit()\n"); + + delete_area(info.frame_buffer_area); + delete_area(info.shared_area); +} +