Added graphic driver and accelerant for Tseng Labs ET6x00 chips, courtesy Evgeniy Vladimirovich Bobkov.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8714 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2004-08-29 16:31:33 +00:00
parent 76dd4cf399
commit 8731383444
24 changed files with 2512 additions and 0 deletions

View File

@ -0,0 +1,123 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#ifndef _DRIVERINTERFACE_H_
#define _DRIVERINTERFACE_H_
#include <Accelerant.h>
#include <Drivers.h>
#include <PCI.h>
#include <OS.h>
#if defined(__cplusplus)
extern "C" {
#endif
/*
* This is the info that needs to be shared between the kernel driver and
* the accelerant for the et6000 driver.
*/
/*****************************************************************************/
typedef struct {
sem_id sem;
int32 ben;
} benaphore;
#define INIT_BEN(x) x.sem = create_sem(0, "ET6000 "#x" benaphore"); x.ben = 0;
#define AQUIRE_BEN(x) if((atomic_add(&(x.ben), 1)) >= 1) acquire_sem(x.sem);
#define RELEASE_BEN(x) if((atomic_add(&(x.ben), -1)) > 1) release_sem(x.sem);
#define DELETE_BEN(x) delete_sem(x.sem);
/*****************************************************************************/
#define ET6000_PRIVATE_DATA_MAGIC 0x100CC001
/*****************************************************************************/
#define ET6000_HANDLER_INSTALLED 0x80000000
/*****************************************************************************/
/*
* How many bytes of memory the accelerator (ACL) takes from the off-screen
* part of the adapter onboard memory to perform some of its operations.
*/
#define ET6000_ACL_NEEDS_MEMORY 4
/*****************************************************************************/
enum {
ET6000_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
ET6000_GET_PCI,
ET6000_SET_PCI,
ET6000_DEVICE_NAME,
ET6000_PROPOSE_DISPLAY_MODE,
ET6000_SET_DISPLAY_MODE
};
/*****************************************************************************/
typedef struct {
uint16 vendor_id; /* PCI vendor ID, from pci_info */
uint16 device_id; /* PCI device ID, from pci_info */
uint8 revision; /* PCI device revsion, from pci_info */
area_id memoryArea; /* Onboard memory's area_id. The addresses
* are shared with all teams. */
void *framebuffer; /* Start of the mapped framebuffer */
void *physFramebuffer; /* Physical address of start of framebuffer */
void *memory; /* Start of the mapped adapter onboard memory */
void *physMemory; /* Physical address of start of onboard memory */
uint32 memSize; /* Size of available onboard memory, bytes. */
uint16 pciConfigSpace; /* PCI header base I/O address */
void *mmRegs; /* memory mapped registers */
void *emRegs; /* external mapped registers */
area_id modesArea; /* Contains the list of display modes the driver supports */
uint32 modesNum; /* Number of display modes in the list */
int32 flags;
display_mode dm; /* current display mode configuration */
uint8 bytesPerPixel; /* bytes(!) per pixel at current display mode */
frame_buffer_config fbc; /* bytes_per_row and start of frame buffer */
struct {
uint64 count; /* last fifo slot used */
uint64 lastIdle; /* last fifo slot we *know* the engine was idle after */
benaphore lock; /* for serializing access to the acceleration engine */
} engine;
uint32 pixelClockMax16; /* The maximum speed the pixel clock should run */
uint32 pixelClockMax24; /* at for a given pixel width. Usually a function */
/* of memory and DAC bandwidths. */
} ET6000SharedInfo;
/*****************************************************************************/
/* Read or write a value in PCI configuration space */
typedef struct {
uint32 magic; /* magic number to make sure the caller groks us */
uint32 offset; /* Offset to read/write */
uint32 size; /* Number of bytes to transfer */
uint32 value; /* The value read or written */
} ET6000GetSetPCI;
/*****************************************************************************/
/* Retrieve the area_id of the kernel/accelerant shared info */
typedef struct {
uint32 magic; /* magic number to make sure the caller groks us */
area_id sharedInfoArea; /* area_id containing the shared information */
} ET6000GetPrivateData;
/*****************************************************************************/
/*
* Retrieve the device name. Usefull for when we have a file handle, but
* want to know the device name (like when we are cloning the accelerant).
*/
typedef struct {
uint32 magic; /* magic number to make sure the caller groks us */
char *name; /* The name of the device, less the /dev root */
} ET6000DeviceName;
/*****************************************************************************/
typedef struct {
uint32 magic; /* magic number to make sure the caller groks us */
display_mode mode; /* Proposed mode or mode to set */
uint16 pciConfigSpace; /* For setting the mode */
uint32 memSize; /* For proposing the mode */
} ET6000DisplayMode;
/*****************************************************************************/
#if defined(__cplusplus)
}
#endif
#endif /* _DRIVERINTERFACE_H_ */

View File

@ -1,6 +1,7 @@
SubDir OBOS_TOP src add-ons accelerants ;
SubInclude OBOS_TOP src add-ons accelerants common ;
SubInclude OBOS_TOP src add-ons accelerants et6x00 ;
SubInclude OBOS_TOP src add-ons accelerants matrox ;
SubInclude OBOS_TOP src add-ons accelerants neomagic ;
SubInclude OBOS_TOP src add-ons accelerants nvidia ;

View File

@ -0,0 +1,256 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "GlobalData.h"
#include "generic.h"
/*****************************************************************************/
/*
* Set bits in a byte pointed by addr; mask must contain 0s at the bits
* positions to be set and must contain 1s at all other bits; val must
* contain the values of bits to be set.
*/
__inline void set8(volatile char *addr, char mask, char val)
{
if (mask == 0)
*addr = val;
else
*addr = (*addr & mask) | (val & ~mask);
}
/*****************************************************************************/
__inline char get8(volatile char *addr)
{
return *addr;
}
/*****************************************************************************/
__inline void et6000aclTerminate(void) {
set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */
et6000aclWaitIdle();
set8(mmRegs+0x30, 0, 0x00);
set8(mmRegs+0x30, 0, 0x01);
et6000aclWaitIdle();
set8(mmRegs+0x30, 0, 0x00);
set8(mmRegs+0x30, 0, 0x10);
et6000aclWaitIdle();
set8(mmRegs+0x30, 0, 0x00);
}
/*****************************************************************************/
/*
* bpp must be bytes per pixel, not bits!
*/
void et6000aclInit(uint8 bpp) {
et6000aclTerminate();
set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */
set8(mmRegs+0x32, 0x99, 0x00); /* maximize the performance */
set8(mmRegs+0x8e, 0xcf, (bpp - 1) << 4); /* set pixel color depth */
set8(mmRegs+0x91, 0x80, 0x00); /* maximize the performance */
set8(mmRegs+0x9d, 0x00, 0x00); /* maximize the performance */
}
/*****************************************************************************/
/*
* Wait until ACL becomes idle.
*/
void et6000aclWaitIdle(void) {
while ((get8(mmRegs+0x36) & 0x02) == 0x02);
}
/*****************************************************************************/
/*
* Wait until ACL queue becomes not full.
*/
__inline void et6000aclWaitQueueNotFull(void) {
while ((get8(mmRegs+0x36) & 0x01) == 0x01);
}
/*****************************************************************************/
/*
* Move the specified list of rectangular regions from one location in
* the frame buffer to another in the order they are specified in the
* blit_params *list. The list is uint32 count elements in length.
*/
void SCREEN_TO_SCREEN_BLIT(engine_token *et,
blit_params *list,
uint32 count)
{
uint16 screenWidth = si->dm.virtual_width;
uint8 bpp = si->bytesPerPixel;
uint8 bltDir;
uint16 src_left, src_top, dest_left, dest_top, width, height;
uint32 srcAddr, destAddr;
et6000aclWaitQueueNotFull();
set8(mmRegs+0x92, 0x80, 0x77); /* no source wrap */
set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */
set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */
/* Set the source Y offset */
*((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1;
/* Set the destination Y offset */
*((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1;
while(count--) {
src_left = list->src_left;
src_top = list->src_top;
dest_left = list->dest_left;
dest_top = list->dest_top;
width = list->width;
height = list->height;
et6000aclWaitQueueNotFull();
/* Set the direction and opcode(BitBLT) register */
bltDir = 0x00;
if (src_left < dest_left) bltDir |= 0x01;
if (src_top < dest_top) bltDir |= 0x02;
set8(mmRegs+0x8f, 0x3c, bltDir);
/* Set the X count register */
*((vuint16 *)(mmRegs+0x98)) = (width + 1) * bpp - 1;
/* Set the Y count register */
*((vuint16 *)(mmRegs+0x9a)) = height;
switch (bltDir & 0x03) {
case 0x00:
srcAddr = (src_top * screenWidth + src_left) * bpp;
destAddr = (dest_top * screenWidth + dest_left) * bpp;
break;
case 0x01:
srcAddr = (src_top * screenWidth + src_left + width) * bpp + bpp-1;
destAddr = (dest_top * screenWidth + dest_left + width) * bpp + bpp-1;
break;
case 0x02:
srcAddr = ((src_top + height)*screenWidth + src_left) * bpp;
destAddr = ((dest_top + height)*screenWidth + dest_left) * bpp;
break;
case 0x03:
srcAddr = ((src_top + height)*screenWidth + src_left + width) * bpp + bpp-1;
destAddr = ((dest_top + height)*screenWidth + dest_left + width) * bpp + bpp-1;
break;
}
/* Set the source address */
*((vuint32 *)(mmRegs+0x84)) = srcAddr;
/*
* Set the destination address -
* this action starts the BitBLT operation.
*/
*((vuint32 *)(mmRegs+0xa0)) = destAddr;
list++;
}
si->engine.count++;
}
/*****************************************************************************/
/*
* Fill the specified list of rectangular regions with the specified color.
* The list is uint32 count elements in length. The rectangular regions are
* inclusive. The uint32 color is specified in the same configuration and
* byte order as the current display_mode. All coordinates in the list of
* rectangles is guaranteed to have been clipped to the virtual limits of
* the display_mode.
*/
void FILL_RECTANGLE(engine_token *et,
uint32 color,
fill_rect_params *list,
uint32 count)
{
uint16 screenWidth = si->dm.virtual_width;
uint8 bpp = si->bytesPerPixel;
uint16 left, top, right, bottom;
uint32 srcAddr;
uint8 i;
/*
* Normally WaitQueueNotFull should be required & enough, but in reality
* this is somewhy sometimes not enough for pixel depth of 3 bytes.
*/
if (bpp == 2)
et6000aclWaitQueueNotFull();
else
et6000aclWaitIdle();
/*
* We'll put the color at 4 bytes just after the framebuffer.
* The srcAddr must be 4 bytes aligned and is always for standard
* resolutions.
*/
srcAddr = (uint32)si->framebuffer - (uint32)si->memory +
si->dm.virtual_width * si->dm.virtual_height * bpp;
switch(bpp) {
case 2:
set8(mmRegs+0x92, 0x80, 0x02); /* 4x1 source wrap */
for (i = 0; i < 2; i++) /* copy the color to source address */
((vuint16 *)((uint32)si->memory + srcAddr))[i] = (uint16)color;
break;
case 3:
set8(mmRegs+0x92, 0x80, 0x0a); /* 3x1 source wrap */
for (i = 0; i < 3; i++) /* copy the color to source address */
((vuint8 *)((uint32)si->memory + srcAddr))[i] = ((uint8 *)&color)[i];
break;
}
set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */
set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */
/* Set the source Y offset */
*((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1;
/* Set the destination Y offset */
*((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1;
/* Set the direction and opcode(trapezoid) register (primary edge) */
set8(mmRegs+0x8f, 0x18, 0x40);
/* Set the secondary edge register */
set8(mmRegs+0x93, 0x1a, 0x00);
/* Set the primary delta minor register */
*((vuint16 *)(mmRegs+0xac)) = 0;
/* Set the secondary delta minor register */
*((vuint16 *)(mmRegs+0xb4)) = 0;
while(count--) {
left = list->left;
top = list->top;
right = list->right;
bottom = list->bottom;
et6000aclWaitQueueNotFull();
/* Set the X count register */
*((vuint16 *)(mmRegs+0x98)) = (right-left+1)*bpp - 1;
/* Set the Y count register */
*((vuint16 *)(mmRegs+0x9a)) = bottom-top;
/* Set the primary delta major register */
*((vuint16 *)(mmRegs+0xae)) = bottom-top;
/* Set the secondary delta major register */
*((vuint16 *)(mmRegs+0xb6)) = bottom-top;
/* Set the source address */
*((vuint32 *)(mmRegs+0x84)) = srcAddr;
/*
* Set the destination address -
* this action starts the trapezoid operation.
*/
*((vuint32 *)(mmRegs+0xa0)) = (top * screenWidth + left) * bpp;
list++;
}
si->engine.count++;
}
/*****************************************************************************/

View File

@ -0,0 +1,61 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "GlobalData.h"
#include "generic.h"
/*****************************************************************************/
static engine_token et6000EngineToken = {1, B_2D_ACCELERATION, NULL};
/*****************************************************************************/
uint32 ACCELERANT_ENGINE_COUNT(void) {
return 1;
}
/*****************************************************************************/
status_t ACQUIRE_ENGINE(uint32 capabilities,
uint32 max_wait,
sync_token *st,
engine_token **et)
{
/* acquire the shared benaphore */
AQUIRE_BEN(si->engine.lock)
/* sync if required */
if (st) SYNC_TO_TOKEN(st);
/* return an engine token */
*et = &et6000EngineToken;
return B_OK;
}
/*****************************************************************************/
status_t RELEASE_ENGINE(engine_token *et, sync_token *st) {
/* update the sync token, if any */
if (st) {
st->engine_id = et->engine_id;
st->counter = si->engine.count;
}
/* release the shared benaphore */
RELEASE_BEN(si->engine.lock)
return B_OK;
}
/*****************************************************************************/
void WAIT_ENGINE_IDLE(void) {
et6000aclWaitIdle();
/* note our current possition */
si->engine.lastIdle = si->engine.count;
}
/*****************************************************************************/
status_t GET_SYNC_TOKEN(engine_token *et, sync_token *st) {
st->engine_id = et->engine_id;
st->counter = si->engine.count;
return B_OK;
}
/*****************************************************************************/
status_t SYNC_TO_TOKEN(sync_token *st) {
WAIT_ENGINE_IDLE();
si->engine.lastIdle = st->counter;
return B_OK;
}
/*****************************************************************************/

View File

@ -0,0 +1,69 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "generic.h"
/*****************************************************************************/
/*
* The standard entry point. Given a uint32 feature identifier, this routine
* returns a pointer to the function that implements the feature. Some features
* require more information than just the identifier to select the proper
* function. The extra information (which is specific to the feature) is
* pointed at by the void *data parameter. By default, no extra information
* is available. Any extra information available to choose the function will
* be noted on a case by case below.
*/
void *get_accelerant_hook(uint32 feature, void *data) {
/* These definition is out of pure lazyness.*/
#define HOOK(x) case B_##x: return (void *)x
switch (feature) {
/*
* One of either B_INIT_ACCELERANT or B_CLONE_ACCELERANT will be
* requested and subsequently called before any other hook is
* requested. All other feature hook selections can be predicated
* on variables assigned during the accelerant initialization process.
*/
/* initialization */
HOOK(INIT_ACCELERANT);
HOOK(CLONE_ACCELERANT);
HOOK(ACCELERANT_CLONE_INFO_SIZE);
HOOK(GET_ACCELERANT_CLONE_INFO);
HOOK(UNINIT_ACCELERANT);
HOOK(GET_ACCELERANT_DEVICE_INFO);
/// HOOK(ACCELERANT_RETRACE_SEMAPHORE); /* Not implemented. Would be useful to have it implemented. */
/* mode configuration */
HOOK(ACCELERANT_MODE_COUNT);
HOOK(GET_MODE_LIST);
/// HOOK(PROPOSE_DISPLAY_MODE);
HOOK(SET_DISPLAY_MODE);
HOOK(GET_DISPLAY_MODE);
HOOK(GET_FRAME_BUFFER_CONFIG);
HOOK(GET_PIXEL_CLOCK_LIMITS);
/* synchronization */
HOOK(ACCELERANT_ENGINE_COUNT);
HOOK(ACQUIRE_ENGINE);
HOOK(RELEASE_ENGINE);
HOOK(WAIT_ENGINE_IDLE);
HOOK(GET_SYNC_TOKEN);
HOOK(SYNC_TO_TOKEN);
/* 2D acceleration */
HOOK(SCREEN_TO_SCREEN_BLIT);
HOOK(FILL_RECTANGLE);
}
/* Return a null pointer for any feature we don't understand. */
return 0;
#undef HOOK
}
/*****************************************************************************/

View File

@ -0,0 +1,57 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "GlobalData.h"
#include "generic.h"
/*****************************************************************************/
/*
* Return the current display mode. The only time you
* might return an error is if a mode hasn't been set.
*/
status_t GET_DISPLAY_MODE(display_mode *current_mode) {
/* easy for us, we return the last mode we set */
*current_mode = si->dm;
return B_OK;
}
/*****************************************************************************/
/*
* Return the frame buffer configuration information.
*/
status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *afb) {
/* easy again, as the last mode set stored the info in a convienient form */
*afb = si->fbc;
return B_OK;
}
/*****************************************************************************/
/*
* Return the maximum and minium pixel clock limits for the specified mode.
* Note that we're not making any guarantees about the ability of the
* attached display to handle pixel clocks within the limits we return.
* A future monitor capablilities database will post-process this
* information.
*/
status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high) {
uint32 clockLimit;
uint32 totalPix = (uint32)dm->timing.h_total * (uint32)dm->timing.v_total;
/* max pixel clock is pixel depth dependant */
switch (dm->space & ~0x3000) {
case B_RGB24: clockLimit = si->pixelClockMax24; break;
case B_RGB15:
case B_RGB16: clockLimit = si->pixelClockMax16; break;
default:
clockLimit = 0;
}
/* lower limit of about 48Hz vertical refresh */
*low = (totalPix * 48L) / 1000L;
if (*low > clockLimit) return B_ERROR;
*high = clockLimit;
return B_OK;
}
/*****************************************************************************/

View File

@ -0,0 +1,17 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "GlobalData.h"
/*****************************************************************************/
int fd;
ET6000SharedInfo *si;
area_id sharedInfoArea;
display_mode *et6000ModesList;
area_id et6000ModesListArea;
int accelerantIsClone;
volatile unsigned char *mmRegs; /* memory mapped registers */
/*****************************************************************************/

View File

@ -0,0 +1,23 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#ifndef _ET6000GLOBALDATA_H_
#define _ET6000GLOBALDATA_H_
#include "DriverInterface.h"
/*****************************************************************************/
extern int fd;
extern ET6000SharedInfo *si;
extern area_id sharedInfoArea;
extern display_mode *et6000ModesList;
extern area_id et6000ModesListArea;
extern int accelerantIsClone;
extern volatile unsigned char *mmRegs; /* memory mapped registers */
/*****************************************************************************/
#endif /* _ET6000GLOBALDATA_H_ */

View File

@ -0,0 +1,227 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "GlobalData.h"
#include "generic.h"
#include "string.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include <sys/ioctl.h>
/*****************************************************************************/
/*
* Initialization code shared between primary and cloned accelerants.
*/
static status_t initCommon(int the_fd) {
status_t result;
ET6000GetPrivateData gpd;
/* memorize the file descriptor */
fd = the_fd;
/* set the magic number so the driver knows we're for real */
gpd.magic = ET6000_PRIVATE_DATA_MAGIC;
/* contact driver and get a pointer to the registers and shared data */
result = ioctl(fd, ET6000_GET_PRIVATE_DATA, &gpd, sizeof(gpd));
if (result != B_OK) goto error0;
/* clone the shared area for our use */
sharedInfoArea = clone_area("ET6000 shared info", (void **)&si,
B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gpd.sharedInfoArea);
if (sharedInfoArea < 0) {
result = sharedInfoArea;
goto error0;
}
mmRegs = si->mmRegs;
error0:
return result;
}
/*****************************************************************************/
/*
* Clean up code shared between primary and cloned accelrants.
*/
static void uninitCommon(void) {
/* release our copy of the shared info from the kernel driver */
delete_area(sharedInfoArea);
si = 0;
}
/*****************************************************************************/
/*
* Initialize the accelerant. the_fd is the file handle of the device
* (in /dev/graphics) that has been opened by the app_server (or some test
* harness). We need to determine if the kernel driver and the accelerant
* are compatible. If they are, get the accelerant ready to handle other
* hook functions and report success or failure.
*/
status_t INIT_ACCELERANT(int the_fd) {
status_t result;
/* note that we're the primary accelerant (accelerantIsClone is global) */
accelerantIsClone = 0;
/* do the initialization common to both the primary and the clones */
result = initCommon(the_fd);
/* bail out if the common initialization failed */
if (result != B_OK) goto error0;
/* Call the device specific initialization code here, bail out if it failed */
if (result != B_OK) goto error1;
/*
* Now is a good time to figure out what video modes the card supports.
* We'll place the list of modes in another shared area so all
* of the copies of the driver can see them. The primary copy of the
* accelerant (ie the one initialized with this routine) will own the
* "one true copy" of the list. Everybody else get's a read-only clone.
*/
result = createModesList();
if (result != B_OK) goto error2;
/*
* We store this info in a frame_buffer_config structure to
* make it convienient to return to the app_server later.
*/
si->fbc.frame_buffer = si->framebuffer;
si->fbc.frame_buffer_dma = si->physFramebuffer;
/* init the shared semaphore */
INIT_BEN(si->engine.lock);
/* initialize the engine synchronization variables */
/* count of issued parameters or commands */
si->engine.lastIdle = si->engine.count = 0;
/* bail out if something failed */
if (result != B_OK) goto error3;
/* a winner! */
result = B_OK;
goto error0;
error3:
/* free up the benaphore */
DELETE_BEN(si->engine.lock);
error2:
/*
* Clean up any resources allocated in your device
* specific initialization code.
*/
error1:
/*
* Initialization failed after initCommon() succeeded, so we need to
* clean up before quiting.
*/
uninitCommon();
error0:
return result;
}
/*****************************************************************************/
/*
* Return the number of bytes required to hold the information required
* to clone the device.
*/
ssize_t ACCELERANT_CLONE_INFO_SIZE(void) {
/*
* Since we're passing the name of the device as the only required
* info, return the size of the name buffer
*/
return B_OS_NAME_LENGTH;
}
/*****************************************************************************/
/*
* Return the info required to clone the device. void *data points to
* a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length.
*/
void GET_ACCELERANT_CLONE_INFO(void *data) {
ET6000DeviceName dn;
status_t result;
/* call the kernel driver to get the device name */
dn.magic = ET6000_PRIVATE_DATA_MAGIC;
/* store the returned info directly into the passed buffer */
dn.name = (char *)data;
result = ioctl(fd, ET6000_DEVICE_NAME, &dn, sizeof(dn));
}
/*****************************************************************************/
/*
* Initialize a copy of the accelerant as a clone. void *data points
* to a copy of the data returned by GET_ACCELERANT_CLONE_INFO().
*/
status_t CLONE_ACCELERANT(void *data) {
status_t result;
char path[MAXPATHLEN];
/* the data is the device name */
strcpy(path, "/dev");
strcat(path, (const char *)data);
/* open the device, the permissions aren't important */
fd = open(path, B_READ_WRITE);
if (fd < 0) {
result = fd;
goto error0;
}
/* note that we're a clone accelerant */
accelerantIsClone = 1;
/* call the shared initialization code */
result = initCommon(fd);
/* bail out if the common initialization failed */
if (result != B_OK) goto error1;
/* get shared area for display modes */
result = et6000ModesListArea = clone_area("ET6000 cloned display_modes",
(void **)&et6000ModesList, B_ANY_ADDRESS, B_READ_AREA, si->modesArea);
if (result < B_OK) goto error2;
/* all done */
result = B_OK;
goto error0;
error2:
/* free up the areas we cloned */
uninitCommon();
error1:
/* close the device we opened */
close(fd);
error0:
return result;
}
/*****************************************************************************/
void UNINIT_ACCELERANT(void) {
/* free our mode list area */
delete_area(et6000ModesListArea);
et6000ModesList = 0;
/* release our cloned data */
uninitCommon();
/* close the file handle ONLY if we're the clone */
if (accelerantIsClone) close(fd);
}
/*****************************************************************************/
status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi)
{
adi->version = B_ACCELERANT_VERSION;
strcpy(adi->name, "Tseng Labs ET6x00");
strcpy(adi->chipset, "Tseng Labs ET6x00");
strcpy(adi->serial_no, "");
adi->memory = si->memSize;
adi->dac_speed = si->pixelClockMax16;
return B_OK;
}
/*****************************************************************************/

View File

@ -0,0 +1,18 @@
SubDir OBOS_TOP src add-ons accelerants et6x00 ;
UsePrivateHeaders [ FDirName graphics et6x00 ] ;
Addon et6x00.accelerant : accelerants :
Acceleration.c
EngineManagment.c
GetAccelerantHook.c
GetModeInfo.c
GlobalData.c
InitAccelerant.c
ProposeDisplayMode.c
SetDisplayMode.c
: false
:
;
Depends et6x00.accelerant : et6x00.driver ;

View File

@ -0,0 +1,141 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "GlobalData.h"
#include "generic.h"
#include <string.h>
#include <sys/ioctl.h>
/*****************************************************************************/
#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
#define MODE_FLAGS (B_SCROLL | B_8_BIT_DAC | B_PARALLEL_ACCESS)
#define MODE_COUNT (sizeof (modesList) / sizeof (display_mode))
/*****************************************************************************/
static const display_mode modesList[] = {
{ { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */
{ { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */
{ { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */
{ { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */
{ { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */
{ { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */
{ { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */
{ { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */
{ { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */
{ { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_RGB24, 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_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */
{ { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_RGB24, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */
{ { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_RGB24, 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_RGB24, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */
{ { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_RGB24, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */
{ { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_RGB24, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */
{ { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_RGB24, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */
{ { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_RGB24, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */
{ { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_RGB24, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */
{ { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_RGB24, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */
{ { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_RGB24, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */
{ { 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */
{ { 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */
{ { 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */
{ { 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */
{ { 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */
{ { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */
};
/*****************************************************************************/
/*
* Validate a target display mode is both
* a) a valid display mode for this device and
* b) falls between the contraints imposed by "low" and "high"
*
* If the mode is not (or cannot) be made valid for this device, return B_ERROR.
* If a valid mode can be constructed, but it does not fall within the limits,
* return B_BAD_VALUE.
* If the mode is both valid AND falls within the limits, return B_OK.
*/
status_t PROPOSE_DISPLAY_MODE(display_mode *target,
const display_mode *low,
const display_mode *high)
{
ET6000DisplayMode mode;
mode.magic = ET6000_PRIVATE_DATA_MAGIC;
mode.mode = *target;
mode.memSize = si->memSize;
return ioctl(fd, ET6000_PROPOSE_DISPLAY_MODE, &mode, sizeof(mode));
}
/*****************************************************************************/
/*
* Return the number of modes this device will return from GET_MODE_LIST().
*/
uint32 ACCELERANT_MODE_COUNT(void) {
/* return the number of 'built-in' display modes */
return si->modesNum;
}
/*****************************************************************************/
/*
* Copy the list of guaranteed supported video modes to the location provided.
*/
status_t GET_MODE_LIST(display_mode *dm) {
/* copy them to the buffer pointed at by *dm */
memcpy(dm, et6000ModesList, si->modesNum * sizeof(display_mode));
return B_OK;
}
/*****************************************************************************/
/*
* Create a list of display_modes to pass back to the caller.
*/
status_t createModesList(void) {
size_t maxSize;
uint32 i, j, pixelClockRange;
const display_mode *src;
display_mode *dst, low, high;
color_space spaces[] = {B_RGB15_LITTLE, B_RGB16_LITTLE, B_RGB24_LITTLE};
/* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE */
maxSize = (((MODE_COUNT * 3) * sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1);
/* Create an area to hold the info */
si->modesArea = et6000ModesListArea =
create_area("ET6000 accelerant mode info", (void **)&et6000ModesList,
B_ANY_ADDRESS, maxSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
if (et6000ModesListArea < B_OK)
return et6000ModesListArea;
/* walk through our predefined list and see which modes fit this device */
src = modesList;
dst = et6000ModesList;
si->modesNum = 0;
for (i = 0; i < MODE_COUNT; i++) {
/* set ranges for acceptable values */
low = high = *src;
/* range is 6.25% of default clock: arbitrarily picked */
pixelClockRange = low.timing.pixel_clock >> 5;
low.timing.pixel_clock -= pixelClockRange;
high.timing.pixel_clock += pixelClockRange;
/* some cards need wider virtual widths for certain modes */
high.virtual_width = 2048;
/* do it once for each depth we want to support */
for (j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++) {
/* set target values */
*dst = *src;
/* poke the specific space */
dst->space = low.space = high.space = spaces[j];
/* ask for a compatible mode */
if (PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) {
/* count it, and move on to next mode */
dst++;
si->modesNum++;
}
}
/* advance to next mode */
src++;
}
return B_OK;
}
/*****************************************************************************/

View File

@ -0,0 +1,62 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "GlobalData.h"
#include "generic.h"
#include <sys/ioctl.h>
/*****************************************************************************/
/*
* The code to actually configure the display.
*/
static status_t doSetDisplayMode(display_mode *dm) {
ET6000DisplayMode mode;
mode.magic = ET6000_PRIVATE_DATA_MAGIC;
mode.mode = *dm;
mode.pciConfigSpace = si->pciConfigSpace;
return ioctl(fd, ET6000_SET_DISPLAY_MODE, &mode, sizeof(mode));
}
/*****************************************************************************/
/*
* The exported mode setting routine. First validate the mode,
* then call our private routine to hammer the registers.
*/
status_t SET_DISPLAY_MODE(display_mode *mode_to_set) {
display_mode bounds, target;
status_t result;
uint8 bpp;
/* ask for the specific mode */
target = bounds = *mode_to_set;
if (PROPOSE_DISPLAY_MODE(&target, &bounds, &bounds) != B_OK) /* ==B_ERROR???/// */
return B_ERROR;
result = doSetDisplayMode(&target);
if (result == B_OK) {
switch (target.space) {
case B_RGB24_LITTLE:
case B_RGB24_BIG:
bpp = 3;
break;
case B_RGB16_LITTLE:
case B_RGB16_BIG:
case B_RGB15_LITTLE:
case B_RGB15_BIG:
bpp = 2;
break;
}
si->fbc.bytes_per_row = target.virtual_width * bpp;
si->dm = target;
si->bytesPerPixel = bpp;
et6000aclInit(bpp);
}
return result;
}
/*****************************************************************************/

View File

@ -0,0 +1,45 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#ifndef _ET6000GENERIC_H_
#define _ET6000GENERIC_H_
#include <Accelerant.h>
/*****************************************************************************/
status_t INIT_ACCELERANT(int fd);
ssize_t ACCELERANT_CLONE_INFO_SIZE(void);
void GET_ACCELERANT_CLONE_INFO(void *data);
status_t CLONE_ACCELERANT(void *data);
void UNINIT_ACCELERANT(void);
status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi);
uint32 ACCELERANT_MODE_COUNT(void);
status_t GET_MODE_LIST(display_mode *dm);
status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high);
status_t SET_DISPLAY_MODE(display_mode *mode_to_set);
status_t GET_DISPLAY_MODE(display_mode *current_mode);
status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *a_frame_buffer);
status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high);
uint32 ACCELERANT_ENGINE_COUNT(void);
status_t ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait, sync_token *st, engine_token **et);
status_t RELEASE_ENGINE(engine_token *et, sync_token *st);
void WAIT_ENGINE_IDLE(void);
status_t GET_SYNC_TOKEN(engine_token *et, sync_token *st);
status_t SYNC_TO_TOKEN(sync_token *st);
void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count);
void FILL_RECTANGLE(engine_token *et, uint32 color, fill_rect_params *list, uint32 count);
status_t createModesList(void);
void et6000aclInit(uint8 bpp);
void et6000aclWaitIdle(void);
/*****************************************************************************/
#endif /* _ET6000GENERIC_H_ */

View File

@ -1,6 +1,7 @@
SubDir OBOS_TOP src add-ons kernel drivers graphics ;
SubInclude OBOS_TOP src add-ons kernel drivers graphics common ;
SubInclude OBOS_TOP src add-ons kernel drivers graphics et6x00 ;
SubInclude OBOS_TOP src add-ons kernel drivers graphics matrox ;
SubInclude OBOS_TOP src add-ons kernel drivers graphics neomagic ;
SubInclude OBOS_TOP src add-ons kernel drivers graphics nvidia ;

View File

@ -0,0 +1,15 @@
SubDir OBOS_TOP src add-ons kernel drivers graphics et6x00 ;
UsePrivateHeaders [ FDirName graphics et6x00 ] ;
R5KernelAddon et6x00.driver : kernel drivers bin :
driver.c setmode.c bits.c acl.c
;
# Link to kernel/drivers/dev/graphics
{
local dir = [ FDirName $(OBOS_ADDON_DIR) kernel drivers dev graphics ] ;
local instDriver = <kernel!drivers!dev!graphics>et6x00.driver ;
MakeLocate $(instDriver) : $(dir) ;
RelSymLink $(instDriver) : et6x00.driver ;
}

View File

@ -0,0 +1,46 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "acl.h"
#include "bits.h"
/*****************************************************************************/
__inline void et6000aclMasterInterruptEnable(void *base) {
set8(&((volatile char *)base)[0x34], 0x7f, 0x80);
}
/*****************************************************************************/
__inline void et6000aclMasterInterruptDisable(void *base) {
set8(&((volatile char *)base)[0x34], 0x7f, 0x00);
}
/*****************************************************************************/
__inline void et6000aclReadInterruptEnable(void *base) {
set8(&((volatile char *)base)[0x34], 0xfd, 0x02);
}
/*****************************************************************************/
__inline void et6000aclReadInterruptDisable(void *base) {
set8(&((volatile char *)base)[0x34], 0xfd, 0x00);
}
/*****************************************************************************/
__inline void et6000aclWriteInterruptEnable(void *base) {
set8(&((volatile char *)base)[0x34], 0xfe, 0x01);
}
/*****************************************************************************/
__inline void et6000aclWriteInterruptDisable(void *base) {
set8(&((volatile char *)base)[0x34], 0xfe, 0x00);
}
/*****************************************************************************/
__inline void et6000aclReadInterruptClear(void *base) {
set8(&((volatile char *)base)[0x35], 0xfd, 0x02);
}
/*****************************************************************************/
__inline void et6000aclWriteInterruptClear(void *base) {
set8(&((volatile char *)base)[0x34], 0xfe, 0x00);
}
/*****************************************************************************/
__inline char et6000aclInterruptCause(void *base) {
return ((volatile char *)base)[0x35] & 0x03;
}
/*****************************************************************************/

View File

@ -0,0 +1,27 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#ifndef _ET6000ACL_H_
#define _ET6000ACL_H_
/*****************************************************************************/
__inline void et6000aclMasterInterruptEnable(void *base);
__inline void et6000aclMasterInterruptDisable(void *base);
__inline void et6000aclReadInterruptEnable(void *base);
__inline void et6000aclReadInterruptDisable(void *base);
__inline void et6000aclWriteInterruptEnable(void *base);
__inline void et6000aclWriteInterruptDisable(void *base);
__inline void et6000aclReadInterruptClear(void *base);
__inline void et6000aclWriteInterruptClear(void *base);
__inline char et6000aclInterruptCause(void *base);
/*****************************************************************************/
#define ET6000_ACL_INT_CAUSE_NONE 0
#define ET6000_ACL_INT_CAUSE_READ 2
#define ET6000_ACL_INT_CAUSE_WRITE 1
#define ET6000_ACL_INT_CAUSE_BOTH 3
/*****************************************************************************/
#endif /* _ET6000ACL_H_ */

View File

@ -0,0 +1,86 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "bits.h"
/*****************************************************************************/
/*
* Set bits in a byte pointed by addr; mask must contain 0s at the bits
* positions to be set and must contain 1s at all other bits; val must
* contain the values of bits to be set.
*/
__inline void set8(volatile char *addr, char mask, char val)
{
if (mask == 0)
*addr = val;
else
*addr = (*addr & mask) | (val & ~mask);
}
/*****************************************************************************/
__inline void set16(volatile short *addr, short mask, short val)
{
if (mask == 0)
*addr = val;
else
*addr = (*addr & mask) | (val & ~mask);
}
/*****************************************************************************/
__inline void set32(volatile int *addr, int mask, int val)
{
if (mask == 0)
*addr = val;
else
*addr = (*addr & mask) | (val & ~mask);
}
/*****************************************************************************/
__inline void ioSet8(short port, char mask, char val)
{
char current;
if (mask == 0) {
__asm__ __volatile__ (
"movb %0, %%al\n\t"
"movw %1, %%dx\n\t"
"outb %%al, %%dx"
: /* no output */
: "r"(val), "r"(port)
: "%eax", "%edx"
);
}
else {
__asm__ __volatile__ (
"movw %1, %%dx;"
"inb %%dx, %%al;"
"movb %%al, %0"
: "=r"(current)
: "r"(port)
: "%eax", "%edx"
);
current = (current & mask) | (val & ~mask);
__asm__ __volatile__ (
"movb %0, %%al;"
"movw %1, %%dx;"
"outb %%al, %%dx"
: /* no output */
: "r"(current), "r"(port)
: "%eax", "%edx"
);
}
}
/*****************************************************************************/
__inline char ioGet8(short port)
{
char current;
__asm__ __volatile__ (
"movw %1, %%dx;"
"inb %%dx, %%al;"
"movb %%al, %0"
: "=r"(current)
: "r"(port)
: "%eax", "%edx"
);
return current;
}
/*****************************************************************************/

View File

@ -0,0 +1,18 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#ifndef _ET6000BITS_H_
#define _ET6000BITS_H_
/*****************************************************************************/
__inline void set8(volatile char *addr, char mask, char val);
__inline void set16(volatile short *addr, short mask, short val);
__inline void set32(volatile int *addr, int mask, int val);
__inline void ioSet8(short port, char mask, char val);
__inline char ioGet8(short port);
/*****************************************************************************/
#endif /* _ET6000BITS_H_ */

View File

@ -0,0 +1,713 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
/* standard kernel driver stuff */
#include <KernelExport.h>
#include <PCI.h>
#include <OS.h>
#include <malloc.h>
/* this is for the standardized portion of the driver API */
/* currently only one operation is defined: B_GET_ACCELERANT_SIGNATURE */
#include <graphic_driver.h>
/* this is for sprintf() */
#include <stdio.h>
/* this is for string compares */
#include <string.h>
/* The private interface between the accelerant and the kernel driver. */
#include "DriverInterface.h"
#include "setmode.h"
#include "acl.h"
#include "bits.h"
/*****************************************************************************/
#if DEBUG > 0
#define ddprintf(a) dprintf a
#else
#define ddprintf(a)
#endif
#define MAX_DEVICES 8
/* Tell the kernel what revision of the driver API we support */
int32 api_version = 2;
/*****************************************************************************/
/* This structure is private to the kernel driver */
typedef struct {
uint32 isOpen; /* a count of how many times the devices has been opened */
area_id sharedArea; /* the area shared between the driver and all of the accelerants */
ET6000SharedInfo *si; /* a pointer to the shared area, for convenience */
#if DEBUG > 0
uint32 interrupt_count; /* if we're debugging, a count of how many times
the interrupt handler has been called for this device */
#endif
pci_info pcii; /* a convenience copy of the pci info for this device */
char name[B_OS_NAME_LENGTH]; /* where we keep the name of the device for publishing and comparing */
} ET6000DeviceInfo;
/*****************************************************************************/
typedef struct {
#if DEBUG > 0
uint32 total_interrupts; /* total number of interrupts seen by our handler */
#endif
uint32 count; /* number of devices actually found */
benaphore kernel; /* for serializing opens/closes */
char *deviceNames[MAX_DEVICES+1]; /* device name pointer storage */
ET6000DeviceInfo di[MAX_DEVICES]; /* device specific stuff */
} DeviceData;
/*****************************************************************************/
static DeviceData *pd;
/*****************************************************************************/
/* prototypes for our private functions */
static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie);
static status_t et6000CloseHook(void* dev);
static status_t et6000FreeHook(void* dev);
static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len);
static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len);
static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len);
static status_t et6000MapDevice(ET6000DeviceInfo *di);
static void et6000UnmapDevice(ET6000DeviceInfo *di);
static void et6000ProbeDevices(void);
static int32 et6000Interrupt(void *data);
#if DEBUG > 0
static int et6000dump(int argc, char **argv);
#endif
/*****************************************************************************/
static pci_module_info *pci_bus;
#define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
#define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v))
/*****************************************************************************/
static device_hooks et6000DeviceHooks = {
et6000OpenHook,
et6000CloseHook,
et6000FreeHook,
et6000ControlHook,
et6000ReadHook,
et6000WriteHook,
NULL,
NULL,
NULL,
NULL
};
/*****************************************************************************/
#define TSENG_VENDOR_ID 0x100C /* Tseng Labs Inc */
static uint16 et6000DeviceList[] = {
0x3208, /* ET6000/ET6100 */
0x4702, /* ET6300 */
0
};
static struct {
uint16 vendor;
uint16 *devices;
} supportedDevices[] = {
{TSENG_VENDOR_ID, et6000DeviceList},
{0x0000, NULL}
};
/*****************************************************************************/
/*
* Returns B_OK if one is found, otherwise returns
* B_ERROR so the driver will be unloaded.
*/
status_t init_hardware(void) {
long pciIndex = 0;
pci_info pcii;
bool foundOne = FALSE;
/* choke if we can't find the PCI bus */
if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK)
return B_ERROR;
/* while there are more pci devices */
while ((*pci_bus->get_nth_pci_info)(pciIndex, &pcii) == B_NO_ERROR) {
int vendor = 0;
ddprintf(("ET6000 init_hardware(): checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, pcii.vendor_id, pcii.device_id));
/* if we match a supported vendor */
while (supportedDevices[vendor].vendor) {
if (supportedDevices[vendor].vendor == pcii.vendor_id) {
uint16 *devices = supportedDevices[vendor].devices;
/* while there are more supported devices */
while (*devices) {
/* if we match a supported device */
if (*devices == pcii.device_id) {
ddprintf(("ET6000: we support this device\n"));
foundOne = TRUE;
goto done;
}
/* next supported device */
devices++;
}
}
vendor++;
}
/* next pci_info struct, please */
pciIndex++;
}
ddprintf(("ET6000: init_hardware - no supported devices\n"));
done:
/* put away the module manager */
put_module(B_PCI_MODULE_NAME);
return (foundOne ? B_OK : B_ERROR);
}
/*****************************************************************************/
static void et6000ProbeDevices(void) {
uint32 pciIndex = 0;
uint32 count = 0;
ET6000DeviceInfo *di = pd->di;
/* while there are more pci devices */
while ((count < MAX_DEVICES) &&
((*pci_bus->get_nth_pci_info)(pciIndex, &(di->pcii)) == B_NO_ERROR))
{
int vendor = 0;
ddprintf(("ET6000: checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, di->pcii.vendor_id, di->pcii.device_id));
/* if we match a supported vendor */
while (supportedDevices[vendor].vendor) {
if (supportedDevices[vendor].vendor == di->pcii.vendor_id) {
uint16 *devices = supportedDevices[vendor].devices;
/* while there are more supported devices */
while (*devices) {
/* if we match a supported device */
if (*devices == di->pcii.device_id) {
/* publish the device name */
sprintf(di->name, "graphics/%04X_%04X_%02X%02X%02X",
di->pcii.vendor_id, di->pcii.device_id,
di->pcii.bus, di->pcii.device, di->pcii.function);
ddprintf(("ET6000: making /dev/%s\n", di->name));
/* remember the name */
pd->deviceNames[count] = di->name;
/* mark the driver as available for R/W open */
di->isOpen = 0;
/* mark areas as not yet created */
di->sharedArea = -1;
/* mark pointer to shared data as invalid */
di->si = NULL;
/* inc pointer to device info */
di++;
/* inc count */
count++;
/* break out of these while loops */
goto next_device;
}
/* next supported device */
devices++;
}
}
vendor++;
}
next_device:
/* next pci_info struct, please */
pciIndex++;
}
/* propagate count */
pd->count = count;
/* terminate list of device names with a null pointer */
pd->deviceNames[pd->count] = NULL;
ddprintf(("SKD et6000ProbeDevices: %ld supported devices\n", pd->count));
}
/*****************************************************************************/
status_t init_driver(void) {
/* get a handle for the pci bus */
if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK)
return B_ERROR;
/* driver private data */
pd = (DeviceData *)calloc(1, sizeof(DeviceData));
if (!pd) {
put_module(B_PCI_MODULE_NAME);
return B_ERROR;
}
/* initialize the benaphore */
INIT_BEN(pd->kernel);
/* find all of our supported devices */
et6000ProbeDevices();
#if DEBUG > 0
add_debugger_command("et6000dump", et6000dump, "dump ET6000 kernel driver persistant data");
#endif
return B_OK;
}
/*****************************************************************************/
const char **publish_devices(void) {
/* return the list of supported devices */
return (const char **)pd->deviceNames;
}
/*****************************************************************************/
device_hooks *find_device(const char *name) {
int index = 0;
while (pd->deviceNames[index]) {
if (strcmp(name, pd->deviceNames[index]) == 0)
return &et6000DeviceHooks;
index++;
}
return NULL;
}
/*****************************************************************************/
void uninit_driver(void) {
#if DEBUG > 0
remove_debugger_command("et6000dump", et6000dump);
#endif
/* free the driver data */
DELETE_BEN(pd->kernel);
free(pd);
pd = NULL;
/* put the pci module away */
put_module(B_PCI_MODULE_NAME);
}
/*****************************************************************************/
static int32 et6000Interrupt(void *data) {
int32 handled = B_UNHANDLED_INTERRUPT;
ET6000DeviceInfo *di = (ET6000DeviceInfo *)data;
ET6000SharedInfo *si = di->si;
int32 *flags = &(si->flags);
#if DEBUG > 0
pd->total_interrupts++;
#endif
/* is someone already handling an interrupt for this device? */
if (atomic_or(flags, ET6000_HANDLER_INSTALLED) & ET6000_HANDLER_INSTALLED) {
#if DEBUG > 0
kprintf("ET6000: Already in handler!\n");
#endif
goto exit0;
}
switch (et6000aclInterruptCause(si->mmRegs)) {
case ET6000_ACL_INT_CAUSE_NONE:
handled = B_UNHANDLED_INTERRUPT;
break;
case ET6000_ACL_INT_CAUSE_READ:
et6000aclReadInterruptClear(si->mmRegs);
handled = B_HANDLED_INTERRUPT;
break;
case ET6000_ACL_INT_CAUSE_WRITE:
et6000aclWriteInterruptClear(si->mmRegs);
handled = B_HANDLED_INTERRUPT;
break;
case ET6000_ACL_INT_CAUSE_BOTH: /* Can it be at all? */
et6000aclReadInterruptClear(si->mmRegs);
et6000aclWriteInterruptClear(si->mmRegs);
handled = B_HANDLED_INTERRUPT;
break;
}
#if DEBUG > 0
/* increment the counter for this device */
if (handled == B_HANDLED_INTERRUPT)
di->interrupt_count++;
#endif
/* note that we're not in the handler any more */
atomic_and(flags, ~ET6000_HANDLER_INSTALLED);
exit0:
return handled;
}
/*****************************************************************************/
uint32 et6000GetOnboardMemorySize(uint16 pciConfigSpace,
volatile void *memory)
{
uint32 memSize = 0;
ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */
ioSet8(0x3b8, 0x00, 0xa0); /* Set the KEY for monochrome modes */
switch (ioGet8(0x3C2) & 0x03) {
case 0x00: /* onboard memory is of DRAM type */
memSize = 1024*1024 * ((ioGet8(pciConfigSpace + 0x45) & 0x03) + 1);
break;
case 0x03: /* onboard memory is of MDRAM type */
memSize = /* number*8 of 32kb banks per channel */
((ioGet8(pciConfigSpace + 0x47) & 0x07) + 1) * 8 * 32*1024;
if (ioGet8(pciConfigSpace + 0x45) & 0x04) /* If 2 channels */
memSize *= 2;
break;
default: /* onboard memory is of unknown type */
memSize = 4196*1024; /* Let it be of maximum possible size */
}
/*
* This algorithm would fail to recongize 2.25Mb of onboard
* memory - it would detect 2.5Mb instead. It needs to be fixed.
*/
if (memSize == 2621440) { /* If 2.5Mb detected */
uint8 pci40 = ioGet8(pciConfigSpace+0x40);
et6000EnableLinearMemoryMapping(pciConfigSpace);
/* Check whether the memory beyond 2.25Mb really exists */
*(volatile uint32 *)((uint32)memory + 2359296) = 0xaa55aa55;
if (*(volatile uint32 *)((uint32)memory + 2359296) != 0xaa55aa55)
memSize = 2359296; /* It's 2.25Mb */
ioSet8(pciConfigSpace+0x40, 0x00, pci40); /* Restore */
}
return memSize;
}
/*****************************************************************************/
static status_t et6000MapDevice(ET6000DeviceInfo *di) {
char buffer[B_OS_NAME_LENGTH];
ET6000SharedInfo *si = di->si;
uint32 tmpUlong;
pci_info *pcii = &(di->pcii);
/* Enable memory space access and I/O space access */
tmpUlong = get_pci(PCI_command, 4);
tmpUlong |= 0x00000003;
set_pci(PCI_command, 4, tmpUlong);
/* Enable ROM decoding */
tmpUlong = get_pci(PCI_rom_base, 4);
tmpUlong |= 0x00000001;
set_pci(PCI_rom_base, 4, tmpUlong);
/* PCI header base address in I/O space */
si->pciConfigSpace = (uint16)di->pcii.u.h0.base_registers[1];
sprintf(buffer, "%04X_%04X_%02X%02X%02X videomemory",
di->pcii.vendor_id, di->pcii.device_id,
di->pcii.bus, di->pcii.device, di->pcii.function);
/*
* We map the whole graphics card memory area (which consist of RAM memory
* and memory mapped registers) at once. Memory mapped registers must not
* be cacheble, so the whole area is mapped with B_MTR_UC (unable caching).
* We certainly could map separately the RAM memory with write combining
* (B_MTR_WC) and the memory mapped registers with B_MTR_UC.
*/
si->memoryArea = map_physical_memory(buffer,
(void *)di->pcii.u.h0.base_registers[0],
di->pcii.u.h0.base_register_sizes[0],
B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_UC,
B_READ_AREA + B_WRITE_AREA,
&(si->memory));
si->framebuffer = si->memory;
si->mmRegs = (void *)((uint32)si->memory + 0x003fff00);
si->emRegs = (void *)((uint32)si->memory + 0x003fe000);
/* remember the physical addresses */
si->physMemory = si->physFramebuffer =
(void *) di->pcii.u.h0.base_registers_pci[0];
si->memSize = et6000GetOnboardMemorySize(si->pciConfigSpace, si->memory);
/* in any case, return the result */
return si->memoryArea;
}
/*****************************************************************************/
static void et6000UnmapDevice(ET6000DeviceInfo *di) {
ET6000SharedInfo *si = di->si;
ddprintf(("et6000UnmapDevice(%08lx) begins...\n", (uint32)di));
ddprintf((" memoryArea: %ld\n", si->memoryArea));
if (si->memoryArea >= 0)
delete_area(si->memoryArea);
si->memoryArea = -1;
si->framebuffer = NULL;
si->physFramebuffer = NULL;
si->memory = NULL;
si->physMemory = NULL;
ddprintf(("et6000UnmapDevice() ends.\n"));
}
/*****************************************************************************/
static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie) {
int32 index = 0;
ET6000DeviceInfo *di;
ET6000SharedInfo *si;
status_t result = B_OK;
char shared_name[B_OS_NAME_LENGTH];
ddprintf(("SKD et6000OpenHook(%s, %ld, 0x%08lx)\n", name, flags, (uint32)cookie));
/* find the device name in the list of devices */
/* we're never passed a name we didn't publish */
while(pd->deviceNames[index] &&
(strcmp(name, pd->deviceNames[index]) != 0))
{
index++;
}
/* for convienience */
di = &(pd->di[index]);
/* make sure no one else has write access to the common data */
AQUIRE_BEN(pd->kernel);
/* if it's already open for writing */
if (di->isOpen) {
/* mark it open another time */
goto mark_as_open;
}
/* create the shared area */
sprintf(shared_name, "%04X_%04X_%02X%02X%02X shared",
di->pcii.vendor_id, di->pcii.device_id,
di->pcii.bus, di->pcii.device, di->pcii.function);
/* create this area with NO user-space read or write permissions, to prevent accidental dammage */
di->sharedArea = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(ET6000SharedInfo) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK, 0);
if (di->sharedArea < 0) {
/* return the error */
result = di->sharedArea;
goto done;
}
/* save a few dereferences */
si = di->si;
/* save the vendor and device IDs */
si->vendor_id = di->pcii.vendor_id;
si->device_id = di->pcii.device_id;
si->revision = di->pcii.revision;
si->pixelClockMax16 = 135000;
si->pixelClockMax24 = 135000;
if (si->vendor_id == 0x100C) { /* Tseng Labs, Inc. */
switch (si->device_id) {
case 0x3208:/* ET6000/ET6100 */
if (si->revision < 0x70) { /* ET6000 */
si->pixelClockMax16 = 135000;
si->pixelClockMax24 = 135000;
}
else { /* ET6100 */
si->pixelClockMax16 = 175000;
si->pixelClockMax24 = 175000;
}
break;
case 0x4702: /* ET6300 */
si->pixelClockMax16 = 220000;
si->pixelClockMax24 = 220000;
break;
}
}
/* map the device */
result = et6000MapDevice(di);
if (result < 0)
goto free_shared;
result = B_OK;
/*
* Clear any pending interrupts and disable interrupts. Driver
* currently does not use interrupts and unlikely will in future.
*/
et6000aclReadInterruptClear(si->mmRegs);
et6000aclWriteInterruptClear(si->mmRegs);
et6000aclMasterInterruptDisable(si->mmRegs);
/* Install the interrupt handler */
result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line,
et6000Interrupt, (void *)di, 0);
/* bail if we couldn't install the handler */
if (result != B_OK)
goto unmap;
mark_as_open:
/* mark the device open */
di->isOpen++;
/* send the cookie to the opener */
*cookie = di;
goto done;
unmap:
et6000UnmapDevice(di);
free_shared:
/* clean up our shared area */
delete_area(di->sharedArea);
di->sharedArea = -1;
di->si = NULL;
done:
/* end of critical section */
RELEASE_BEN(pd->kernel);
/* all done, return the status */
ddprintf(("et6000OpenHook returning 0x%08lx\n", result));
return result;
}
/*****************************************************************************/
/*
* et6000ReadHook - does nothing, gracefully
*/
static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len)
{
*len = 0;
return B_NOT_ALLOWED;
}
/*****************************************************************************/
/*
* et6000WriteHook - does nothing, gracefully
*/
static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len)
{
*len = 0;
return B_NOT_ALLOWED;
}
/*****************************************************************************/
/*
* et6000CloseHook - does nothing, gracefully
*/
static status_t et6000CloseHook(void* dev)
{
ddprintf(("SKD et6000CloseHook(%08lx)\n", (uint32)dev));
/* we don't do anything on close: there might be dup'd fd */
return B_NO_ERROR;
}
/*****************************************************************************/
/*
* et6000FreeHook - close down the device
*/
static status_t et6000FreeHook(void* dev) {
ET6000DeviceInfo *di = (ET6000DeviceInfo *)dev;
ET6000SharedInfo *si = di->si;
ddprintf(("SKD et6000FreeHook() begins...\n"));
/* lock the driver */
AQUIRE_BEN(pd->kernel);
/* if opened multiple times, decrement the open count and exit */
if (di->isOpen > 1)
goto unlock_and_exit;
/* Clear any pending interrupts and disable interrupts. */
et6000aclReadInterruptClear(si->mmRegs);
et6000aclWriteInterruptClear(si->mmRegs);
et6000aclMasterInterruptDisable(si->mmRegs);
/* Remove the interrupt handler */
remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, et6000Interrupt, di);
/* free framebuffer area */
et6000UnmapDevice(di);
/* clean up our shared area */
delete_area(di->sharedArea);
di->sharedArea = -1;
di->si = NULL;
unlock_and_exit:
/* mark the device available */
di->isOpen--;
/* unlock the driver */
RELEASE_BEN(pd->kernel);
ddprintf(("SKD et6000FreeHook() ends.\n"));
/* all done */
return B_OK;
}
/*****************************************************************************/
/*
* et6000ControlHook - where the real work is done
*/
static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len) {
ET6000DeviceInfo *di = (ET6000DeviceInfo *)dev;
status_t result = B_DEV_INVALID_IOCTL;
/* ddprintf(("ioctl: %d, buf: 0x%08x, len: %d\n", msg, buf, len)); */
switch (msg) {
/* the only PUBLIC ioctl */
case B_GET_ACCELERANT_SIGNATURE: {
char *sig = (char *)buf;
strcpy(sig, "et6000.accelerant");
result = B_OK;
} break;
/* PRIVATE ioctl from here on */
case ET6000_GET_PRIVATE_DATA: {
ET6000GetPrivateData *gpd = (ET6000GetPrivateData *)buf;
if (gpd->magic == ET6000_PRIVATE_DATA_MAGIC) {
gpd->sharedInfoArea = di->sharedArea;
result = B_OK;
}
} break;
case ET6000_GET_PCI: {
ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf;
if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) {
pci_info *pcii = &(di->pcii);
gsp->value = get_pci(gsp->offset, gsp->size);
result = B_OK;
}
} break;
case ET6000_SET_PCI: {
ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf;
if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) {
pci_info *pcii = &(di->pcii);
set_pci(gsp->offset, gsp->size, gsp->value);
result = B_OK;
}
} break;
case ET6000_DEVICE_NAME: { /* Needed for cloning */
ET6000DeviceName *dn = (ET6000DeviceName *)buf;
if(dn->magic == ET6000_PRIVATE_DATA_MAGIC) {
strncpy(dn->name, di->name, B_OS_NAME_LENGTH);
result = B_OK;
}
} break;
case ET6000_PROPOSE_DISPLAY_MODE: {
ET6000DisplayMode *dm = (ET6000DisplayMode *)buf;
if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) {
result = et6000ProposeMode(&dm->mode, dm->memSize);
}
} break;
case ET6000_SET_DISPLAY_MODE: {
ET6000DisplayMode *dm = (ET6000DisplayMode *)buf;
if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) {
result = et6000SetMode(&dm->mode, dm->pciConfigSpace);
}
} break;
}
return result;
}
/*****************************************************************************/
#if DEBUG > 0
static int et6000dump(int argc, char **argv) {
int i;
kprintf("ET6000 Kernel Driver Persistant Data\n\nThere are %ld card(s)\n", pd->count);
kprintf("Driver wide benahpore: %ld/%ld\n", pd->kernel.ben, pd->kernel.sem);
kprintf("Total seen interrupts: %ld\n", pd->total_interrupts);
for (i = 0; i < pd->count; i++) {
ET6000DeviceInfo *di = &(pd->di[i]);
uint16 device_id = di->pcii.device_id;
ET6000SharedInfo *si = di->si;
kprintf(" device_id: 0x%04x\n", device_id);
kprintf(" interrupt count: %ld\n", di->interrupt_count);
if (si) {
kprintf(" flags:");
}
kprintf("\n");
}
return 1; /* the magic number for success */
}
#endif
/*****************************************************************************/

View File

@ -0,0 +1,45 @@
Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
the above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
This Software uses Be sample code and the license of this Software inherits
the statements of Be Sample Code License.
-------------------------------------------------------------------------------
Be Sample Code License
----------------------
Copyright 1991-1999, Be Incorporated.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,12 @@
This graphics driver for BeOS 5 supports Tseng Labs ET6000, ET6100
and ET6300 chips. Version 0.5 features are:
- 640x480, 800x600 and 1024x768 resolutions with 15, 16 and 24 bits
per pixel and 60-75 Hz monitor refresh rates;
- hardware accelerated screen-to-screen blocks copying;
- hardware accelerated rectangular areas filling.
Note that the original Screen preferences program shipped with
BeOS 5 does not provide the possibily to set 24bpp modes.
To install the driver run install.sh script in Terminal
from "binaries" directory.

View File

@ -0,0 +1,430 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#include "setmode.h"
/*
* ATTENTION: Currently we set the graphics modes by setting the registers
* with the beforehand dumped values of the corresponding registers. So not
* all graphics modes ET6x00 chips are capable of are accessible. So it would
* be great to implement the normal algorithm of run-time computing of the
* values to set the register.
*/
/*****************************************************************************/
typedef struct {
uint32 VisScreenWidth;
uint32 VisScreenHeight;
uint8 BitsPerPlane;
uint8 NumberGreenBits;
uint16 Frequency;
} VIDEO_MODE_INFORMATION;
/*****************************************************************************/
/*
* ATTENTION: Don't forget that CRTC indexed register 0x11
* bit[7] write-protects some registers.
*/
struct {
uint16 width, height, bpp, refreshRate;
uint8 clock0M, clock0N;
uint8 pci42; /* contains MCLK divider (MDIV) */
uint8 crtc[64];
} clock0MN[] = {
{640, 480, 24, 75, 0x28, 0x22, 0x02,
{0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
{640, 480, 24, 72, 0x56, 0x63, 0x00,
{0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x0b, 0xdf, 0xf0, 0x60, 0xe7, 0xff, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
{640, 480, 24, 60, 0x28, 0x22, 0x02,
{0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
{640, 480, 16, 75, 0x56, 0x43, 0x01,
{0x64, 0x4f, 0x4f, 0x88, 0x54, 0x9c, 0xf2, 0x1f,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe0, 0x03, 0xdf, 0xa0, 0x60, 0xdf, 0xf3, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
{640, 480, 16, 72, 0x56, 0x43, 0x01,
{0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x0b, 0xdf, 0xa0, 0x60, 0xe7, 0xff, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
{640, 480, 16, 60, 0x28, 0x41, 0x01,
{0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xea, 0x0c, 0xdf, 0xa0, 0x60, 0xe7, 0x04, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
{800, 600, 24, 75, 0x79, 0x49, 0x00,
{0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
{800, 600, 24, 72, 0x28, 0x41, 0x00,
{0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7c, 0x02, 0x57, 0x2c, 0x60, 0x57, 0x99, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
{800, 600, 24, 60, 0x79, 0x49, 0x00,
{0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
{800, 600, 16, 75, 0x51, 0x44, 0x00,
{0x7f, 0x63, 0x63, 0x83, 0x68, 0x12, 0x6f, 0xf0,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x58, 0x0b, 0x57, 0xc8, 0x60, 0x57, 0x70, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
{800, 600, 16, 72, 0x28, 0x41, 0x00,
{0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7c, 0x02, 0x57, 0xc8, 0x60, 0x57, 0x99, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
{800, 600, 16, 60, 0x79, 0x49, 0x00,
{0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x58, 0x0c, 0x57, 0xc8, 0x60, 0x57, 0x73, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}},
{1024, 768, 16, 75, 0x1f, 0x21, 0x00,
{0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
{1024, 768, 16, 70, 0x28, 0x22, 0x00,
{0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
{1024, 768, 16, 60, 0x6b, 0x44, 0x00,
{0xa1, 0x7f, 0x80, 0x84, 0x88, 0x99, 0x26, 0xfd,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x0a, 0xff, 0x00, 0x60, 0x04, 0x22, 0xab,
0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}},
};
#define CLOCK0MN (sizeof(clock0MN) / sizeof(clock0MN[0]))
/*****************************************************************************/
__inline void et6000EnableLinearMemoryMapping(uint16 pciConfigSpace)
{
/*
* Relocate memory via PCI Base Address 0; don't enable MMU;
* enable memory mapped registers; enable system linear memory mapping.
*/
ioSet8(pciConfigSpace+0x40, 0xf0, 0x0b);
}
/*****************************************************************************/
static void setPCIConfigSpaceRegisters41to5E(uint16 pciConfigSpace,
VIDEO_MODE_INFORMATION *mi,
uint32 m)
{
uint8 pci415e[30] = {
0x3a, 0x00, 0x02, 0x15, 0x04, 0x40, 0x13, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8 i;
pci415e[1] = clock0MN[m].pci42;
for (i=0x41; i<0x5f; i++) {
if ((i==0x45) || ((i>0x47)&&(i<0x4e)) ||
(i==0x4e) || ((i>0x59)&&(i<0x5c)))
continue; /* Skip absent or read-only registers */
ioSet8(pciConfigSpace+i, 0x00, pci415e[i-0x41]);
}
if (mi->BitsPerPlane == 16) {
if (mi->NumberGreenBits == 5)
ioSet8(pciConfigSpace+0x58, 0xfd, 0x00); /* 16bpp is 5:5:5 */
else
ioSet8(pciConfigSpace+0x58, 0xfd, 0x02); /* 16bpp is 5:6:5 */
}
}
/*****************************************************************************/
static void setMiscOutputRegister(VIDEO_MODE_INFORMATION *mi) {
uint8 MiscOutputReg;
if (mi->VisScreenHeight < 400)
MiscOutputReg = 0x80; /* -vsync, +hsync */
else if (mi->VisScreenHeight < 480)
MiscOutputReg = 0x40; /* +vsync, -hsync */
else if (mi->VisScreenHeight < 768)
MiscOutputReg = 0xc0; /* -vsync, -hsync */
else
MiscOutputReg = 0x00; /* +vsync, +hsync */
ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0x3f) | MiscOutputReg);
/* Enable host access to display memory, color mode */
ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xfc) | 0x03);
}
/*****************************************************************************/
static void setATC(uint8 bpp) {
uint8 atc[7] = {0x21, 0x00, 0x30, 0x00, 0x00}, atc16 = 0x80;///
///uint8 atc[7] = {0x01, 0x00, 0x0f, 0x00, 0x00}, atc16 = 0x80;///zzz
uint8 i, atcIndexReg;
volatile uint8 f;
f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */
atcIndexReg = ioGet8(0x3c0) & 0xe0; /* Save bits[7:5] */
for (i = 0x10; i < 0x15; i++) {
f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */
ioSet8(0x3c0, 0x00, i | atcIndexReg);
ioSet8(0x3c0, 0x00, atc[i-0x10]);
}
switch (bpp) {
case 24:
atc16 |= 0x20;
break;
case 16:
atc16 |= 0x10;
break;
}
f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */
ioSet8(0x3c0, 0x00, 0x16 | atcIndexReg);
ioSet8(0x3c0, 0x00, atc16);
}
/*****************************************************************************/
static void setTS(void) {
uint8 ts[7] = {0x02, 0x01, 0x0f, 0x00, 0x0e, 0x00, 0x00};
uint8 i;
for (i = 0; i < 7; i++) {
if (i == 5) continue; /* Skip absent register */
ioSet8(0x3c4, 0xf8, i);
ioSet8(0x3c5, 0x00, ts[i]);
}
}
/*****************************************************************************/
static void setGDC(void) {
uint8 gdc[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff};
uint8 i;
for (i = 0; i < 9; i++) {
ioSet8(0x3ce, 0xf0, i);
ioSet8(0x3cf, 0x00, gdc[i]);
}
}
/*****************************************************************************/
static void setClock0RegNum(uint8 regNum) {
/* Set bits[1:0] of the selected CLOCK0 PLL parameters register number */
ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xf3) | ((regNum & 0x03) << 2));
/* Set bit[2] of the selected CLOCK0 PLL parameters register number */
ioSet8(0x3d4, 0xc0, 0x34);
ioSet8(0x3d5, 0xfd, (regNum & 0x04) << 1);
}
/*****************************************************************************/
static void setPLL(uint16 pciConfigSpace,
uint32 m) /* mode index */
{
uint8 regNum = 3;
uint8 clock0M = 0, clock0N = 0;
clock0M = clock0MN[m].clock0M;
clock0N = clock0MN[m].clock0N;
setClock0RegNum(regNum);
ioSet8(pciConfigSpace+0x67, 0x00, regNum);
ioSet8(pciConfigSpace+0x68, 0x00, regNum);
ioSet8(pciConfigSpace+0x69, 0x00, clock0M);
ioSet8(pciConfigSpace+0x69, 0x00, clock0N);
}
/*****************************************************************************/
static void setCRTC(uint32 m) /* mode index */
{
uint8 i;
/* Unlock the write protection of several registers */
ioSet8(0x3d4, 0xc0, 0x11);
ioSet8(0x3d5, 0x7f, 0x00);
for (i = 0; i < 64; i++) {
if (((i > 0x18) && (i < 0x33)) ||
((i > 0x35) && (i < 0x3f)))
continue; /* Skip absent or read-only registers */
ioSet8(0x3d4, 0xc0, i);
ioSet8(0x3d5, 0x00, clock0MN[m].crtc[i]);
}
}
/*****************************************************************************/
uint32 et6000SetGraphicsMode(VIDEO_MODE_INFORMATION *mi,
uint16 pciConfigSpace)
{
uint8 m;
for(m = 0; m < CLOCK0MN; m++) {
if ((clock0MN[m].width == mi->VisScreenWidth) &&
(clock0MN[m].height == mi->VisScreenHeight) &&
(clock0MN[m].bpp == mi->BitsPerPlane) &&
((clock0MN[m].refreshRate-1 <= mi->Frequency) &&
(clock0MN[m].refreshRate+1 >= mi->Frequency)))
{
break;
}
}
if (m == CLOCK0MN)
return B_BAD_VALUE; /* Found no entry for requested mode */
et6000EnableLinearMemoryMapping(pciConfigSpace);
setMiscOutputRegister(mi);
ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */
setPCIConfigSpaceRegisters41to5E(pciConfigSpace, mi, m);
ioSet8(0x3c6, 0x00, 0xff); /* Set pixel mask */
setATC(mi->BitsPerPlane);
setTS();
setGDC();
setCRTC(m);
setPLL(pciConfigSpace, m);
return B_OK;
}
/*****************************************************************************/
status_t et6000SetMode(display_mode *mode, uint16 pciConfigSpace) {
VIDEO_MODE_INFORMATION mi;
mi.VisScreenWidth = mode->virtual_width;
mi.VisScreenHeight = mode->virtual_height;
switch (mode->space) {
case B_RGB24_LITTLE:
case B_RGB24_BIG:
mi.BitsPerPlane = 24;
mi.NumberGreenBits = 8;
break;
case B_RGB16_LITTLE:
case B_RGB16_BIG:
mi.BitsPerPlane = 16;
mi.NumberGreenBits = 6;
break;
case B_RGB15_LITTLE:
case B_RGB15_BIG:
mi.BitsPerPlane = 16;
mi.NumberGreenBits = 5;
break;
}
mi.Frequency = (uint16) (mode->timing.pixel_clock * 1000
/ (mode->timing.h_total * mode->timing.v_total));
return et6000SetGraphicsMode(&mi, pciConfigSpace);
}
/*****************************************************************************/
status_t et6000ProposeMode(display_mode *mode, uint32 memSize) {
uint8 m, bpp;
uint16 refreshRate;
/* Framebuffer must not overlap with the memory mapped registers */
if (memSize > 0x3fe000)
memSize = 0x3fe000;
memSize -= ET6000_ACL_NEEDS_MEMORY;
switch (mode->space) {
case B_RGB24_LITTLE:
case B_RGB24_BIG:
bpp = 24;
break;
case B_RGB16_LITTLE:
case B_RGB16_BIG:
case B_RGB15_LITTLE:
case B_RGB15_BIG:
bpp = 16;
break;
}
refreshRate = (uint16) (mode->timing.pixel_clock * 1000
/ (mode->timing.h_total * mode->timing.v_total));
for(m = 0; m < CLOCK0MN; m++) {
if ((clock0MN[m].width == mode->virtual_width) &&
(clock0MN[m].height == mode->virtual_height) &&
(clock0MN[m].bpp == bpp) &&
((clock0MN[m].refreshRate-1 <= refreshRate) &&
(clock0MN[m].refreshRate+1 >= refreshRate)))
{
break;
}
}
if (m == CLOCK0MN)
return B_BAD_VALUE; /* Found no entry for requested mode */
if (mode->virtual_width * mode->virtual_height * bpp / 8 > memSize)
return B_BAD_VALUE; /* Not enough adapter onboard memory */
return B_OK;
}
/*****************************************************************************/

View File

@ -0,0 +1,19 @@
/*****************************************************************************\
* Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
* Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
\*****************************************************************************/
#ifndef _ET6000SETMODE_H_
#define _ET6000SETMODE_H_
#include "DriverInterface.h"
#include "bits.h"
/*****************************************************************************/
__inline void et6000EnableLinearMemoryMapping(uint16 pciConfigSpace);
status_t et6000SetMode(display_mode *mode, uint16 pciConfigSpace);
status_t et6000ProposeMode(display_mode *mode, uint32 memSize);
/*****************************************************************************/
#endif /* _ET6000SETMODE_H_ */