Added very basic VESA driver. Will be improved in the future (right now

it doesn't really do anything, it just passes the initial frame buffer
on to the app_server).
While it seems to work on real hardware (if you set the video mode to
640x480x32, app_server restriction), under Bochs, the app_server crashes.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12273 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-04-08 15:11:32 +00:00
parent 07ce63458b
commit 93ee21046d
19 changed files with 1373 additions and 0 deletions

View File

@ -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 */

View File

@ -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 <Drivers.h>
#include <Accelerant.h>
#include <PCI.h>
#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 */

View File

@ -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 ;

View File

@ -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
;

View File

@ -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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
//#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;
}

View File

@ -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 */

View File

@ -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 <Accelerant.h>
#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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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"));
}

View File

@ -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 ;

View File

@ -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 = <kernel!drivers!dev!graphics>vesa ;
MakeLocate $(instDriver) : $(dir) ;
RelSymLink $(instDriver) : vesa ;
}

View File

@ -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 <OS.h>
#include <KernelExport.h>
#include <Drivers.h>
#include <PCI.h>
#include <SupportDefs.h>
#include <graphic_driver.h>
#include <image.h>
#include <boot_item.h>
#include <frame_buffer_console.h>
#include <stdlib.h>
#include <string.h>
#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;
}

View File

@ -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 <Drivers.h>
// The device hooks for the published device
extern device_hooks gDeviceHooks;
#endif /* DEVICE_H */

View File

@ -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 <OS.h>
#include <KernelExport.h>
#include <SupportDefs.h>
#include <PCI.h>
#include <frame_buffer_console.h>
#include <boot_item.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#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;
}

View File

@ -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 <KernelExport.h>
#include <PCI.h>
#include "vesa_info.h"
#include "lock.h"
extern char *gDeviceNames[];
extern vesa_info *gDeviceInfo[];
extern lock gLock;
#endif /* DRIVER_H */

View File

@ -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 <OS.h>
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 */

View File

@ -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 <string.h>
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);
}