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:
parent
76dd4cf399
commit
8731383444
123
headers/private/graphics/et6x00/DriverInterface.h
Normal file
123
headers/private/graphics/et6x00/DriverInterface.h
Normal 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_ */
|
@ -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 ;
|
||||
|
256
src/add-ons/accelerants/et6x00/Acceleration.c
Normal file
256
src/add-ons/accelerants/et6x00/Acceleration.c
Normal 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++;
|
||||
}
|
||||
/*****************************************************************************/
|
61
src/add-ons/accelerants/et6x00/EngineManagment.c
Normal file
61
src/add-ons/accelerants/et6x00/EngineManagment.c
Normal 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;
|
||||
}
|
||||
/*****************************************************************************/
|
69
src/add-ons/accelerants/et6x00/GetAccelerantHook.c
Normal file
69
src/add-ons/accelerants/et6x00/GetAccelerantHook.c
Normal 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
|
||||
}
|
||||
/*****************************************************************************/
|
57
src/add-ons/accelerants/et6x00/GetModeInfo.c
Normal file
57
src/add-ons/accelerants/et6x00/GetModeInfo.c
Normal 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;
|
||||
}
|
||||
/*****************************************************************************/
|
17
src/add-ons/accelerants/et6x00/GlobalData.c
Normal file
17
src/add-ons/accelerants/et6x00/GlobalData.c
Normal 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 */
|
||||
/*****************************************************************************/
|
23
src/add-ons/accelerants/et6x00/GlobalData.h
Normal file
23
src/add-ons/accelerants/et6x00/GlobalData.h
Normal 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_ */
|
227
src/add-ons/accelerants/et6x00/InitAccelerant.c
Normal file
227
src/add-ons/accelerants/et6x00/InitAccelerant.c
Normal 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;
|
||||
}
|
||||
/*****************************************************************************/
|
18
src/add-ons/accelerants/et6x00/Jamfile
Normal file
18
src/add-ons/accelerants/et6x00/Jamfile
Normal 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 ;
|
141
src/add-ons/accelerants/et6x00/ProposeDisplayMode.c
Normal file
141
src/add-ons/accelerants/et6x00/ProposeDisplayMode.c
Normal 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;
|
||||
}
|
||||
/*****************************************************************************/
|
62
src/add-ons/accelerants/et6x00/SetDisplayMode.c
Normal file
62
src/add-ons/accelerants/et6x00/SetDisplayMode.c
Normal 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;
|
||||
}
|
||||
/*****************************************************************************/
|
45
src/add-ons/accelerants/et6x00/generic.h
Normal file
45
src/add-ons/accelerants/et6x00/generic.h
Normal 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_ */
|
@ -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 ;
|
||||
|
15
src/add-ons/kernel/drivers/graphics/et6x00/Jamfile
Normal file
15
src/add-ons/kernel/drivers/graphics/et6x00/Jamfile
Normal 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 ;
|
||||
}
|
46
src/add-ons/kernel/drivers/graphics/et6x00/acl.c
Normal file
46
src/add-ons/kernel/drivers/graphics/et6x00/acl.c
Normal 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;
|
||||
}
|
||||
/*****************************************************************************/
|
27
src/add-ons/kernel/drivers/graphics/et6x00/acl.h
Normal file
27
src/add-ons/kernel/drivers/graphics/et6x00/acl.h
Normal 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_ */
|
86
src/add-ons/kernel/drivers/graphics/et6x00/bits.c
Normal file
86
src/add-ons/kernel/drivers/graphics/et6x00/bits.c
Normal 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;
|
||||
}
|
||||
/*****************************************************************************/
|
18
src/add-ons/kernel/drivers/graphics/et6x00/bits.h
Normal file
18
src/add-ons/kernel/drivers/graphics/et6x00/bits.h
Normal 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_ */
|
713
src/add-ons/kernel/drivers/graphics/et6x00/driver.c
Normal file
713
src/add-ons/kernel/drivers/graphics/et6x00/driver.c
Normal 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
|
||||
/*****************************************************************************/
|
45
src/add-ons/kernel/drivers/graphics/et6x00/license
Normal file
45
src/add-ons/kernel/drivers/graphics/et6x00/license
Normal 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.
|
12
src/add-ons/kernel/drivers/graphics/et6x00/readme
Normal file
12
src/add-ons/kernel/drivers/graphics/et6x00/readme
Normal 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.
|
430
src/add-ons/kernel/drivers/graphics/et6x00/setmode.c
Normal file
430
src/add-ons/kernel/drivers/graphics/et6x00/setmode.c
Normal 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;
|
||||
}
|
||||
/*****************************************************************************/
|
19
src/add-ons/kernel/drivers/graphics/et6x00/setmode.h
Normal file
19
src/add-ons/kernel/drivers/graphics/et6x00/setmode.h
Normal 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_ */
|
Loading…
Reference in New Issue
Block a user