incorporated savage driver sources from Gerald Zajac. I hope it's the good place for this.

fixed warnings and code style. Please, from now on, provide *patches* to this version.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21421 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2007-06-15 21:02:08 +00:00
parent 60b8b10331
commit de050c6029
27 changed files with 4504 additions and 3996 deletions
@@ -1,12 +1,16 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors:
Gerald Zajac 2006-2007
*/ */
#ifndef DRIVERINTERFACE_H #ifndef DRIVERINTERFACE_H
#define DRIVERINTERFACE_H #define DRIVERINTERFACE_H
#include <Accelerant.h> #include <Accelerant.h>
#include <GraphicsDefs.h>
#include <Drivers.h> #include <Drivers.h>
#include <PCI.h> #include <PCI.h>
#include <OS.h> #include <OS.h>
@@ -19,6 +23,9 @@
extern "C" { extern "C" {
#endif #endif
#define NUM_ELEMENTS(a) ((int)(sizeof(a) / sizeof(a[0]))) // for computing number of elements in an array
typedef struct typedef struct
{ {
sem_id sem; sem_id sem;
@@ -31,15 +38,8 @@ typedef struct
#define DELETE_BEN(x) delete_sem(x.sem); #define DELETE_BEN(x) delete_sem(x.sem);
#define SAVAGE_PRIVATE_DATA_MAGIC 0x1234 /* a private driver rev, of sorts */ #define SAVAGE_PRIVATE_DATA_MAGIC 0x5791 // a private driver rev, of sorts
#define MAX_SAVAGE_DEVICE_NAME_LENGTH 32
#define SKD_MOVE_CURSOR 0x00000001
#define SKD_PROGRAM_CLUT 0x00000002
#define SKD_SET_START_ADDR 0x00000004
#define SKD_SET_CURSOR 0x00000008
#define SKD_HANDLER_INSTALLED 0x80000000
enum enum
{ {
@@ -48,145 +48,192 @@ enum
SAVAGE_SET_PCI, SAVAGE_SET_PCI,
SAVAGE_DEVICE_NAME, SAVAGE_DEVICE_NAME,
SAVAGE_RUN_INTERRUPTS, SAVAGE_RUN_INTERRUPTS,
SAVAGE_DPRINTF
}; };
// Chip tags. These are used to group the adapters into related
// families. See table SavageChipsetTable in driver.c
enum S3ChipTags
{
S3_UNKNOWN = 0,
S3_SAVAGE3D,
S3_SAVAGE_MX,
S3_SAVAGE4,
S3_PROSAVAGE,
S3_TWISTER,
S3_PROSAVAGEDDR,
S3_SUPERSAVAGE,
S3_SAVAGE2000,
};
#define S3_SAVAGE3D_SERIES(chip) ((chip==S3_SAVAGE3D) || (chip==S3_SAVAGE_MX))
#define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) \
|| (chip==S3_PROSAVAGE) \
|| (chip==S3_TWISTER) \
|| (chip==S3_PROSAVAGEDDR))
#define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip==S3_PROSAVAGEDDR))
typedef enum {
MT_NONE,
MT_CRT,
MT_LCD,
MT_DFP,
MT_TV
} SavageMonitorType;
// Bitmap descriptor structures for BCI
typedef struct _HIGH {
unsigned short Stride;
unsigned char Bpp;
unsigned char ResBWTile;
} HIGH;
typedef struct _BMPDESC1 {
unsigned long Offset;
HIGH HighPart;
} BMPDESC1;
typedef struct _BMPDESC2 {
unsigned long LoPart;
unsigned long HiPart;
} BMPDESC2;
typedef union _BMPDESC {
BMPDESC1 bd1;
BMPDESC2 bd2;
} BMPDESC;
typedef struct typedef struct
{ {
uint16 vendor_id; /* PCI vendor ID, from pci_info */ // Device ID info.
uint16 device_id; /* PCI device ID, from pci_info */ uint16 vendorID; // PCI vendor ID, from pci_info
uint8 revision; /* PCI device revsion, from pci_info */ uint16 deviceID; // PCI device ID, from pci_info
area_id regs_area; /* Kernel's area_id for the memory mapped registers. uint8 revision; // PCI device revsion, from pci_info
It will be cloned into the accelerant's address uint32 chipset; // indicates family in which chipset belongs (a family has similar functionality)
space. */ char chipsetName[32]; // user recognizable name of chipset
area_id fb_area; /* Frame buffer's area_id. The addresses are shared
with all teams. */
void *framebuffer; /* As viewed from virtual memory */
void *framebuffer_pci; /* As viewed from the PCI bus (for DMA) */
area_id rom_area; /* Mapped ROM's area_id */
void *rom; /* As viewed from virtual memory. Shared by all teams */
area_id mode_area; /* Contains the list of display modes the driver supports */
uint32 mode_count; /* Number of display modes in the list */
sem_id vblank; /* The vertical blank semaphore. Ownership will be
transfered to the team opening the device first */
int32 flags;
int32 start_addr;
bool bAccelerantInUse; // true = accelerant has been initialized
bool bInterruptAssigned; // card has a useable interrupt assigned to it
// Memory mappings.
area_id regsArea; // area_id for the memory mapped registers. It will
// be cloned into accelerant's address space.
area_id videoMemArea; // video memory area_id. The addresses are shared with all teams.
void* videoMemAddr; // video memory addr as viewed from virtual memory
void* videoMemPCI; // video memory addr as viewed from the PCI bus (for DMA)
uint32 videoMemSize; // video memory size in bytes.
uint32 cursorOffset; // offset of cursor in video memory
uint32 frameBufferOffset; // offset of frame buffer in video memory
uint32 maxFrameBufferSize; // max available video memory for frame buffer
// List of screen modes.
area_id modeArea; // Contains the list of display modes the driver supports
uint32 modeCount; // Number of display modes in the list
// Vertical blank semaphore.
sem_id vblank; // vertical blank semaphore; if < 0, there is no semaphore
// Ownership will be transfered to team opening device first
// Flags used by driver.
int32 flags;
// Cursor info.
struct struct
{ {
uint8* data; /* Pointer into the frame buffer to where the uint16 hot_x; // Cursor hot spot. The top left corner of the cursor
cursor data starts */ uint16 hot_y; // is 0,0
uint16 hot_x; /* Cursor hot spot. The top left corner of the cursor */ uint16 x; // The location of the cursor hot spot on the
uint16 hot_y; /* is 0,0 */ uint16 y; // display (or desktop?)
uint16 x; /* The location of the cursor hot spot on the */ uint16 width; // Width and height of the cursor shape
uint16 y; /* display (or desktop?) */
uint16 width; /* Width and height of the cursor shape */
uint16 height; uint16 height;
bool is_visible; /* Is the cursor currently displayed? */ bool bIsVisible; // Is the cursor currently displayed?
} cursor; } cursor;
uint16 first_color;
uint16 color_count; display_mode dm; // current display mode configuration
bigtime_t refresh_period; /* Duration of one frame (ie 1/refresh rate) */ int bitsPerPixel; // bits per pixel of current display mode
bigtime_t blank_period; /* Duration of the blanking period. These are
usefull when faking vertical blanking frame_buffer_config fbc; // frame buffer addresses and bytes_per_row
interrupts. */
uint8 color_data[3 * 256]; /* */ // Acceleration engine.
uint8 cursor0[64*64/8]; /* AND mask for a 64x64 cursor */
uint8 cursor1[512]; /* XOR mask for a 64x64 cursor */
display_mode dm; /* current display mode configuration */
frame_buffer_config
fbc; /* bytes_per_row and start of frame buffer */
struct struct
{ {
uint64 count; /* last fifo slot used */ uint64 count; // last fifo slot used
uint64 last_idle; /* last fifo slot we *know* the engine was idle after */ uint64 lastIdle; // last fifo slot we *know* the engine was idle after
benaphore lock; /* for serializing access to the acceleration engine */ benaphore lock; // for serializing access to the acceleration engine
} engine; } engine;
uint32 pix_clk_max8; /* The maximum speed the pixel clock should run */ int mclk;
uint32 pix_clk_max16; /* at for a given pixel width. Usually a function */ uint32 pix_clk_max8; // The maximum speed the pixel clock should run
uint32 pix_clk_max32; /* of memory and DAC bandwidths. */ uint32 pix_clk_max16; // at for a given pixel width. Usually a function
uint32 mem_size; /* Frame buffer memory, in bytes. */ uint32 pix_clk_max32; // of memory and DAC bandwidths.
} shared_info;
/* Read or write a value in PCI configuration space */ // Command Overflow Buffer (COB) parameters.
bool bDisableCOB; // enable/disable COB for Savage 4 & ProSavage
uint32 cobIndex; // size index
uint32 cobSize; // size in bytes
uint32 cobOffset; // offset in video memory
uint32 bciThresholdLo; // low and high thresholds for
uint32 bciThresholdHi; // shadow status update (32bit words)
BMPDESC GlobalBD; // Bitmap Descriptor for BCI
int panelX; // LCD panel width
int panelY; // LCD panel height
int frameX0; // viewport position
int frameY0;
// The various Savage wait handlers.
bool (*WaitQueue)(int);
bool (*WaitIdleEmpty)();
SavageMonitorType displayType;
} SharedInfo;
// Read or write a value in PCI configuration space
typedef struct typedef struct
{ {
uint32 magic; /* magic number to make sure the caller groks us */ uint32 magic; // magic number to make sure the caller groks us
uint32 offset; /* Offset to read/write */ uint32 offset; // Offset to read/write
uint32 size; /* Number of bytes to transfer */ uint32 size; // Number of bytes to transfer
uint32 value; /* The value read or written */ uint32 value; // The value read or written
} savage_get_set_pci; } SavageGetSetPci;
/* Set some boolean condition (like enabling or disabling interrupts) */
// Set some boolean condition (like enabling or disabling interrupts)
typedef struct typedef struct
{ {
uint32 magic; /* magic number to make sure the caller groks us */ uint32 magic; // magic number to make sure the caller groks us
bool do_it; /* state to set */ bool bEnable; // state to set
} savage_set_bool_state; } SavageSetBoolState;
/* Retrieve the area_id of the kernel/accelerant shared info */
// Retrieve the area_id of the kernel/accelerant shared info
typedef struct typedef struct
{ {
uint32 magic; /* magic number to make sure the caller groks us */ uint32 magic; // magic number to make sure the caller groks us
area_id shared_info_area; /* area_id containing the shared information */ area_id sharedInfoArea; // ID of area containing shared information
} savage_get_private_data; } SavageGetPrivateData;
/* 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) */ // 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 typedef struct
{ {
uint32 magic; /* magic number to make sure the caller groks us */ uint32 magic; // magic number to make sure the caller groks us
char *name; /* The name of the device, less the /dev root */ char *name; // The name of the device, less the /dev root
} savage_device_name; } SavageDeviceName;
enum
{
SAVAGE_WAIT_FOR_VBLANK = (0 << 0)
};
enum
{
/* Savage3D series */
PCI_PID_SAVAGE3D = 0x8a20, /* Savage3D */
PCI_PID_SAVAGE3DMV = 0x8a21, /* Savage3D/MV */
PCI_PID_SAVAGEMXMV = 0x8c10, /* Savage/MX-MV */
PCI_PID_SAVAGEMX = 0x8c11, /* Savage/MX */
PCI_PID_SAVAGEIXMV = 0x8c12, /* Savage/IX-MV */
PCI_PID_SAVAGEIX = 0x8c13, /* Savage/IX */
/* Savage4 series */
PCI_PID_SAVAGE4_2 = 0x8a22, /* Savage4 */
PCI_PID_SAVAGE4_3 = 0x8a23, /* Savage4 */
PCI_PID_SAVAGE2000 = 0x9102, /* Savage2000 */
PCI_PID_PM133 = 0x8a25, /* ProSavage PM133 */
PCI_PID_KM133 = 0x8a26, /* ProSavage KM133 */
PCI_PID_PN133 = 0x8d01, /* ProSavage PN133, 86C380 [ProSavageDDR K4M266] */
PCI_PID_KN133 = 0x8d02, /* ProSavage KN133/TwisterK AGP4X VT8636A */
PCI_PID_KM266 = 0x8d04, /* ProSavage8 KM266/KL266 VT8375 */
PCI_PID_PN266 = 0x8d03, /* VT8751 [ProSavageDDR P4M266] */
/* SuperSavage series (unsupported) */
PCI_PID_SUPERSAVAGE_MX128 = 0x8c22, /* SuperSavage MX/128 */
PCI_PID_SUPERSAVAGE_MX64 = 0x8c24, /* SuperSavage MX/64 */
PCI_PID_SUPERSAVAGE_MX64C = 0x8c26, /* SuperSavage MX/64C */
PCI_PID_SUPERSAVAGE_IX128_SDR = 0x8c2a, /* SuperSavage IX/128 SDR */
PCI_PID_SUPERSAVAGE_IX128_DDR = 0x8c2b, /* SuperSavage IX/128 DDR */
PCI_PID_SUPERSAVAGE_IX64_SDR = 0x8c2c, /* SuperSavage IX/64 SDR */
PCI_PID_SUPERSAVAGE_IX64_DDR = 0x8c2d, /* SuperSavage IX/64 DDR */
PCI_PID_SUPERSAVAGE_IXC_SDR = 0x8c2e, /* SuperSavage IX/C SDR */
PCI_PID_SUPERSAVAGE_IXC_DDR = 0x8c2f, /* SuperSavage IX/C DDR */
};
#define isSavage4Family(p) \
((p) == PCI_PID_SAVAGE4_2 || \
(p) == PCI_PID_SAVAGE4_3 || \
(p) == PCI_PID_SAVAGE2000 || \
(p) == PCI_PID_PM133 || \
(p) == PCI_PID_KM133 || \
(p) == PCI_PID_PN133 || \
(p) == PCI_PID_KN133 || \
(p) == PCI_PID_KM266)
#if defined(__cplusplus) #if defined(__cplusplus)
@@ -2,13 +2,12 @@
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
*/ */
#ifndef GENERIC_H
#define GENERIC_H
#ifndef ACCELERANT_PROTOTYPES_H
#define ACCELERANT_PROTOTYPES_H
#include <Accelerant.h> #include <Accelerant.h>
status_t INIT_ACCELERANT(int fd); status_t INIT_ACCELERANT(int fd);
ssize_t ACCELERANT_CLONE_INFO_SIZE(void); ssize_t ACCELERANT_CLONE_INFO_SIZE(void);
void GET_ACCELERANT_CLONE_INFO(void *data); void GET_ACCELERANT_CLONE_INFO(void *data);
@@ -49,4 +48,9 @@ void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count);
void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count); void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count);
// Prototype for other functions that are called from source files
// other than where they are defined.
status_t create_mode_list(void);
#endif #endif
+149 -88
View File
@@ -1,121 +1,182 @@
/* /*
* Copyright 1999 Erdi Chen Haiku S3 Savage driver adapted from the X.org Savage driver.
*/
Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
Copyright (c) 2003-2006, X.Org Foundation
Copyright 2007 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2006-2007
*/
#include "GlobalData.h" #include "GlobalData.h"
#include "generic.h" #include "AccelerantPrototypes.h"
#include "s3accel.h" #include "savage.h"
#include "s3mmio.h"
void void
SCREEN_TO_SCREEN_BLIT ( FILL_RECTANGLE (engine_token *et, uint32 color, fill_rect_params *pList, uint32 count)
engine_token *et, blit_params *list, uint32 count)
{ {
s3accel_wait_for_fifo (1); int cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
UpdateGEReg16 (FRGD_MIX, 0x0067); | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_SOLID | BCI_CMD_SEND_COLOR;
while (count--) (void)et; // avoid compiler warning for unused arg
{
int cmd = 0xc0b1;
int src_x = list->src_left;
int src_y = list->src_top;
int dest_x = list->dest_left;
int dest_y = list->dest_top;
int width = list->width;
int height = list->height;
if (src_x < dest_x) // TRACE(("FILL_RECTANGLE, color: %X count: %d\n", color, count));
{
src_x += width; dest_x += width; BCI_CMD_SET_ROP(cmd, 0xCC); // use GXcopy for rop
cmd ^=32;
while (count--) {
int x = pList->left;
int y = pList->top;
int w = pList->right - x + 1;
int h = pList->bottom - y + 1;
BCI_GET_PTR;
si->WaitQueue(7);
BCI_SEND(cmd);
BCI_SEND(si->GlobalBD.bd2.LoPart);
BCI_SEND(si->GlobalBD.bd2.HiPart);
BCI_SEND(color);
BCI_SEND(BCI_X_Y(x, y));
BCI_SEND(BCI_W_H(w, h));
pList++;
} }
if (src_y < dest_y)
{
src_y += height; dest_y += height;
cmd ^=128;
}
UpdateGEReg (ALT_CURXY, (src_x<<16)|src_y);
UpdateGEReg (ALT_STEP, (dest_x<<16)|dest_y);
UpdateGEReg (ALT_PCNT, (width<<16)|height);
UpdateGEReg (CMD, cmd);
list ++;
}
s3accel_wait_for_fifo (3);
UpdateGEReg16 (FRGD_MIX, 0x0027);
} }
void void
FILL_RECTANGLE ( FILL_SPAN(engine_token *et, uint32 color, uint16 *pList, uint32 count)
engine_token *et, uint32 color, fill_rect_params *list, uint32 count)
{ {
s3accel_wait_for_fifo (1); int cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
UpdateGEReg (FRGD_COLOR, color); | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_SOLID | BCI_CMD_SEND_COLOR;
UpdateGEReg16 (FRGD_MIX, 0x0027);
while (count--) (void)et; // avoid compiler warning for unused arg
{
int x = list->left;
int y = list->top;
int w = list->right - x;
int h = list->bottom - y;
s3accel_wait_for_fifo (2); // TRACE(("FILL_SPAN, count: %d\n", count));
UpdateGEReg (ALT_CURXY, (x<<16)|y);
UpdateGEReg (ALT_PCNT, (w<<16)|h);
UpdateGEReg (CMD, 0x000040b1);
list++; BCI_CMD_SET_ROP(cmd, 0xCC); // use GXcopy for rop
while (count--) {
int y = *pList++;
int x = *pList++;
int w = *pList++ - x + 1;
BCI_GET_PTR;
// The MediaPlayer in Zeta 1.21 displays a window which has 2 zero width
// spans which the Savage chips display as a line completely across the
// screen; thus, the following if statement discards any span with zero
// or negative width.
if (w <= 0)
continue;
si->WaitQueue(7);
BCI_SEND(cmd);
BCI_SEND(si->GlobalBD.bd2.LoPart);
BCI_SEND(si->GlobalBD.bd2.HiPart);
BCI_SEND(color);
BCI_SEND(BCI_X_Y(x, y));
BCI_SEND(BCI_W_H(w, 1));
} }
s3accel_wait_for_fifo(3);
} }
void void
INVERT_RECTANGLE ( INVERT_RECTANGLE(engine_token *et, fill_rect_params *pList, uint32 count)
engine_token *et, fill_rect_params *list, uint32 count)
{ {
s3accel_wait_for_fifo (1); int cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
UpdateGEReg16 (FRGD_MIX, 0x0020); | BCI_CMD_DEST_PBD_NEW;
while (count--) (void)et; // avoid compiler warning for unused arg
{
int x = list->left;
int y = list->top;
int w = list->right - x;
int h = list->bottom - y;
s3accel_wait_for_fifo (2); // TRACE(("INVERT_RECTANGLE, count: %d\n", count));
UpdateGEReg (ALT_CURXY, (x<<16)|y);
UpdateGEReg (ALT_PCNT, (w<<16)|h);
UpdateGEReg (CMD, 0x000040b1);
list++; BCI_CMD_SET_ROP(cmd, 0x55); // use GXinvert for rop
while (count--) {
int x = pList->left;
int y = pList->top;
int w = pList->right - x + 1;
int h = pList->bottom - y + 1;
BCI_GET_PTR;
si->WaitQueue(7);
BCI_SEND(cmd);
BCI_SEND(si->GlobalBD.bd2.LoPart);
BCI_SEND(si->GlobalBD.bd2.HiPart);
BCI_SEND(BCI_X_Y(x, y));
BCI_SEND(BCI_W_H(w, h));
pList++;
} }
s3accel_wait_for_fifo (3);
UpdateGEReg16 (FRGD_MIX, 0x0027);
} }
void void
FILL_SPAN ( SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *pList, uint32 count)
engine_token *et, uint32 color, uint16 *list, uint32 count)
{ {
s3accel_wait_for_fifo (1); // TRACE(("SCREEN_TO_SCREEN_BLIT\n"));
UpdateGEReg (FRGD_COLOR, color);
UpdateGEReg16 (FRGD_MIX, 0x0027);
while (count--) (void)et; // avoid compiler warning for unused arg
{
int y = *list ++;
int x = *list ++;
int w = *list - x; list ++;
s3accel_wait_for_fifo (2); while (count--) {
UpdateGEReg (ALT_CURXY, (x<<16)|y); int cmd;
UpdateGEReg (ALT_PCNT, (w<<16)|1); int src_x = pList->src_left;
UpdateGEReg (CMD, 0x000040b1); int src_y = pList->src_top;
int dest_x = pList->dest_left;
int dest_y = pList->dest_top;
int width = pList->width;
int height = pList->height;
BCI_GET_PTR;
cmd = BCI_CMD_RECT | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_SBD_COLOR_NEW;
BCI_CMD_SET_ROP(cmd, 0xCC); // use GXcopy for rop
if (dest_x <= src_x) {
cmd |= BCI_CMD_RECT_XP;
} else {
src_x += width;
dest_x += width;
}
if (dest_y <= src_y) {
cmd |= BCI_CMD_RECT_YP;
} else {
src_y += height;
dest_y += height;
}
si->WaitQueue(9);
BCI_SEND(cmd);
BCI_SEND(si->GlobalBD.bd2.LoPart);
BCI_SEND(si->GlobalBD.bd2.HiPart);
BCI_SEND(si->GlobalBD.bd2.LoPart);
BCI_SEND(si->GlobalBD.bd2.HiPart);
BCI_SEND(BCI_X_Y(src_x, src_y));
BCI_SEND(BCI_X_Y(dest_x, dest_y));
BCI_SEND(BCI_W_H(width + 1, height + 1));
pList ++;
} }
} }
+40 -63
View File
@@ -1,45 +1,35 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors:
Gerald Zajac 2006-2007
*/ */
/*
* Copyright 1999 Erdi Chen
*/
#include "GlobalData.h" #include "GlobalData.h"
#include "generic.h" #include "AccelerantPrototypes.h"
#include "s3drv.h" #include "savage.h"
void set_cursor_colors(void)
{
/* it's only called by the INIT_ACCELERANT() */
s3drv_set_cursor_color (0, ~0);
}
status_t status_t
SET_CURSOR_SHAPE ( SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y,
uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8* andMask, uint8* xorMask)
uint8 *andMask, uint8 *xorMask)
{ {
/* NOTE: Currently, for BeOS, cursor width and height must be equal to 16. */ /* NOTE: Currently, for BeOS, cursor width and height must be equal to 16. */
if ((width != 16) || (height != 16)) if ((width != 16) || (height != 16)) {
{
return B_ERROR; return B_ERROR;
} } else if ((hot_x >= width) || (hot_y >= height)) {
else if ((hot_x >= width) || (hot_y >= height))
{
return B_ERROR; return B_ERROR;
} } else {
else
{
/* Update cursor variables appropriately. */ /* Update cursor variables appropriately. */
si->cursor.width = width; si->cursor.width = width;
si->cursor.height = height; si->cursor.height = height;
si->cursor.hot_x = hot_x; si->cursor.hot_x = hot_x;
si->cursor.hot_y = hot_y; si->cursor.hot_y = hot_y;
s3drv_load_cursor ((byte_t*)framebuffer, 0,
width, height, andMask, xorMask); if (!SavageLoadCursorImage(width, height, andMask, xorMask))
return B_ERROR;
} }
return B_OK; return B_OK;
@@ -50,64 +40,51 @@ Move the cursor to the specified position on the desktop. If we're
using some kind of virtual desktop, adjust the display start position using some kind of virtual desktop, adjust the display start position
accordingly and position the cursor in the proper "virtual" location. accordingly and position the cursor in the proper "virtual" location.
*/ */
void MOVE_CURSOR (uint16 x_p, uint16 y_p) void
MOVE_CURSOR(uint16 xPos, uint16 yPos)
{ {
int x = x_p, y = y_p; int x = xPos; // use signed int's since SavageSetCursorPosition()
bool move_screen = false; int y = yPos; // needs signed int to determine if cursor off screen
/* the current horizontal starting pixel */
uint16 hds = si->dm.h_display_start;
/* the current vertical starting line */
uint16 vds = si->dm.v_display_start;
/* Need to set this value for 32 bit */ uint16 hds = si->dm.h_display_start; /* current horizontal starting pixel */
uint16 h_adjust = 3; uint16 vds = si->dm.v_display_start; /* current vertical starting line */
/* clamp cursor to virtual display */ /* clamp cursor to virtual display */
if (x >= si->dm.virtual_width) x = si->dm.virtual_width - 1; if (x >= si->dm.virtual_width)
if (y >= si->dm.virtual_height) y = si->dm.virtual_height - 1; x = si->dm.virtual_width - 1;
if (y >= si->dm.virtual_height)
y = si->dm.virtual_height - 1;
/* adjust h/v_display_start to move cursor onto screen */ /* adjust h/v display start to move cursor onto screen */
if (x >= (si->dm.timing.h_display + hds)) if (x >= (si->dm.timing.h_display + hds))
{ hds = x - si->dm.timing.h_display + 1;
hds = ((x - si->dm.timing.h_display) + 1 + h_adjust) & ~h_adjust;
move_screen = true;
}
else if (x < hds) else if (x < hds)
{ hds = x;
hds = x & ~h_adjust;
move_screen = true;
}
if (y >= (si->dm.timing.v_display + vds)) if (y >= (si->dm.timing.v_display + vds))
{
vds = y - si->dm.timing.v_display + 1; vds = y - si->dm.timing.v_display + 1;
move_screen = true;
}
else if (y < vds) else if (y < vds)
{
vds = y; vds = y;
move_screen = true;
}
/* reposition the desktop on the display if required */ /* reposition the desktop on the display if required */
if (move_screen) MOVE_DISPLAY(hds,vds); if (hds != si->dm.h_display_start || vds != si->dm.v_display_start)
MOVE_DISPLAY(hds, vds);
/* put cursor in correct physical position */ /* put cursor in correct physical position */
x -= hds; x -= (hds + si->cursor.hot_x);
y -= vds; y -= (vds + si->cursor.hot_y);
x -= si->cursor.hot_x;
y -= si->cursor.hot_y;
/* position the cursor on the display */ /* position the cursor on the display */
s3drv_move_cursor (x, y); SavageSetCursorPosition(x, y);
} }
void SHOW_CURSOR (bool is_visible)
void
SHOW_CURSOR(bool bShow)
{ {
if (is_visible) if (bShow)
s3drv_show_cursor (); SavageShowCursor();
else else
s3drv_hide_cursor (); SavageHideCursor();
/* record for our info */
si->cursor.is_visible = is_visible;
} }
@@ -1,70 +1,80 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors:
Gerald Zajac 2006-2007
*/ */
/*
* Copyright 1999 Erdi Chen
*/
#include "GlobalData.h" #include "GlobalData.h"
#include "generic.h" #include "AccelerantPrototypes.h"
#include "s3drv.h"
static engine_token savage_engine_token = { 1, B_2D_ACCELERATION, NULL }; static engine_token savage_engine_token = { 1, B_2D_ACCELERATION, NULL };
uint32 ACCELERANT_ENGINE_COUNT(void)
uint32
ACCELERANT_ENGINE_COUNT(void)
{ {
return 1; return 1;
} }
status_t status_t
ACQUIRE_ENGINE ( ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait,
uint32 capabilities, uint32 max_wait,
sync_token *st, engine_token **et) sync_token *st, engine_token **et)
{ {
(void)capabilities; // avoid compiler warning for unused arg
(void)max_wait; // avoid compiler warning for unused arg
/* acquire the shared benaphore */ /* acquire the shared benaphore */
AQUIRE_BEN(si->engine.lock) AQUIRE_BEN(si->engine.lock)
/* sync if required */ /* sync if required */
if (st) SYNC_TO_TOKEN(st); if (st)
SYNC_TO_TOKEN(st);
/* return an engine token */ /* return an engine token */
*et = &savage_engine_token; *et = &savage_engine_token;
return B_OK; return B_OK;
} }
status_t RELEASE_ENGINE (engine_token *et, sync_token *st)
status_t
RELEASE_ENGINE(engine_token *et, sync_token *st)
{ {
/* update the sync token, if any */ /* update the sync token, if any */
if (st) if (st)
{ GET_SYNC_TOKEN(et, st);
st->engine_id = et->engine_id;
st->counter = si->engine.count;
}
/* release the shared benaphore */ /* release the shared benaphore */
RELEASE_BEN(si->engine.lock) RELEASE_BEN(si->engine.lock)
return B_OK; return B_OK;
} }
void WAIT_ENGINE_IDLE(void)
void
WAIT_ENGINE_IDLE(void)
{ {
s3drv_wait_for_idle (); si->WaitIdleEmpty(); // wait until engine is completely idle
// note our current possition
si->engine.last_idle = si->engine.count;
} }
status_t GET_SYNC_TOKEN(engine_token *et, sync_token *st)
status_t
GET_SYNC_TOKEN(engine_token *et, sync_token *st)
{ {
/* engine count will always be zero: we don't support syncing to token (yet) */
st->engine_id = et->engine_id; st->engine_id = et->engine_id;
st->counter = si->engine.count; st->counter = si->engine.count;
return B_OK; return B_OK;
} }
status_t SYNC_TO_TOKEN(sync_token *st)
status_t
SYNC_TO_TOKEN(sync_token *st)
{ {
s3drv_wait_for_idle (); (void)st; // avoid compiler warning for unused arg
si->engine.last_idle = st->counter;
WAIT_ENGINE_IDLE();
return B_OK; return B_OK;
} }
@@ -1,12 +1,12 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
*/
/*
* Copyright 1999 Erdi Chen
*/
#include "generic.h" Other authors:
Gerald Zajac 2006-2007
*/
#include "AccelerantPrototypes.h"
/* /*
@@ -19,20 +19,24 @@ is available. Any extra information available to choose the function will be
noted on a case by case below. noted on a case by case below.
*/ */
void * get_accelerant_hook(uint32 feature, void *data) { void *
get_accelerant_hook(uint32 feature, void *data)
{
(void)data; // avoid compiler warning for unused arg
switch (feature) { switch (feature) {
/* /*
These definitions are out of pure lazyness. These definitions are out of pure lazyness.
*/ */
#define HOOK(x) case B_##x: return (void *)x #define HOOK(x) case B_##x: return (void *)x
#define ZERO(x) case B_##x: return (void *)0 #define ZERO(x) case B_##x: return (void *)0
/* /*
One of either B_INIT_ACCELERANT or B_CLONE_ACCELERANT will be requested and 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 subsequently called before any other hook is requested. All other feature
hook selections can be predicated on variables assigned during the accelerant hook selections can be predicated on variables assigned during the accelerant
initialization process. initialization process.
*/ */
/* initialization */ /* initialization */
HOOK(INIT_ACCELERANT); HOOK(INIT_ACCELERANT);
HOOK(CLONE_ACCELERANT); HOOK(CLONE_ACCELERANT);
@@ -53,7 +57,7 @@ initialization process.
HOOK(GET_PIXEL_CLOCK_LIMITS); HOOK(GET_PIXEL_CLOCK_LIMITS);
HOOK(MOVE_DISPLAY); HOOK(MOVE_DISPLAY);
HOOK(SET_INDEXED_COLORS); HOOK(SET_INDEXED_COLORS);
HOOK(GET_TIMING_CONSTRAINTS); //HOOK(GET_TIMING_CONSTRAINTS);
HOOK(DPMS_CAPABILITIES); HOOK(DPMS_CAPABILITIES);
HOOK(DPMS_MODE); HOOK(DPMS_MODE);
@@ -72,13 +76,13 @@ initialization process.
HOOK(GET_SYNC_TOKEN); HOOK(GET_SYNC_TOKEN);
HOOK(SYNC_TO_TOKEN); HOOK(SYNC_TO_TOKEN);
/* /*
When requesting an acceleration hook, the calling application provides a When requesting an acceleration hook, the calling application provides a
pointer to the display_mode for which the acceleration function will be used. pointer to the display_mode for which the acceleration function will be used.
Depending on the engine architecture, you may choose to provide a different Depending on the engine architecture, you may choose to provide a different
function to be used with each bit-depth. In the sample driver we return function to be used with each bit-depth. In the sample driver we return
the same function all the time. the same function all the time.
*/ */
/* 2D acceleration */ /* 2D acceleration */
HOOK(SCREEN_TO_SCREEN_BLIT); HOOK(SCREEN_TO_SCREEN_BLIT);
HOOK(FILL_RECTANGLE); HOOK(FILL_RECTANGLE);
@@ -86,9 +90,11 @@ the same function all the time.
HOOK(FILL_SPAN); HOOK(FILL_SPAN);
#undef HOOK #undef HOOK
#undef ZERO #undef ZERO
} }
/* /*
Return a null pointer for any feature we don't understand. Return a null pointer for any feature we don't understand.
*/ */
return 0; return 0;
} }
@@ -0,0 +1,28 @@
/*
Copyright 2007 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2007
*/
#include "AccelerantPrototypes.h"
#include "GlobalData.h"
#include <string.h>
// Get info about the device.
status_t
GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi)
{
adi->version = 1;
strcpy(adi->name, "S3 Savage chipset");
strcpy(adi->chipset, si->chipsetName);
strcpy(adi->serial_no, "unknown");
adi->memory = si->videoMemSize;
adi->dac_speed = 250;
return B_OK;
}
+38 -44
View File
@@ -1,96 +1,90 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors:
Gerald Zajac 2006-2007
*/ */
/*
* Copyright 1999 Erdi Chen
*/
#include "GlobalData.h" #include "GlobalData.h"
#include "generic.h" #include "AccelerantPrototypes.h"
/* /*
Return the current display mode. The only time you might return an Return the current display mode. The only time you might return an
error is if a mode hasn't been set. error is if a mode hasn't been set.
*/ */
status_t GET_DISPLAY_MODE (display_mode *current_mode) status_t
GET_DISPLAY_MODE (display_mode *current_mode)
{ {
/* easy for us, we return the last mode we set */ /* easy for us, we return the last mode we set */
*current_mode = si->dm; *current_mode = si->dm;
return B_OK; return B_OK;
} }
/* /*
Return the frame buffer configuration information. Return the frame buffer configuration information.
*/ */
status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *afb) status_t
GET_FRAME_BUFFER_CONFIG(frame_buffer_config *pFBC)
{ {
/* easy again, as the last mode set stored the info in a convienient form */ // TRACE(("GET_FRAME_BUFFER_CONFIG called\n"));
*afb = si->fbc;
*pFBC = si->fbc;
return B_OK; return B_OK;
} }
/* /*
Return the maximum and minium pixel clock limits for the specified mode. Return the maximum and minium pixel clock limits for the specified mode.
*/ */
status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high) status_t
GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high)
{ {
/* /*
Note that we're not making any guarantees about the ability of the attached 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 display to handle pixel clocks within the limits we return. A future monitor
capablilities database will post-process this information. capablilities database will post-process this information.
*/ */
uint32 total_pix = (uint32)dm->timing.h_total * (uint32)dm->timing.v_total; uint32 total_pix = (uint32)dm->timing.h_total * (uint32)dm->timing.v_total;
uint32 clock_limit; uint32 clock_limit;
/* max pixel clock is pixel depth dependant */ /* max pixel clock is pixel depth dependant */
switch (dm->space & ~0x3000) switch (dm->space & ~0x3000) {
{ case B_RGB32:
case B_RGB32: clock_limit = si->pix_clk_max32; break; clock_limit = si->pix_clk_max32;
break;
case B_RGB15: case B_RGB15:
case B_RGB16: clock_limit = si->pix_clk_max16; break; case B_RGB16:
case B_CMAP8: clock_limit = si->pix_clk_max8; break; clock_limit = si->pix_clk_max16;
break;
case B_CMAP8:
clock_limit = si->pix_clk_max8;
break;
default: default:
clock_limit = 0; clock_limit = 0;
} }
/* lower limit of about 48Hz vertical refresh */ /* lower limit of about 48Hz vertical refresh */
*low = (total_pix * 48L) / 1000L; *low = (total_pix * 48L) / 1000L;
if (*low > clock_limit) return B_ERROR; if (*low > clock_limit)
return B_ERROR;
*high = clock_limit; *high = clock_limit;
return B_OK; return B_OK;
} }
status_t GET_TIMING_CONSTRAINTS(display_timing_constraints *dtc)
{
status_t retval;
dtc->h_res = 8;
dtc->h_sync_min = 2*8;
dtc->h_sync_max = 32*8 - 1;
dtc->h_blank_min = 0;
dtc->h_blank_max = 64*8 - 1;
dtc->v_res = 1;
dtc->v_sync_min = 2;
dtc->v_sync_max = 15;
dtc->v_blank_min = 0;
dtc->v_blank_max = 255;
retval = B_OK;
return retval;
}
/* /*
Return the semaphore id that will be used to signal a vertical retrace Return the semaphore id that will be used to signal a vertical retrace
occured. occured.
*/ */
sem_id ACCELERANT_RETRACE_SEMAPHORE(void) sem_id
ACCELERANT_RETRACE_SEMAPHORE(void)
{ {
/* // TRACE(("ACCELERANT_RETRACE_SEMAPHORE() called\n"));
NOTE:
The kernel driver created this for us. We don't know if the system is // if (si->bInterruptAssigned && si->vblank >= 0)
using real interrupts, or if we're faking it, and we don't care. // return si->vblank;
If we choose not to support this at all, we'd just return B_ERROR here, // else
and the user wouldn't get any kind of vertical retrace support. return B_ERROR;
*/
return si->vblank;
} }
+11 -25
View File
@@ -1,33 +1,19 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors:
Gerald Zajac 2006-2007
*/ */
/*
* Copyright 1999 Erdi Chen
*/
#include "GlobalData.h" #include "GlobalData.h"
#include <stdarg.h>
#include <stdio.h>
#include <sys/ioctl.h>
int fd; int driverFileDesc;
shared_info *si; SharedInfo* si;
area_id shared_info_area; area_id sharedInfoArea;
vuint32 *regs; uint8* regs;
area_id regs_area; area_id regsArea;
vuint32 *framebuffer; display_mode* modeList;
area_id fb_area; area_id modeListArea;
display_mode *my_mode_list; bool bAccelerantIsClone;
area_id my_mode_list_area;
int accelerantIsClone;
void dpf (const char * format, ...)
{
char buffer[4096] = "SAVAGE: ";
va_list args;
va_start (args, format);
vsprintf (buffer + 8, format, args);
ioctl (fd, SAVAGE_DPRINTF, buffer, 0);
va_end (args);
}
+19 -19
View File
@@ -1,32 +1,32 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors:
Gerald Zajac 2006-2007
*/ */
#ifndef GLOBALDATA_H #ifndef GLOBALDATA_H
#define GLOBALDATA_H #define GLOBALDATA_H
#include "DriverInterface.h" #include "DriverInterface.h"
extern int driverFileDesc; // file descriptor of kernel driver
extern SharedInfo* si; // address of info shared between accelerants
extern area_id sharedInfoArea; // shared info area ID
extern uint8* regs; // base address of MMIO register area
extern area_id regsArea; // MMIO register area ID
extern display_mode* modeList; // list of standard display modes
extern area_id modeListArea; // mode list area ID
extern bool bAccelerantIsClone;// true if this is a cloned accelerant
extern int fd;
extern shared_info *si;
extern area_id shared_info_area;
extern vuint32 *regs;
extern area_id regs_area;
extern vuint32 *framebuffer;
extern area_id fb_area;
extern display_mode *my_mode_list;
extern area_id my_mode_list_area;
extern int accelerantIsClone;
/* Print debug message through kernel driver. Should move to other location later. */ void TraceLog(const char* fmt, ...);
extern void dpf (const char * format, ...);
/* ProposeDisplayMode.c */
extern status_t create_mode_list(void);
/* Cursor.c */
extern void set_cursor_colors(void);
#ifdef DEBUG
#define TRACE(a) TraceLog a
#else
#define TRACE(a)
#endif #endif
#endif // GLOBALDATA_H
+116 -311
View File
@@ -1,19 +1,18 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors:
Gerald Zajac 2006-2007
*/ */
/*
* Copyright 1999 Erdi Chen
*/
#include "GlobalData.h" #include "GlobalData.h"
#include "generic.h" #include "AccelerantPrototypes.h"
#include "s3drv.h" #include "savage.h"
#include "s3mmio.h"
#include "s3accel.h"
#include "errno.h" #include "errno.h"
#include "fcntl.h" #include "fcntl.h"
#include "stdio.h"
#include "string.h" #include "string.h"
#include "unistd.h" #include "unistd.h"
#include "sys/types.h" #include "sys/types.h"
@@ -21,241 +20,98 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
/*!
Get the linear address of an area. Workaround for BeOS bug that
returns invalid pointer from clone_area.
*/
static void *
get_area_address(area_id area)
{
area_info ai;
get_area_info(area, &ai);
return ai.address;
}
#if 0
// unused!
// Determines the amount of card memory available by seeing how far up
// the frame buffer data can be written and read back reliably. Does a
// paranoia check to make sure that it isn't just wrapping, either.
unsigned long
Get_Card_Mem_Size()
{
// Allowed sizes actually go up to 16 megs, but clip at the
// register window for now.
const unsigned long AllowedSizes[] =
{ 0x00080000, 0x00100000, 0x00180000, 0x00200000,
0x00280000, 0x00300000, 0x00380000, 0x00400000,
0x00500000, 0x00600000, 0x00700000, 0x007FF800,
0x0 };
unsigned long MaxMem;
unsigned long RWIndex;
int iMaxIndex, iTestIndex, iX;
unsigned long LTemp;
int IsOk;
uint32 *VramBase;
VramBase = (uint32 *)framebuffer;
MaxMem = 0; // Default.
IsOk = 1;
// Step through ever-larger memory sizes, recording size if passes test and
// ignoring otherwise.
for (iMaxIndex = 0; (AllowedSizes[iMaxIndex] != 0) && IsOk; iMaxIndex++)
{
// Write test values to the linear aperature.
// Only need to do this for the farthest location, as previous
// locations already have been written to in previous passes.
RWIndex = AllowedSizes[iMaxIndex];
RWIndex = (RWIndex - 16384) >> 2;
for (iX = 0; iX < 4096; iX++)
{
LTemp = RWIndex;
// Hash LTemp. As the parameters for the hash are prime, it should
// be extremely unlikely to get these values through a glitch, and
// the pattern only repeats at prime intervals, so aliasing
// shouldn't fool the test either.
LTemp = (263 * (LTemp % 65521) + 29) % 65521;
// Extend this to 32 bits.
LTemp |= (LTemp ^ 0x0000FFFFul) << 16;
VramBase[RWIndex] = LTemp;
RWIndex++;
}
// Verify that all test patterns are still intact. If values written
// past the end of memory drop off the face of the frame buffer, the
// farthest pattern(s) will not be what they should be. If values
// written past the end of memory wrap, then previous patterns will
// be overwritten (or partly overwritten, as the test location at
// 8 megs is actually at 8 megs - 2k).
// As soon as an invalid value is detected, IsOk is set to 0, which
// should quickly terminate the test loops.
for (iTestIndex = 0; (iTestIndex <= iMaxIndex) && IsOk; iTestIndex++)
{
RWIndex = AllowedSizes[iTestIndex];
RWIndex = (RWIndex - 16384) >> 2;
for (iX = 0; (iX < 4096) && IsOk; iX++)
{
LTemp = RWIndex;
// Hash LTemp. As the parameters for the hash are prime, it
// should be extremely unlikely to get these values through
// a glitch, and the pattern only repeats at prime intervals,
// so aliasing shouldn't fool the test either.
LTemp = (263 * (LTemp % 65521) + 29) % 65521;
// Extend this to 32 bits.
LTemp |= (LTemp ^ 0x0000FFFFul) << 16;
// Test against the value read from the frame buffer.
if (VramBase[RWIndex] != LTemp)
IsOk = 0;
RWIndex++;
}
}
// If the test patterns check out, update MaxMem accordingly.
if (IsOk)
MaxMem = AllowedSizes[iMaxIndex];
}
return MaxMem;
}
#endif
/* Initialization code shared between primary and cloned accelerants */ /* Initialization code shared between primary and cloned accelerants */
static status_t static status_t
init_common(int the_fd) init_common(int the_fd)
{ {
status_t result; status_t result;
savage_get_private_data gpd; SavageGetPrivateData gpd;
/* memorize the file descriptor */ /* memorize the file descriptor */
fd = the_fd; driverFileDesc = the_fd;
dpf ("init_common begin\n");
/* set the magic number so the driver knows we're for real */ /* set the magic number so the driver knows we're for real */
gpd.magic = SAVAGE_PRIVATE_DATA_MAGIC; gpd.magic = SAVAGE_PRIVATE_DATA_MAGIC;
/* contact driver and get a pointer to the registers and shared data */ /* contact driver and get a pointer to the registers and shared data */
if (ioctl(fd, SAVAGE_GET_PRIVATE_DATA, &gpd, sizeof(gpd)) != 0) result = ioctl(driverFileDesc, SAVAGE_GET_PRIVATE_DATA, &gpd, sizeof(gpd));
return errno; if (result != B_OK)
goto error0;
/* clone the shared area for our use */ /* clone the shared area for our use */
shared_info_area = clone_area("SAVAGE shared info", (void **)&si, sharedInfoArea = clone_area("SAVAGE shared info", (void**)&si, B_ANY_ADDRESS,
B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gpd.shared_info_area); B_READ_AREA | B_WRITE_AREA, gpd.sharedInfoArea);
if (shared_info_area < 0) if (sharedInfoArea < 0) {
return shared_info_area; result = sharedInfoArea;
goto error0;
}
/* clone the memory mapped registers for our use */ /* clone the memory mapped registers for our use */
regs_area = clone_area("SAVAGE regs area", (void **)&regs, B_ANY_ADDRESS, regsArea = clone_area("SAVAGE regs area", (void**)&regs, B_ANY_ADDRESS,
B_READ_AREA | B_WRITE_AREA, si->regs_area); B_READ_AREA | B_WRITE_AREA, si->regsArea);
if (regs_area < 0) { if (regsArea < 0) {
result = regs_area; result = regsArea;
goto error1; goto error1;
} }
regs = get_area_address(regs_area);
dpf("PCI VENDOR_ID = 0x%4X, DEVICE_ID = 0x%4X\n",
read16((byte_t*)regs + 0x8000),
read16((byte_t*)regs + 0x8002));
/* clone the framebuffer buffer for our use */
fb_area = clone_area("SAVAGE fb area", (void **)&framebuffer,
B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, si->fb_area);
if (fb_area < 0) {
result = regs_area;
goto error2;
}
framebuffer = get_area_address(fb_area);
s3drv_init((byte_t*)regs);
dpf ("s3drv_init called\n");
s3accel_init(s3drv_get_context());
dpf ("s3accel_init called\n");
s3drv_unlock_regs();
/* all done */ /* all done */
return B_OK; goto error0;
error2:
delete_area(regs_area);
error1: error1:
delete_area(shared_info_area); delete_area(sharedInfoArea);
error0:
return result; return result;
} }
/*! Clean up code shared between primary and cloned accelerants */ /* Clean up code shared between primary and cloned accelrants */
static void static void
uninit_common(void) uninit_common(void)
{ {
/* release framebuffer area */
delete_area (fb_area);
/* release the memory mapped registers */ /* release the memory mapped registers */
delete_area(regs_area); delete_area(regsArea);
/* a little cheap paranoia */
regs = 0; regs = 0;
/* release our copy of the shared info from the kernel driver */ /* release our copy of the shared info from the kernel driver */
delete_area(shared_info_area); delete_area(sharedInfoArea);
/* more cheap paranoia */
si = 0; si = 0;
} }
/*! /*
Initialize the accelerant. the_fd is the file handle of the device (in 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). /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. 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 If they are, get the accelerant ready to handle other hook functions and
report success or failure. report success or failure.
*/ */
status_t status_t
INIT_ACCELERANT(int the_fd) INIT_ACCELERANT(int the_fd)
{ {
status_t result; status_t result;
/* note that we're the primary accelerant (accelerantIsClone is global) */
accelerantIsClone = 0; TRACE(("Enter INIT_ACCELERANT\n"));
/* note that we're the primary accelerant (bAccelerantIsClone is global) */
bAccelerantIsClone = false;
/* do the initialization common to both the primary and the clones */ /* do the initialization common to both the primary and the clones */
result = init_common(the_fd); result = init_common(the_fd);
if (result != B_OK) if (result != B_OK)
goto error0; goto error0; // common initialization failed
/* TRACE(("Vendor ID: 0x%X, Device ID: 0x%X\n", si->vendorID, si->deviceID));
If there is a possiblity that the kernel driver will recognize a card that
the accelerant can't support, you should check for that here. Perhaps some
odd memory configuration or some such.
*/
/* /* ensure that INIT_ACCELERANT is executed just once (copies should be clones) */
This is a good place to go and initialize your card. The details are so if (si->bAccelerantInUse) {
device specific, we're not even going to pretend to provide you with sample result = B_NOT_ALLOWED;
code. If this fails, we'll have to bail out, cleaning up the resources goto error1;
we've already allocated.
*/
/* call the device specific init code */
{
SVGAMode orig, newmode;
PixelTiming timing =
{ 0, { 640, 656, 752, 800, 0 }, { 480, 490, 492, 525, 0 } };
s3drv_unlock_regs ();
s3drv_get_mode (&timing, 32, (byte_t*)&newmode, sizeof (newmode));
s3drv_save_mode ((byte_t*)&orig, sizeof (orig));
s3drv_restore_mode ((byte_t*)&newmode, sizeof (newmode), 1);
s3accel_init (s3drv_get_context ());
//si->mem_size = s3drv_detect_vram_mb_size ((byte_t*)framebuffer, 32);
//dpf ("si->mem_size = %dMB\n", si->mem_size);
si->mem_size = s3drv_detect_vram_mb_size (NULL, 2);
dpf ("si->mem_size = %dMB\n", si->mem_size);
si->mem_size *= 1024*1024;
s3drv_restore_mode ((byte_t*)&orig, sizeof (orig), 1);
s3drv_lock_regs ();
} }
si->pix_clk_max8 = 250000; /* call the device specific init code */
si->pix_clk_max16 = 250000;
si->pix_clk_max32 = 250000;
/* bail out if it failed */ if (!SavagePreInit())
if (result != B_OK) goto error1; goto error1;
/* /*
Now would be a good time to figure out what video modes your card supports. Now would be a good time to figure out what video modes your card supports.
@@ -266,69 +122,39 @@ INIT_ACCELERANT(int the_fd)
*/ */
result = create_mode_list(); result = create_mode_list();
if (result != B_OK) if (result != B_OK)
goto error2; goto error1;
/* /* Initialize the cursor information */
Initialize the frame buffer and cursor pointers. Most newer video cards
have integrated the DAC into the graphics engine, and so the cursor shape
is stored in the frame buffer RAM. Also, newer cards tend not to have as
many restrictions about the placement of the start of the frame buffer in
frame buffer RAM. If you're supporting an older card with frame buffer
positioning restrictions, or one without an integrated DAC, you'll have to
change this accordingly.
*/
/*
Put the cursor at the start of the frame buffer. The typical 64x64 4 color
(black, white, transparent, inverse) takes up 1024 bytes of RAM.
*/
si->cursor.data = (uint8 *)si->framebuffer;
/* Initialize the rest of the cursor information while we're here */
si->cursor.width = 0; si->cursor.width = 0;
si->cursor.height = 0; si->cursor.height = 0;
si->cursor.hot_x = 0; si->cursor.hot_x = 0;
si->cursor.hot_y = 0; si->cursor.hot_y = 0;
si->cursor.x = 0; si->cursor.x = 0;
si->cursor.y = 0; si->cursor.y = 0;
/*
Put the frame buffer immediately following the cursor data. We store this si->fbc.frame_buffer = (void *)((addr_t)si->videoMemAddr + si->frameBufferOffset);
info in a frame_buffer_config structure to make it convienient to return si->fbc.frame_buffer_dma = (void *)((addr_t)si->videoMemPCI + si->frameBufferOffset);
to the app_server later.
*/
si->fbc.frame_buffer = (void *)(((char *)si->framebuffer) + 1024);
si->fbc.frame_buffer_dma = (void *)(((char *)si->framebuffer_pci) + 1024);
si->start_addr = 1024;
/* init the shared semaphore */ /* init the shared semaphore */
INIT_BEN(si->engine.lock); INIT_BEN(si->engine.lock);
/* initialize the engine synchronization variables */ /* initialize the engine synchronization variables */
/* count of issued parameters or commands */ /* count of issued parameters or commands */
si->engine.last_idle = si->engine.count = 0; si->engine.lastIdle = si->engine.count = 0;
/* bail out if something failed */
if (result != B_OK) goto error3;
/* set the cursor colors. You may or may not have to do this, depending /* set the cursor colors. You may or may not have to do this, depending
on the device. */ on the device. */
set_cursor_colors(); SavageSetCursorColors(~0, 0);
/* ensure cursor state */ /* ensure cursor state */
SHOW_CURSOR(false); SHOW_CURSOR(false);
/* a winner! */
/* ensure that INIT_ACCELERANT won't be executed again (copies should be clones) */
si->bAccelerantInUse = true;
result = B_OK; result = B_OK;
goto error0; 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: error1:
/* /*
Initialization failed after init_common() succeeded, so we need to clean Initialization failed after init_common() succeeded, so we need to clean
@@ -337,13 +163,14 @@ error1:
uninit_common(); uninit_common();
error0: error0:
TRACE(("Exit INIT_ACCELERANT, result: 0x%X\n", result));
return result; return result;
} }
/*! /*
Return the number of bytes required to hold the information required Return the number of bytes required to hold the information required
to clone the device. to clone the device.
*/ */
ssize_t ssize_t
ACCELERANT_CLONE_INFO_SIZE(void) ACCELERANT_CLONE_INFO_SIZE(void)
@@ -352,69 +179,78 @@ ACCELERANT_CLONE_INFO_SIZE(void)
Since we're passing the name of the device as the only required Since we're passing the name of the device as the only required
info, return the size of the name buffer info, return the size of the name buffer
*/ */
return MAX_SAVAGE_DEVICE_NAME_LENGTH; return B_OS_NAME_LENGTH;
} }
/*! /*
Return the info required to clone the device. void *data points to Return the info required to clone the device. void* data points to
a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length. a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length.
*/ */
void void
GET_ACCELERANT_CLONE_INFO(void *data) GET_ACCELERANT_CLONE_INFO(void* data)
{ {
savage_device_name dn; SavageDeviceName dn;
status_t result; status_t result;
/* call the kernel driver to get the device name */ /* call the kernel driver to get the device name */
dn.magic = SAVAGE_PRIVATE_DATA_MAGIC; dn.magic = SAVAGE_PRIVATE_DATA_MAGIC;
/* store the returned info directly into the passed buffer */ /* store the returned info directly into the passed buffer */
dn.name = (char *)data; dn.name = (char*)data;
result = ioctl(fd, SAVAGE_DEVICE_NAME, &dn, sizeof(dn)); result = ioctl(driverFileDesc, SAVAGE_DEVICE_NAME, &dn, sizeof(dn));
} }
/*
/*! Initialize a copy of the accelerant as a clone. void* data points to
Initialize a copy of the accelerant as a clone. void *data points to a copy of the data returned by GET_ACCELERANT_CLONE_INFO().
a copy of the data returned by GET_ACCELERANT_CLONE_INFO().
*/ */
status_t status_t
CLONE_ACCELERANT(void *data) CLONE_ACCELERANT(void* data)
{ {
status_t result; status_t result;
char path[MAXPATHLEN]; char path[MAXPATHLEN];
/* the data is the device name */ /* the data is the device name */
strcpy(path, "/dev/"); strcpy(path, "/dev/");
strcat(path, (const char *)data); strcat(path, (const char*)data);
/* open the device, the permissions aren't important */ /* open the device, the permissions aren't important */
fd = open(path, B_READ_WRITE); driverFileDesc = open(path, B_READ_WRITE);
if (fd < 0) if (driverFileDesc < 0)
return errno; return errno;
/* note that we're a clone accelerant */ /* note that we're a clone accelerant */
accelerantIsClone = 1; bAccelerantIsClone = true;
/* call the shared initialization code */ /* call the shared initialization code */
result = init_common(fd); result = init_common(driverFileDesc);
/* bail out if the common initialization failed */
if (result != B_OK) if (result != B_OK)
goto error1; goto error1;
/* get shared area for display modes */ /* get shared area for display modes */
result = my_mode_list_area = clone_area("SAVAGE cloned display_modes", result = modeListArea = clone_area(
(void **)&my_mode_list, B_ANY_ADDRESS, B_READ_AREA, si->mode_area); "SAVAGE cloned display_modes",
(void**) &modeList,
B_ANY_ADDRESS,
B_READ_AREA,
si->modeArea
);
if (result < B_OK) if (result < B_OK)
goto error2; goto error2;
/* all done */ /* all done */
return B_OK; result = B_OK;
goto error0;
error2: error2:
/* free up the areas we cloned */ /* free up the areas we cloned */
uninit_common(); uninit_common();
error1: error1:
/* close the device we opened */ /* close the device we opened */
close(fd); close(driverFileDesc);
error0:
return result; return result;
} }
@@ -423,62 +259,31 @@ void
UNINIT_ACCELERANT(void) UNINIT_ACCELERANT(void)
{ {
/* free our mode list area */ /* free our mode list area */
delete_area(my_mode_list_area); delete_area(modeListArea);
/* paranoia */ modeList = 0;
my_mode_list = 0;
/* release our cloned data */ /* release our cloned data */
uninit_common(); uninit_common();
/* close the file handle ONLY if we're the clone */ /* close file handle ONLY if we're the clone */
if (accelerantIsClone) if (bAccelerantIsClone)
close(fd); close(driverFileDesc);
} }
status_t
GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi) // Kernel function dprintf() is not available in user space; however,
// _sPrintf performs the same function in user space but is undefined
// in the OS header files. Thus, it is defined here.
void _sPrintf(const char *format, ...);
void
TraceLog(const char* fmt, ...)
{ {
status_t retval; char string[1024];
static const char * names1[] = va_list args;
{ "Savage3D", "Savage3D/MV", "Savage4", "Savage4",
"Savage4", "ProSavage PM133", "ProSavage KM133" };
static const char * names2[] =
{ "Savage/MX-MV", "Savage/MX", "Savage/IX-MV", "Savage/IX" };
static const char * names3[] =
{ "ProSavage PN133", "ProSavage KN133", "ProSavage P4M266", "ProSavage8 KM266" };
adi->version = 0x10000; strcpy(string, "savage: ");
if (si->device_id == PCI_PID_SAVAGE2000) { va_start(args, fmt);
strcpy (adi->name, "Savage2000"); vsprintf(&string[strlen(string)], fmt, args);
strcpy (adi->chipset, "Savage2000"); _sPrintf(string);
} else {
const char ** names = NULL;
int offset = 0;
switch (si->device_id & 0xFFF0) {
case 0x8a20:
names = names1;
offset = si->device_id - PCI_PID_SAVAGE3D;
break;
case 0x8c10:
names = names2;
offset = si->device_id - PCI_PID_SAVAGEMXMV;
break;
case 0x8d00:
names = names3;
offset = si->device_id - PCI_PID_PN133;
break;
}
if (names != NULL) {
strcpy (adi->name, names[offset]);
strcpy (adi->chipset, names[offset]);
} else {
strcpy (adi->name, "not supported");
strcpy (adi->chipset, "Savage");
}
}
strcpy (adi->serial_no, "0");
adi->memory = si->mem_size;
adi->dac_speed = 250;
retval = B_OK;
return retval;
} }
+5 -3
View File
@@ -10,15 +10,17 @@ Addon s3savage.accelerant :
Cursor.c Cursor.c
EngineManagement.c EngineManagement.c
GetAccelerantHook.c GetAccelerantHook.c
GetDeviceInfo.c
GetModeInfo.c GetModeInfo.c
GlobalData.c GlobalData.c
InitAccelerant.c InitAccelerant.c
ProposeDisplayMode.c ProposeDisplayMode.c
SetDisplayMode.c SetDisplayMode.c
s3accel.c savage_accel.c
s3drv.c savage_cursor.c
s3vga.c savage_dpms.c
savage_driver.c
: be : be
; ;
@@ -1,81 +1,103 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors:
Gerald Zajac 2006-2007
*/ */
/*
* Copyright 1999 Erdi Chen
*/
#include "GlobalData.h" #include "GlobalData.h"
#include "generic.h" #include "AccelerantPrototypes.h"
#include <string.h>
#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC) #define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
#define MODE_FLAGS (B_SCROLL|B_8_BIT_DAC|B_HARDWARE_CURSOR|B_PARALLEL_ACCESS) #define MODE_FLAGS (B_SCROLL | B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS)
#define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode)) #define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode))
static const display_mode mode_list[] = { static const display_mode mode_list[] = {
{ { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */ { { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */
{ { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */ { { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */
{ { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */ { { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */
{ { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */ { { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */
{ { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */ { { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */
{ { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */ { { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */
{ { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */
{ { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */ { { 36000, 800, 824, 896, 1024, 600, 601, 603, 625, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@56Hz_(800X600) */
{ { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */ { { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */
{ { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(800X600X8.Z1) */ { { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */
{ { 56250, 800, 832, 896, 1048, 600, 601, 604, 631, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */ { { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */
{ { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */ { { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(800X600X8.Z1) */
{ { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(1024X768X8.Z1) */ { { 56250, 800, 832, 896, 1048, 600, 601, 604, 631, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */
{ { 78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */
{ { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */ { { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */
{ { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */ { { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(1024X768X8.Z1) */
{ { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */ { { 78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */
{ { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */ { { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */
{ { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */
{ { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */ { { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */
{ { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */ { { 97800, 1152, 1216, 1344, 1552, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */
{ { 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */ { { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */
{ { 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */ { { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */
{ { 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */
{ { 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */ { { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */
{ { 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */ { { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */
{ { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */ { { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */
{ { 122600, 1400, 1488, 1640, 1880, 1050, 1051, 1054, 1087, T_POSITIVE_SYNC}, B_CMAP8, 1400, 1050, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1400X1050) */
{ { 155800, 1400, 1464, 1784, 1912, 1050, 1052, 1064, 1090, T_POSITIVE_SYNC}, B_CMAP8, 1400, 1050, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1400X1050) */
{ { 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */
{ { 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */
{ { 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */
{ { 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */
{ { 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */
{ { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */
{ { 204750, 1792, 1920, 2120, 2448, 1344, 1345, 1348, 1394, B_POSITIVE_VSYNC}, B_CMAP8, 1792, 1344, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1792X1344) */
{ { 261000, 1792, 1888, 2104, 2456, 1344, 1345, 1348, 1417, B_POSITIVE_VSYNC}, B_CMAP8, 1792, 1344, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1792X1344) */
{ { 218250, 1856, 1952, 2176, 2528, 1392, 1393, 1396, 1439, B_POSITIVE_VSYNC}, B_CMAP8, 1856, 1392, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1856X1392) */
{ { 288000, 1856, 1984, 2208, 2560, 1392, 1393, 1396, 1500, B_POSITIVE_VSYNC}, B_CMAP8, 1856, 1392, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1856X1392) */
{ { 234000, 1920, 2048, 2256, 2600, 1440, 1441, 1444, 1500, B_POSITIVE_VSYNC}, B_CMAP8, 1920, 1440, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1920X1440) */
{ { 297000, 1920, 2064, 2288, 2640, 1440, 1441, 1444, 1500, B_POSITIVE_VSYNC}, B_CMAP8, 1920, 1440, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1920X1440) */
{ { 341350, 1920, 2072, 2288, 2656, 1440, 1441, 1444, 1512, B_POSITIVE_VSYNC}, B_CMAP8, 1920, 1440, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1920X1440) */
{ { 266950, 2048, 2200, 2424, 2800, 1536, 1537, 1540, 1589, B_POSITIVE_VSYNC}, B_CMAP8, 2048, 1536, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(2048x1536) */
{ { 340480, 2048, 2216, 2440, 2832, 1536, 1537, 1540, 1603, B_POSITIVE_VSYNC}, B_CMAP8, 2048, 1536, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(2048x1536) */
{ { 388040, 2048, 2216, 2440, 2832, 1536, 1537, 1540, 1612, B_POSITIVE_VSYNC}, B_CMAP8, 2048, 1536, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(2048x1536) */
}; };
/* create a mask of one "bits" bits wide */ /* create a mask of one "bits" bits wide */
#define MASKFROMWIDTH(bits) ((1 << bits) - 1) #define MASKFROMWIDTH(bits) ((1 << bits) - 1)
/*! /*
Validate a target display mode is both Validate a target display mode is both
a) a valid display mode for this device and a) a valid display mode for this device and
b) falls between the contraints imposed by "low" and "high" 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. Return values:
If a valid mode can be constructed, but it does not fall within the limits, B_ERROR - mode is not (or cannot) be made valid for this device.
return B_BAD_VALUE. B_BAD_VALUE - valid mode can be constructed, but it is not within limits.
If the mode is both valid AND falls within the limits, return B_OK. B_OK - mode is both valid AND is within the limits.
*/ */
status_t status_t
PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high)
const display_mode *high)
{ {
//const uint16 h_display_bits = MASKFROMWIDTH(8);
const uint16 h_sync_bits = MASKFROMWIDTH(5); const uint16 h_sync_bits = MASKFROMWIDTH(5);
const uint16 h_total_bits = MASKFROMWIDTH(9); const uint16 h_total_bits = MASKFROMWIDTH(9);
const uint16 v_display_bits = MASKFROMWIDTH(11); const uint16 v_display_bits = MASKFROMWIDTH(11);
const uint16 v_sync_bits = MASKFROMWIDTH(5); const uint16 v_sync_bits = MASKFROMWIDTH(5);
//const uint16 v_total_bits = MASKFROMWIDTH(11);
status_t result = B_OK; status_t result = B_OK;
uint32 row_bytes, limit_clock; uint32 row_bytes, limit_clock;
double target_refresh = ((double)target->timing.pixel_clock * 1000.0) double target_refresh = ((double)target->timing.pixel_clock * 1000.0)
/ ((double)target->timing.h_total / ((double)target->timing.h_total
* (double)target->timing.v_total); * (double)target->timing.v_total);
bool want_same_width = target->timing.h_display == target->virtual_width; bool want_same_width = (target->timing.h_display == target->virtual_width);
bool want_same_height = target->timing.v_display == target->virtual_height; bool want_same_height = (target->timing.v_display == target->virtual_height);
/* /*
NOTE: NOTE:
@@ -96,6 +118,9 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
This code doesn't explicitly support interlaced video modes. This code doesn't explicitly support interlaced video modes.
*/ */
// TRACE(("ProposeDisplayMode; clock = %d, width = %d, height = %d\n",
// target->timing.pixel_clock, target->virtual_width, target->virtual_height));
/* validate horizontal timings */ /* validate horizontal timings */
{ {
/* for most devices, horizontal parameters must be multiples of 8 */ /* for most devices, horizontal parameters must be multiples of 8 */
@@ -104,7 +129,7 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
uint16 h_sync_end = target->timing.h_sync_end >> 3; uint16 h_sync_end = target->timing.h_sync_end >> 3;
uint16 h_total = target->timing.h_total >> 3; uint16 h_total = target->timing.h_total >> 3;
/* ensure reasonable minium display and sequential order of parms */ /* ensure reasonable minimum display and sequential order of parms */
if (h_display < (320 >> 3)) if (h_display < (320 >> 3))
h_display = 320 >> 3; h_display = 320 >> 3;
if (h_display > (2048 >> 3)) if (h_display > (2048 >> 3))
@@ -115,7 +140,6 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
h_sync_end = h_sync_start + 3; /*(0x001f >> 2);*/ h_sync_end = h_sync_start + 3; /*(0x001f >> 2);*/
if (h_total < (h_sync_end + 1)) if (h_total < (h_sync_end + 1))
h_total = h_sync_end + 1; h_total = h_sync_end + 1;
/* adjust for register limitations: */ /* adjust for register limitations: */
/* h_total is 9 bits */ /* h_total is 9 bits */
if (h_total > h_total_bits) if (h_total > h_total_bits)
@@ -134,16 +158,17 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
} }
/* did we fall out of one of the limits? */ /* did we fall out of one of the limits? */
if (target->timing.h_display < low->timing.h_display if ((target->timing.h_display < low->timing.h_display)
|| target->timing.h_display > high->timing.h_display || (target->timing.h_display > high->timing.h_display)
|| target->timing.h_sync_start < low->timing.h_sync_start || (target->timing.h_sync_start < low->timing.h_sync_start)
|| target->timing.h_sync_start > high->timing.h_sync_start || (target->timing.h_sync_start > high->timing.h_sync_start)
|| target->timing.h_sync_end < low->timing.h_sync_end || (target->timing.h_sync_end < low->timing.h_sync_end)
|| target->timing.h_sync_end > high->timing.h_sync_end || (target->timing.h_sync_end > high->timing.h_sync_end)
|| target->timing.h_total < low->timing.h_total || (target->timing.h_total < low->timing.h_total)
|| target->timing.h_total > high->timing.h_total) || (target->timing.h_total > high->timing.h_total))
result = B_BAD_VALUE; result = B_BAD_VALUE;
/* validate vertical timings */ /* validate vertical timings */
{ {
uint16 v_display = target->timing.v_display; uint16 v_display = target->timing.v_display;
@@ -166,7 +191,6 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
v_sync_end = v_sync_start + 3; v_sync_end = v_sync_start + 3;
if (v_total < (v_sync_end + 1)) if (v_total < (v_sync_end + 1))
v_total = v_sync_end + 1; v_total = v_sync_end + 1;
/* adjust for register limitations */ /* adjust for register limitations */
if ((v_sync_end - v_sync_start) > v_sync_bits) if ((v_sync_end - v_sync_start) > v_sync_bits)
v_sync_end = v_sync_start + v_sync_bits; v_sync_end = v_sync_start + v_sync_bits;
@@ -178,16 +202,26 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
} }
/* did we fall out of one of the limits? */ /* did we fall out of one of the limits? */
if (target->timing.v_display < low->timing.v_display if ((target->timing.v_display < low->timing.v_display)
|| target->timing.v_display > high->timing.v_display || (target->timing.v_display > high->timing.v_display)
|| target->timing.v_sync_start < low->timing.v_sync_start || (target->timing.v_sync_start < low->timing.v_sync_start)
|| target->timing.v_sync_start > high->timing.h_sync_start || (target->timing.v_sync_start > high->timing.h_sync_start)
|| target->timing.v_sync_end < low->timing.v_sync_end || (target->timing.v_sync_end < low->timing.v_sync_end)
|| target->timing.v_sync_end > high->timing.v_sync_end || (target->timing.v_sync_end > high->timing.v_sync_end)
|| target->timing.v_total < low->timing.v_total || (target->timing.v_total < low->timing.v_total)
|| target->timing.v_total > high->timing.v_total) || (target->timing.v_total > high->timing.v_total))
result = B_BAD_VALUE; result = B_BAD_VALUE;
// If the video is connected directly to an LCD display (ie, notebook
// computer), restrict the display mode to the resolution of the LCD
// display.
if (MT_LCD == si->displayType && si->panelX > 0 && si->panelY > 0 &&
(target->timing.h_display != si->panelX
|| target->timing.v_display != si->panelY)) {
return B_ERROR;
}
/* adjust pixel clock for DAC limits and target refresh rate */ /* adjust pixel clock for DAC limits and target refresh rate */
/* /*
We're re-calcuating the pixel_clock here because we might have We're re-calcuating the pixel_clock here because we might have
@@ -233,70 +267,55 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
but I'm lazy */ but I'm lazy */
/* note if we fell outside the limits */ /* note if we fell outside the limits */
if (target->timing.pixel_clock < low->timing.pixel_clock if ((target->timing.pixel_clock < low->timing.pixel_clock)
|| target->timing.pixel_clock > high->timing.pixel_clock) || (target->timing.pixel_clock > high->timing.pixel_clock))
result = B_BAD_VALUE; result = B_BAD_VALUE;
/* validate display vs. virtual */ /* validate display vs. virtual */
if (target->timing.h_display > target->virtual_width || want_same_width) if ((target->timing.h_display > target->virtual_width) || want_same_width)
target->virtual_width = target->timing.h_display; target->virtual_width = target->timing.h_display;
if (target->timing.v_display > target->virtual_height || want_same_height) if ((target->timing.v_display > target->virtual_height) || want_same_height)
target->virtual_height = target->timing.v_display; target->virtual_height = target->timing.v_display;
if (target->virtual_width > 2048) if (target->virtual_width > 2048)
target->virtual_width = 2048; target->virtual_width = 2048;
/* adjust virtual width for engine limitations */ /* adjust virtual width for engine limitations */
target->virtual_width = (target->virtual_width + 7) & ~7; target->virtual_width = (target->virtual_width + 7) & ~7;
if (target->virtual_width < low->virtual_width if ( (target->virtual_width < low->virtual_width)
|| target->virtual_width > high->virtual_width) || (target->virtual_width > high->virtual_width))
result = B_BAD_VALUE; result = B_BAD_VALUE;
/* calculate rowbytes after we've nailed the virtual width */ /* calculate rowbytes after we've nailed the virtual width */
row_bytes *= target->virtual_width; row_bytes *= target->virtual_width;
/* memory requirement for frame buffer */ /* memory requirement for frame buffer */
if ((row_bytes * target->virtual_height) > si->mem_size) if ((row_bytes * target->virtual_height) > si->maxFrameBufferSize)
target->virtual_height = si->mem_size / row_bytes; target->virtual_height = si->maxFrameBufferSize / row_bytes;
if (target->virtual_height > 2048) if (target->virtual_height > 2048)
target->virtual_height = 2048; target->virtual_height = 2048;
if (target->virtual_height < target->timing.v_display) { if (target->virtual_height < target->timing.v_display)
/* not enough frame buffer memory for the mode */ /* not enough frame buffer memory for the mode */
return B_ERROR; return B_ERROR;
} else if (target->virtual_height < low->virtual_height else if ((target->virtual_height < low->virtual_height)
|| target->virtual_height > high->virtual_height) || (target->virtual_height > high->virtual_height))
result = B_BAD_VALUE; result = B_BAD_VALUE;
/*
Bit Flag Encoding
The way the bit flags works is as follows:
low high meaning
--- ---- -------
0 0 Feature must NOT be enabled
0 1 Feature MAY be enabled, prefered enabled
1 0 Feature MAY be enabled, prefered disabled
1 1 Feature MUST be enabled
*/
/* MORE WORK REQUIRED HERE. Current drivers mostly ignore the flags */
return result; return result;
} }
/*
/*!
Return the number of modes this device will return from GET_MODE_LIST(). Return the number of modes this device will return from GET_MODE_LIST().
*/ */
uint32 uint32
ACCELERANT_MODE_COUNT(void) ACCELERANT_MODE_COUNT(void)
{ {
/* return the number of 'built-in' display modes */ /* return the number of 'built-in' display modes */
return si->mode_count; return si->modeCount;
} }
/*
/*!
Copy the list of guaranteed supported video modes to the location Copy the list of guaranteed supported video modes to the location
provided. provided.
*/ */
@@ -304,19 +323,20 @@ status_t
GET_MODE_LIST(display_mode *dm) GET_MODE_LIST(display_mode *dm)
{ {
/* copy them to the buffer pointed at by *dm */ /* copy them to the buffer pointed at by *dm */
memcpy(dm, my_mode_list, si->mode_count * sizeof(display_mode)); memcpy(dm, modeList, si->modeCount * sizeof(display_mode));
return B_OK; return B_OK;
} }
/*! /*
Create a list of display_modes to pass back to the caller. Create a list of display_modes to pass back to the caller.
*/ */
status_t status_t
create_mode_list(void) create_mode_list(void)
{ {
size_t max_size; size_t max_size;
uint32 i, j, pix_clk_range; uint32 i;
uint32 pix_clk_range;
const display_mode *src; const display_mode *src;
display_mode *dst, low, high; display_mode *dst, low, high;
@@ -327,55 +347,49 @@ create_mode_list(void)
allow the user to choose which one to use. allow the user to choose which one to use.
*/ */
#if defined(__INTEL__) #if defined(__INTEL__)
color_space spaces[] = color_space colorSpaces[] = { B_CMAP8, B_RGB16_LITTLE, B_RGB32_LITTLE };
// {B_CMAP8, B_RGB15_LITTLE, B_RGB16_LITTLE, B_RGB32_LITTLE};
{B_CMAP8, B_RGB16_LITTLE, B_RGB32_LITTLE};
#else #else
color_space spaces[] = color_space colorSpaces[] = { B_CMAP8, B_RGB16_BIG, B_RGB32_BIG };
// {B_CMAP8, B_RGB15_BIG, B_RGB16_BIG, B_RGB32_BIG};
{B_CMAP8, B_RGB16_BIG, B_RGB32_BIG};
#endif #endif
int numColorSpaces = sizeof(colorSpaces) / sizeof(colorSpaces[0]);
/* figure out how big the list could be, and adjust up to nearest /* figure out how big the list could be, and adjust up to nearest
multiple of B_PAGE_SIZE */ multiple of B_PAGE_SIZE */
max_size = (((MODE_COUNT * sizeof (spaces) / sizeof (color_space)) max_size = ((MODE_COUNT * numColorSpaces * sizeof(display_mode))
* sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1); + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1);
/* create an area to hold the info */ /* create an area to hold the info */
si->mode_area = my_mode_list_area = si->modeArea = modeListArea = create_area("SAVAGE accelerant mode info",
create_area("SAVAGE accelerant mode info", (void **)&my_mode_list, (void **) &modeList, B_ANY_ADDRESS, max_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
B_ANY_ADDRESS, max_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); if (modeListArea < B_OK)
if (my_mode_list_area < B_OK) return modeListArea;
return my_mode_list_area;
/* walk through our predefined list and see which modes fit this device */ /* walk through our predefined list and see which modes fit this device */
src = mode_list; src = mode_list;
dst = my_mode_list; dst = modeList;
si->mode_count = 0; si->modeCount = 0;
for (i = 0; i < MODE_COUNT; i++) { for (i = 0; i < MODE_COUNT; i++) {
int j;
/* set ranges for acceptable values */ /* set ranges for acceptable values */
low = high = *src; low = high = *src;
/* Expand range of default clock by 3.1% on each end: arbitrarily picked */
/* range is 6.25% of default clock: arbitrarily picked */ pix_clk_range = low.timing.pixel_clock >> 5; // divide by 32 to get ~3.1%
pix_clk_range = low.timing.pixel_clock >> 5;
low.timing.pixel_clock -= pix_clk_range; low.timing.pixel_clock -= pix_clk_range;
high.timing.pixel_clock += pix_clk_range; high.timing.pixel_clock += pix_clk_range;
/* some cards need wider virtual widths for certain modes */
high.virtual_width = 2048;
/* do it once for each depth we want to support */ /* do it once for each depth we want to support */
for (j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++) { for (j = 0; j < numColorSpaces; j++) {
/* set target values */ /* set target values */
*dst = *src; *dst = *src;
/* poke the specific space */ /* poke the specific space */
dst->space = low.space = high.space = spaces[j]; dst->space = low.space = high.space = colorSpaces[j];
if (spaces[j] != B_CMAP8)
dst->flags &= ~B_8_BIT_DAC;
/* ask for a compatible mode */ /* ask for a compatible mode */
if (1 || PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) { if (PROPOSE_DISPLAY_MODE(dst, &low, &high) == B_OK) {
/* count it, and move on to next mode */ /* count it, and move on to next mode */
dst++; dst++;
si->mode_count++; si->modeCount++;
} }
} }
/* advance to next mode */ /* advance to next mode */
@@ -384,3 +398,4 @@ create_mode_list(void)
return B_OK; return B_OK;
} }
+87 -192
View File
@@ -1,142 +1,137 @@
/* /*
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors:
Gerald Zajac 2006-2007
*/ */
/*
* Copyright 1999 Erdi Chen
*/
#include "GlobalData.h" #include "GlobalData.h"
#include "generic.h" #include "AccelerantPrototypes.h"
#include "s3drv.h" #include "savage.h"
#include "s3accel.h"
#include "s3mmio.h"
#include <stdio.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <stdio.h>
/* /*
Enable/Disable interrupts. Just a wrapper around the Enable/Disable interrupts. Just a wrapper around the
ioctl() to the kernel driver. ioctl() to the kernel driver.
*/ */
static void interrupt_enable(bool flag) static void
interrupt_enable(bool bEnable)
{ {
status_t result; status_t result;
savage_set_bool_state sbs; SavageSetBoolState sbs;
if (si->bInterruptAssigned) {
/* set the magic number so the driver knows we're for real */ /* set the magic number so the driver knows we're for real */
sbs.magic = SAVAGE_PRIVATE_DATA_MAGIC; sbs.magic = SAVAGE_PRIVATE_DATA_MAGIC;
sbs.do_it = flag; sbs.bEnable = bEnable;
/* contact driver and get a pointer to the registers and shared data */ /* contact driver and get a pointer to the registers and shared data */
result = ioctl(fd, SAVAGE_RUN_INTERRUPTS, &sbs, sizeof(sbs)); result = ioctl(driverFileDesc, SAVAGE_RUN_INTERRUPTS, &sbs, sizeof(sbs));
}
} }
/* /*
Calculates the number of bits for a given color_space. Calculates the number of bits for a given color_space.
Usefull for mode setup routines, etc. Usefull for mode setup routines, etc.
*/ */
static uint32 calcBitsPerPixel(uint32 cs) static uint32
CalcBitsPerPixel(uint32 cs)
{ {
uint32 bpp = 0; uint32 bpp = 0;
switch (cs) switch (cs) {
{
case B_RGB32_BIG: case B_RGB32_BIG:
case B_RGBA32_BIG: case B_RGBA32_BIG:
case B_RGB32_LITTLE: case B_RGB32_LITTLE:
case B_RGBA32_LITTLE: case B_RGBA32_LITTLE:
bpp = 32; break; bpp = 32;
break;
case B_RGB24_BIG: case B_RGB24_BIG:
case B_RGB24_LITTLE: case B_RGB24_LITTLE:
bpp = 24; break; bpp = 24;
break;
case B_RGB16_BIG: case B_RGB16_BIG:
case B_RGB16_LITTLE: case B_RGB16_LITTLE:
bpp = 16; break; bpp = 16;
break;
case B_RGB15_BIG: case B_RGB15_BIG:
case B_RGBA15_BIG: case B_RGBA15_BIG:
case B_RGB15_LITTLE: case B_RGB15_LITTLE:
case B_RGBA15_LITTLE: case B_RGBA15_LITTLE:
bpp = 15; break; bpp = 15;
break;
case B_CMAP8: case B_CMAP8:
bpp = 8; break; bpp = 8;
break;
} }
return bpp; return bpp;
} }
/* /*
The code to actually configure the display. The code to actually configure the display.
Do all of the error checking in PROPOSE_DISPLAY_MODE(), Do all of the error checking in PROPOSE_DISPLAY_MODE(),
and just assume that the values I get here are acceptable. and just assume that the values I get here are acceptable.
*/ */
static void do_set_display_mode(display_mode *dm) static void
SetDisplayMode(display_mode* dm)
{ {
uint bpp; // The code to actually configure the display.
SVGAMode s3mode; // All the error checking must be done in PROPOSE_DISPLAY_MODE(),
PixelTiming timing; // and assume that the mode values we get here are acceptable.
status_t result;
dpf ("do_set_display_mode begin\n"); uint bpp = CalcBitsPerPixel(dm->space);
/* disable interrupts using the kernel driver */ DisplayMode mode;
interrupt_enable(false);
bpp = calcBitsPerPixel (dm->space); TRACE(("SetDisplayMode begin; depth = %d, width = %d, height = %d\n",
bpp, dm->virtual_width, dm->virtual_height));
timing.dot_clock_khz = dm->timing.pixel_clock; interrupt_enable(false); // disable interrupts using kernel driver
timing.x.disp = dm->timing.h_display;
timing.x.sync_start = dm->timing.h_sync_start;
timing.x.sync_end = dm->timing.h_sync_end;
timing.x.total = dm->timing.h_total;
timing.x.polarity = (dm->timing.flags & B_POSITIVE_HSYNC) ? 1 : 0;
timing.y.disp = dm->timing.v_display;
timing.y.sync_start = dm->timing.v_sync_start;
timing.y.sync_end = dm->timing.v_sync_end;
timing.y.total = dm->timing.v_total;
timing.y.polarity = (dm->timing.flags & B_POSITIVE_VSYNC) ? 1 : 0;
dpf ("TIMING = { %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d }\n",
timing.dot_clock_khz,
timing.x.disp, timing.x.sync_start, timing.x.sync_end,
timing.x.total, timing.x.polarity,
timing.y.disp, timing.y.sync_start, timing.y.sync_end,
timing.y.total, timing.y.polarity);
s3drv_unlock_regs ();
memset (&s3mode, 0, sizeof (s3mode));
result = s3drv_get_mode (&timing, bpp, (byte_t*)&s3mode, sizeof (s3mode));
if (result > 0) dpf ("s3drv_get_mode succeeded\n");
else dpf ("s3drv_get_mode failed\n");
dpf ("depth = %d, width = %d, height = %d\n",
s3mode.pixel_size, s3mode.pixel_width, s3mode.pixel_height);
result = s3drv_restore_mode ((byte_t*)&s3mode, sizeof (s3mode), true);
if (result > 0) dpf ("s3drv_set_mode succeeded\n");
else dpf ("s3drv_set_mode failed\n");
/* enable interrupts using the kernel driver */ mode.timing = dm->timing;
interrupt_enable(true); mode.bpp = bpp;
mode.width = dm->virtual_width;
mode.bytesPerRow = dm->virtual_width * ((bpp + 7) / 8);
TRACE(("TIMING = { %d %d %d %d %d %d %d %d %d 0x%x }\n",
mode.timing.pixel_clock,
mode.timing.h_display, mode.timing.h_sync_start, mode.timing.h_sync_end,
mode.timing.h_total,
mode.timing.v_display, mode.timing.v_sync_start, mode.timing.v_sync_end,
mode.timing.v_total, mode.timing.flags));
dpf ("si->start_addr = %d\n", si->start_addr); if (SavageModeInit(&mode)) {
s3drv_set_display_start (si->start_addr); TRACE(("SavageModeInit succeeded\n"));
s3drv_set_logical_width (dm->virtual_width); } else {
si->fbc.bytes_per_row = (dm->virtual_width * bpp + 7) / 8; TRACE(("SavageModeInit failed\n"));
s3accel_init (s3drv_get_context ()); }
dpf ("s3accel_init called\n");
//s3drv_lock_regs (); interrupt_enable(true); // enable interrupts using kernel driver
dpf ("do_set_display_mode done\n");
si->fbc.bytes_per_row = dm->virtual_width * ((bpp + 7) / 8);
si->bitsPerPixel = bpp;
SavageAdjustFrame(dm->h_display_start, dm->v_display_start);
TRACE(("SetDisplayMode done\n"));
} }
/*
The exported mode setting routine. First validate the mode, status_t
then call our private routine to hammer the registers. SET_DISPLAY_MODE (display_mode* mode_to_set)
*/
status_t SET_DISPLAY_MODE (display_mode *mode_to_set)
{ {
// The exported mode setting routine. First validate the mode,
// then call our private routine to hammer the registers.
display_mode bounds, target; display_mode bounds, target;
/* ask for the specific mode */ /* ask for the specific mode */
target = bounds = *mode_to_set; target = bounds = *mode_to_set;
if (PROPOSE_DISPLAY_MODE(&target, &bounds, &bounds) == B_ERROR) if (PROPOSE_DISPLAY_MODE(&target, &bounds, &bounds) == B_ERROR)
return B_ERROR; return B_ERROR;
do_set_display_mode(&target);
SetDisplayMode(&target);
si->dm = target; si->dm = target;
return B_OK; return B_OK;
} }
@@ -146,7 +141,8 @@ status_t SET_DISPLAY_MODE (display_mode *mode_to_set)
top left corner of the display device. Used for page-flipping top left corner of the display device. Used for page-flipping
games and virtual desktops. games and virtual desktops.
*/ */
status_t MOVE_DISPLAY (uint16 h_display_start, uint16 v_display_start) status_t
MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start)
{ {
/* /*
Many devices have limitations on the granularity of the horizontal offset. Many devices have limitations on the granularity of the horizontal offset.
@@ -167,7 +163,7 @@ status_t MOVE_DISPLAY (uint16 h_display_start, uint16 v_display_start)
si->dm.v_display_start = v_display_start; si->dm.v_display_start = v_display_start;
/* actually set the registers */ /* actually set the registers */
s3drv_adjust_viewport (h_display_start, v_display_start); SavageAdjustFrame(h_display_start, v_display_start);
return B_OK; return B_OK;
} }
@@ -175,15 +171,18 @@ status_t MOVE_DISPLAY (uint16 h_display_start, uint16 v_display_start)
/* /*
Set the indexed color palette. Set the indexed color palette.
*/ */
void SET_INDEXED_COLORS ( void
uint count, uint8 first, uint8 *color_data, uint32 flags) SET_INDEXED_COLORS(uint count, uint8 first, uint8* colorData, uint32 flags)
{ {
(void)flags; // avoid compiler warning for unused arg
/* /*
Some cards use the indexed color regisers in the DAC for gamma correction. Some cards use the indexed color regisers in the DAC for gamma correction.
If this is true with your device (and it probably is), you need to protect If this is true with your device (and it probably is), you need to protect
against setting these registers when not in an indexed mode. against setting these registers when not in an indexed mode.
*/ */
if (si->dm.space != B_CMAP8) return; if (si->dm.space != B_CMAP8)
return ;
/* /*
There isn't any need to keep a copy of the data being stored, There isn't any need to keep a copy of the data being stored,
@@ -191,119 +190,15 @@ void SET_INDEXED_COLORS (
an 8bpp mode, or takes ownership of an 8bpp mode after a GameKit an 8bpp mode, or takes ownership of an 8bpp mode after a GameKit
app has used it. app has used it.
*/ */
s3drv_unlock_regs ();
write_sr ((byte_t*)regs + 0x8000, 0x1B, 0x10); OUTREG16(VGA_SEQ_INDEX, 0x101b);
while (count--)
{ while (count--) {
s3drv_set_palette ( OUTREG8(0x83c8, first++); // color index
first++, color_data[0], color_data[1], color_data[2]); OUTREG8(0x83c9, colorData[0]); // red
color_data += 3; OUTREG8(0x83c9, colorData[1]); // green
OUTREG8(0x83c9, colorData[2]); // blue
colorData += 3;
} }
s3drv_lock_regs ();
} }
/* masks for DPMS control bits */
enum
{
H_SYNC_OFF = 0x01,
V_SYNC_OFF = 0x02,
DISPLAY_OFF = 0x04,
BITSMASK = H_SYNC_OFF | V_SYNC_OFF | DISPLAY_OFF
};
/*
Put the display into one of the Display Power Management modes.
*/
status_t SET_DPMS_MODE(uint32 dpms_flags)
{
uint32 LTemp;
/*
The register containing the horizontal and vertical sync control bits
usually contains other control bits, so do a read-modify-write.
*/
/* FIXME - read the bits */
LTemp = *regs;
/* this mask is device dependant */
LTemp &= ~BITSMASK; /* clear all disable bits (including display disable) */
/* now pick one of the DPMS configurations */
switch(dpms_flags)
{
case B_DPMS_ON: /* H: on, V: on */
/* do nothing, bits already clear */
/* usually, but it may be different for your device */
break;
case B_DPMS_STAND_BY: /* H: off, V: on, display off */
LTemp |= H_SYNC_OFF | DISPLAY_OFF;
break;
case B_DPMS_SUSPEND: /* H: on, V: off, display off */
LTemp |= V_SYNC_OFF | DISPLAY_OFF;
break;
case B_DPMS_OFF: /* H: off, V: off, display off */
LTemp |= H_SYNC_OFF | V_SYNC_OFF | DISPLAY_OFF;
break;
default:
return B_ERROR;
}
/* FIXME - write the bits */
*regs = LTemp;
/*
NOTE: if you're driving a device with a backlight (like a digital
LCD), you may want to turn off the backlight here when in a DPMS
power saving mode.
if (dpms_flags == B_DPMS_ON)
// turn on the back light
;
else
// turn off the back light
;
*/
return B_OK;
}
/*
Report device DPMS capabilities. Most newer cards can do it all.
I've only seen one older card that can do a subset (ON and OFF).
Very early cards may not be able to do this at all.
*/
uint32 DPMS_CAPABILITIES (void)
{
return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF;
}
/*
Return the current DPMS mode.
*/
uint32 DPMS_MODE (void)
{
uint32 LTemp;
uint32 mode = B_DPMS_ON;
/* read the control bits from the device */
/* FIXME - read the bits */
LTemp = *regs;
/* what mode is set? */
switch (LTemp & (H_SYNC_OFF | V_SYNC_OFF))
{
case 0: /* H: on, V: on */
mode = B_DPMS_ON;
break;
case H_SYNC_OFF: /* H: off, V: on */
mode = B_DPMS_STAND_BY;
break;
case V_SYNC_OFF: /* H: on, V: off */
mode = B_DPMS_SUSPEND;
break;
case (H_SYNC_OFF | V_SYNC_OFF): /* H: off, V: off */
mode = B_DPMS_OFF;
break;
}
return mode;
}
-100
View File
@@ -1,100 +0,0 @@
/*
* Copyright 1999 Erdi Chen
*/
#ifndef __DATA_TYPES_H__
#define __DATA_TYPES_H__
#define TEXT_MODE_SIZE 256*1024
#define TEXT_FONT_SIZE 32*1024
#define DISPLAY_START 1024*0
#define CRTC_INDEX 0x3d4
#define CRTC_DATA 0x3d5
#define SEQ_INDEX 0x3c4
#define SEQ_DATA 0x3c5
typedef unsigned char byte_t;
typedef unsigned short word_t;
typedef unsigned long dword_t;
extern byte_t vga_mode_numbers[];
typedef struct
{
byte_t col;
byte_t row;
byte_t height;
byte_t buf_size0;
byte_t buf_size1;
byte_t seq_regs[0x04];
byte_t misc_output;
byte_t crtc_regs[0x19];
byte_t attr_regs[0x14];
byte_t graph_regs[0x09];
} VGAMode;
typedef struct
{
byte_t col;
byte_t row;
byte_t height;
byte_t buf_size0;
byte_t buf_size1;
byte_t seq_regs[0x04];
byte_t misc_output;
byte_t crtc_regs[0x19];
byte_t attr_regs[0x14];
byte_t graph_regs[0x09];
byte_t refresh_rate;
word_t pixel_size;
word_t pixel_width;
word_t pixel_height;
byte_t sr12;
byte_t sr13;
byte_t sr29;
byte_t misc_ctrl;
byte_t cr43;
byte_t cr50;
byte_t cr51;
byte_t cr5d;
byte_t cr5e;
byte_t cr5f;
byte_t cr66;
byte_t cr67;
byte_t cr31;
byte_t cr58;
byte_t cr69;
} SVGAMode;
typedef struct
{
byte_t s3mode;
byte_t mode_tab0;
byte_t mode_tab1;
byte_t mode_attr;
byte_t cr66;
byte_t cr67;
byte_t seq4;
byte_t patch0;
byte_t patch1;
} SVGAModeInfo;
typedef struct
{
byte_t crtc0;
byte_t crtc1;
byte_t rate_attr;
byte_t rate_freq;
byte_t sr13;
byte_t sr12;
byte_t sr29;
byte_t misc_ctrl;
byte_t cr50;
byte_t cr5d;
byte_t cr5e;
} SVGAPatchTable;
#endif /* __DATA_TYPES_H__ */
-337
View File
@@ -1,337 +0,0 @@
/*
* Copyright 1999 Erdi Chen
*/
#include "datatype.h"
#include "s3mmio.h"
#include "s3accel.h"
#include "s3drv.h"
#define MIX_MASK 0x000f
#define MIX_NOT_DST 0x0000
#define MIX_0 0x0001
#define MIX_1 0x0002
#define MIX_DST 0x0003
#define MIX_NOT_SRC 0x0004
#define MIX_XOR 0x0005
#define MIX_XNOR 0x0006
#define MIX_SRC 0x0007
#define MIX_NAND 0x0008
#define MIX_NOT_SRC_OR_DST 0x0009
#define MIX_SRC_OR_NOT_DST 0x000a
#define MIX_OR 0x000b
#define MIX_AND 0x000c
#define MIX_SRC_AND_NOT_DST 0x000d
#define MIX_NOT_SRC_AND_DST 0x000e
#define MIX_NOR 0x000f
byte_t s3alu[16] =
{
MIX_0,
MIX_AND,
MIX_SRC_AND_NOT_DST,
MIX_SRC,
MIX_NOT_SRC_AND_DST,
MIX_DST,
MIX_XOR,
MIX_OR,
MIX_NOR,
MIX_XNOR,
MIX_NOT_DST,
MIX_SRC_OR_NOT_DST,
MIX_NOT_SRC,
MIX_NOT_SRC_OR_DST,
MIX_NAND,
MIX_1
};
byte_t * __vga_base = 0;
byte_t * __mmio_base = 0;
dword_t s3accelCmd = 0;
typedef struct
{
S3DriverContext * s3dc;
byte_t * mmio_base;
byte_t * vga_base;
byte_t * bci_base;
byte_t * fb_base;
int fb_size;
word_t device_id;
dword_t global_bd;
dword_t primary_bd;
dword_t secondary_bd;
int bpp;
int logical_width;
int logical_height;
} S3AccelContext;
static S3AccelContext S3AC = { 0 };
int s3accel_init (S3DriverContext * s3dc)
{
byte_t sr1;
int stride;
int display_start;
if (!s3dc) return 0;
S3AC.s3dc = s3dc;
S3AC.mmio_base = __mmio_base = S3AC.s3dc->mmio_base;
S3AC.vga_base = __vga_base = S3AC.s3dc->vga_base;
S3AC.fb_base = S3AC.s3dc->fb_base;
S3AC.fb_size = S3AC.s3dc->fb_size;
S3AC.bpp = S3AC.s3dc->bpp;
S3AC.logical_width = S3AC.s3dc->logical_width;
s3drv_unlock_regs ();
write32 (S3AC.mmio_base + 0x850C, 0x11);
write32 (S3AC.mmio_base + 0x850C, 0x11);
S3AC.device_id = read16 (__vga_base + 2);
sr1 = read_sr (__vga_base, 1);
write_sr (__vga_base, 1, sr1 | 0x20);
UpdateGEReg (ALT_CURXY, 0);
UpdateGEReg (ALT_STEP, 0);
UpdateGEReg (ERR_TERM, 0);
UpdateGEReg (SHORT_STROKE,0);
UpdateGEReg (BKGD_COLOR, 0x00000000);
UpdateGEReg (FRGD_COLOR, 0xffffffff);
UpdateGEReg (WRT_MASK, 0xffffffff);
UpdateGEReg (RD_MASK, 0xffffffff);
UpdateGEReg (COLOR_CMP, 0x00000000);
UpdateGEReg (ALT_MIX, 0x00270007);
UpdateGEReg (SCISSORS_LT, 0x20001000);
UpdateGEReg (SCISSORS_RB, 0x4fff3fff);
UpdateGEReg (PIX_CNTL, 0xd000a000);
UpdateGEReg (MULT_MISC, 0xf000e200);
UpdateGEReg (ALT_PCNT, 0);
display_start = S3AC.s3dc->display_start;
s3drv_dpf ("display_start = %d\n", display_start);
write32 (__mmio_base + 0x81c0, display_start);
stride = (S3AC.logical_width * S3AC.bpp + 7) >> 3;
write32 (__mmio_base + 0x81c8, stride); /* set stride */
write32 (__mmio_base + 0x8168, display_start);
S3AC.global_bd = (S3AC.logical_width & 0x1ff0)|(S3AC.bpp<<16)|0x10000001;
/* Need to write GBD twice after an engine reset */
write32 (__mmio_base + 0x816c, S3AC.global_bd);
write32 (__mmio_base + 0x816c, S3AC.global_bd);
S3AC.s3dc->global_bd = S3AC.global_bd;
write_sr (__vga_base, 1, sr1);
s3drv_lock_regs ();
return 1;
}
int s3accel_wait_for_idle ()
{
s3drv_wait_for_idle ();
UpdateGEReg (WRT_MASK, 0xffffffff);
UpdateGEReg (RD_MASK, 0xffffffff);
UpdateGEReg (ALT_MIX, 0x00270007);
UpdateGEReg (SCISSORS_LT, 0x20001000);
UpdateGEReg (SCISSORS_RB, 0x4fff3fff);
UpdateGEReg (PIX_CNTL, 0xd000a000);
return 1;
}
int s3accel_wait_for_fifo (int count)
{
int i;
s3drv_wait_for_idle ();
i = 0;
return i;
}
__inline__ void s3accel_set_fg_color (dword_t color)
{
s3accel_wait_for_fifo (1);
UpdateGEReg (FRGD_COLOR, color);
}
__inline__ void s3accel_set_bg_color (dword_t color)
{
s3accel_wait_for_fifo (1);
UpdateGEReg (BKGD_COLOR, color);
}
void s3accel_set_clip_rect (int x1, int y1, int x2, int y2)
{
s3accel_wait_for_fifo (2);
UpdateGEReg (SCISSORS_LT, (y1 << 16) | (x1 & 0xffff));
UpdateGEReg (SCISSORS_RB, (y2 << 16) | (x2 & 0xffff));
}
#if S3ACCEL_NEED_FUNCTIONS
void s3accel_setup_fill_rect (int color, int rop, dword_t planemask)
{
s3accel_wait_for_fifo (2);
UpdateGEReg (WRT_MASK, planemask);
UpdateGEReg16 (FRGD_MIX, 0x0020 | s3alu[rop]);
s3drv_dpf ("FRGD_MIX is 0x%4X\n", 0x0020 | s3alu[rop]);
UpdateGEReg (FRGD_COLOR, color);
s3accelCmd = 0x40b1;
}
void s3accel_repeat_fill_rect (int x, int y, int w, int h)
{
w--; h--;
s3accel_wait_for_fifo (2);
UpdateGEReg (ALT_CURXY, (x<<16)|y);
UpdateGEReg (ALT_PCNT, (w<<16)|h);
UpdateGEReg (CMD, 0x000040b1);
}
void s3accel_fill_rect (int x, int y, int w, int h)
{
w--; h--;
UpdateGEReg16 (FRGD_MIX, 0x0027);
write32 (__mmio_base + ALT_CURXY, (x<<16)|y);
UpdateGEReg (ALT_PCNT, (w<<16)|h);
UpdateGEReg (CMD, 0x000040b1);
}
__inline__ void s3accel_setup_copy_rect (
int xdir, int ydir, int rop, dword_t planemask,
int transparency_color)
{
s3accelCmd = 0xc011;
if (xdir == 1) s3accelCmd |= 0x20;
if (ydir == 1) s3accelCmd |= 0x80;
s3accel_wait_for_fifo (2);
UpdateGEReg (WRT_MASK, planemask);
if (transparency_color != -1)
{
UpdateGEReg (COLOR_CMP, transparency_color);
UpdateGEReg16 (PIX_CNTL, 0xa100);
}
UpdateGEReg16 (FRGD_MIX, 0x0060 | s3alu[rop]);
}
__inline__ void s3accel_repeat_copy_rect (
int src_x, int src_y, int dest_x, int dest_y, int w, int h)
{
w--; h--;
if (!(s3accelCmd & 0x20))
{
src_x += w; dest_x += w;
}
if (!(s3accelCmd & 0x80))
{
src_y += h; dest_y += h;
}
s3accel_wait_for_fifo (4);
UpdateGEReg (ALT_CURXY, (src_x<<16)|src_y);
UpdateGEReg (ALT_STEP, (dest_x<<16)|dest_y);
UpdateGEReg (ALT_PCNT, (w<<16)|h);
UpdateGEReg (CMD, s3accelCmd);
}
void s3accel_copy_rect (int is_patterned, int src_x, int src_y,
int dest_x, int dest_y, int w, int h)
{
int cmd = 0xc0b1;
w--; h--;
if (is_patterned)
cmd |= 0x4000;
else
{
if ((src_x < dest_x) )//&& (src_x + w) > dest_x)
{
src_x += w; dest_x += w;
cmd ^= 32;
}
if ((src_y < dest_y) )//&& (src_y + h) > dest_y)
{
src_y += h; dest_y += h;
cmd ^= 128;
}
}
UpdateGEReg16 (FRGD_MIX, 0x0067);
UpdateGEReg (ALT_CURXY, (src_x<<16)|src_y);
UpdateGEReg (ALT_STEP, (dest_x<<16)|dest_y);
UpdateGEReg (ALT_PCNT, (w<<16)|h);
UpdateGEReg (CMD, cmd);
}
void s3accel_draw_line (int x1, int y1, int x2, int y2, int no_endpoint)
{
int cmd = 0x20b1;
int min, max, err_term, *tmp=&max;
/*
max = max(abs(x2-x1),abs(y2-y1));
min = min(abs(x2-x1),abs(y2-y1));
*/
max = x2 - x1;
min = y2 - y1;
if (max < 0)
{
max = -max;
cmd ^= 32;
}
if (min < 0)
{
min = -min;
cmd ^= 128;
}
if (max < min)
{
max = min;
min = &tmp;
cmd |= 0x40;
}
err_term = 2 * min - max;
if (!(cmd & 0x20)) err_term --;
if (no_endpoint) cmd |= 4;
s3accel_wait_for_idle ();
UpdateGEReg16 (FRGD_MIX, 0x0027);
UpdateGEReg (ALT_CURXY, (x1<<16)|y1);
/* Databook says MAJ_AXIS_PCNT = max - 1,
but MAJ_AXIS_PCNT = max seems to produce correct result. */
UpdateGEReg16 (MAJ_AXIS_PCNT, max);
UpdateGEReg (ALT_STEP, ((2*(min-max))<<16)|(2*min));
UpdateGEReg (ERR_TERM, err_term);
UpdateGEReg (CMD, cmd);
}
void s3accel_repeat_draw_line (
int x1, int y1, int x2, int y2, dword_t bias)
{
s3accel_draw_line (x1, y1, x2, y2, bias & 0x100);
}
void s3accel_write_image (int x, int y, int w, int h)
{
int count;
count = (((w * S3AC.bpp) + 31) >> 5) * h;
w--; h--;
s3accel_wait_for_idle ();
UpdateGEReg16 (FRGD_MIX, 0x0047);
UpdateGEReg (ALT_CURXY, (x<<16)|y); /* destination */
UpdateGEReg (ALT_PCNT, (w<<16)|h); /* width/height */
UpdateGEReg (CMD, 0x55b1);
while (count --) { write32 (__mmio_base, ~0); }
}
#endif /* S3ACCEL_NEED_FUNCTIONS */
-112
View File
@@ -1,112 +0,0 @@
/*
* Copyright 1999 Erdi Chen
*/
#ifndef __S3ACCEL_H__
#define __S3ACCEL_H__
#include "s3drv.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
ALT_CURXY = 0x8100,
CUR_Y = 0x8100,
CUR_X = 0x8102,
ALT_STEP = 0x8108,
DESTY_AXSTP = 0x8108,
DESTX_DIASTP = 0x810a,
ERR_TERM = 0x8110,
CMD = 0x8118,
SHORT_STROKE = 0x811c,
BKGD_COLOR = 0x8120,
FRGD_COLOR = 0x8124,
WRT_MASK = 0x8128,
RD_MASK = 0x812c,
COLOR_CMP = 0x8130,
ALT_MIX = 0x8134,
BKGD_MIX = 0x8134,
FRGD_MIX = 0x8136,
SCISSORS_LT = 0x8138,
SCISSORS_T = 0x8138,
SCISSORS_L = 0x813a,
SCISSORS_RB = 0x813c,
SCISSORS_B = 0x813c,
SCISSORS_R = 0x813e,
PIX_CNTL = 0x8140,
MULT_MISC2 = 0x8142,
MULT_MISC = 0x8144,
READ_SEL = 0x8144,
ALT_PCNT = 0x8148,
MIN_AXIS_PCNT = 0x8148,
MAJ_AXIS_PCNT = 0x814a
} S3GERegister;
extern byte_t s3alu[16];
extern byte_t * __vga_base;
extern byte_t * __mmio_base;
#define UpdateGEReg(reg, val)\
write32 (__mmio_base + reg, val);\
#define UpdateGEReg16(reg, val)\
write16 (__mmio_base + reg, val);\
/*
* Function prototypes.
*/
extern int s3accel_init (S3DriverContext * s3dc);
extern int s3accel_wait_for_idle ();
extern int s3accel_wait_for_fifo (int count);
extern void s3accel_set_pattern ();
extern void s3accel_set_fg_color (dword_t fg_color);
extern void s3accel_set_bg_color (dword_t bg_color);
extern void s3accel_set_clip_rect (int x1, int y1, int x2, int y2);
extern void s3accel_setup_copy_rect (
int xdir, int ydir, int rop,
dword_t planemask, int transparency_color);
extern void s3accel_repeat_copy_rect (
int x1, int y1, int x2, int y2, int w, int h);
extern void s3accel_copy_rect (int is_patterned, int src_x, int src_y,
int dest_x, int dest_y, int w, int h);
extern void s3accel_setup_fill_rect (int color, int rop, dword_t planemask);
extern void s3accel_repeat_fill_rect (int x, int y, int w, int h);
extern void s3accel_fill_rect (int x, int y, int w, int h);
extern void s3accel_fill_polygon ();
extern void s3accel_setup_fill_polygon ();
extern void s3accel_repeat_fill_polygon (int count, short * xw);
extern void s3accel_draw_line (int x1, int y1, int x2, int y2,
int no_endpoint);
extern void s3accel_draw_polyline (int count, short * xy);
extern void s3accel_draw_segments (int count, short * xy);
extern void s3accel_setup_draw_line ();
extern void s3accel_repeat_draw_line (int x1, int y1, int x2, int y2,
dword_t bias);
extern void s3accel_draw_scanline ();
extern void s3accel_setup_draw_scanline ();
extern void s3accel_repeat_draw_scanline (int x, int width);
extern void s3accel_draw_multi_scanlines (int count, int starty, short * xw);
extern void s3accel_write_image (int x, int y, int w, int h);
extern void s3accel_write_bitmap ();
#ifdef __cplusplus
}
#endif
#endif /* __S3ACCEL_H__ */
-683
View File
@@ -1,683 +0,0 @@
/*
* Copyright 1999 Erdi Chen
*/
#include "s3mmio.h"
#include "s3drv.h"
#include "DriverInterface.h"
#include <stdarg.h>
#include <stdio.h>
extern int __s3drv_get_svga_mode (
SVGAMode * svgamode, PixelTiming * pixel_timing);
static S3DriverContext S3DC =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
void s3drv_dpf (const char * format, ...)
{
#if DEBUG > 0
va_list args;
char buffer[4096];
va_start (args, format);
vsprintf (buffer, format, args);
fputs (buffer, stderr);
va_end (args);
#endif
}
S3DriverContext * s3drv_get_context ()
{
return &S3DC;
}
int s3drv_init (byte_t * mb)
{
if (!mb) return 0;
S3DC.mmio_base = mb;
S3DC.vga_base = mb + 0x8000;
S3DC.device_id = read16 (S3DC.vga_base + 2);
S3DC.viewport_x = 0;
S3DC.viewport_y = 0;
S3DC.display_start = DISPLAY_START;
write32 (mb + 0x8510, 1);
return 1;
}
static int __reg_unlock_count = 0;
void s3drv_lock_regs ()
{
__reg_unlock_count --;
if (__reg_unlock_count < 1)
{
__reg_unlock_count = 0;
s3_lock_regs (S3DC.vga_base);
}
}
void s3drv_unlock_regs ()
{
s3_unlock_regs (S3DC.vga_base);
__reg_unlock_count ++;
}
int s3drv_detect_vram_mb_size (byte_t * vram_start, int max_mb)
{
int ram_size_mb;
byte_t * vga_base = S3DC.vga_base;
s3drv_unlock_regs ();
if (vram_start)
{
byte_t cr58, cr66;
byte_t * magic_spot;
if (!vga_base) return 2;
if (!vram_start) return 2;
magic_spot = vram_start + 1024*1024;
cr58 = read_cr (vga_base, 0x58);
write_cr (vga_base, 0x58, 0x13);
cr66 = read_cr (vga_base, 0x66);
write_cr (vga_base, 0x66, cr66 | 1);
for (ram_size_mb = 1; ram_size_mb < max_mb; ram_size_mb ++)
{
read32 (vga_base);
write32 (magic_spot, 0xC55CC55C);
if (read32 (magic_spot) != 0xC55CC55C) break;
write32 (vram_start, 0);
write32 (magic_spot, 0xFFFFFFFF);
if (read32 (vram_start) == 0xFFFFFFFF) break;
magic_spot += 1024*1024;
}
write_cr (vga_base, 0x58, cr58);
write_cr (vga_base, 0x66, cr66);
}
else
{
byte_t cr36;
word_t device;
device = (read_cr (vga_base, 0x2d) << 8) | read_cr (vga_base, 0x2e);
cr36 = read_cr (vga_base, 0x36);
ram_size_mb = 2;
if (isSavage4Family(device))
{
switch (cr36 >> 5)
{
case 0:
ram_size_mb = 2;
break;
case 1:
ram_size_mb = 4;
case 2:
ram_size_mb = 8;
break;
case 3:
ram_size_mb = 12;
break;
case 4:
ram_size_mb = 16;
break;
case 5:
ram_size_mb = 32;
break;
case 6:
ram_size_mb = 64;
break;
case 7:
ram_size_mb = 128;
break;
case 8:
ram_size_mb = 256;
break;
}
}
else
{
switch (cr36 >> 6)
{
case 0:
ram_size_mb = 8;
break;
case 1:
case 2:
ram_size_mb = 4;
break;
case 3:
ram_size_mb = 2;
break;
}
}
}
s3drv_lock_regs ();
return ram_size_mb;
}
int s3drv_is_text_mode ()
{
return !(read_gr (S3DC.vga_base, 0x06) & 1);
}
int s3drv_save_font (byte_t * vram, byte_t * font_buf, int buf_size)
{
int i;
byte_t * font;
byte_t * plane2;
if (!font_buf) return 0;
font = font_buf;
plane2 = vram + 2;
*font = *plane2;
for (i = 0; i < buf_size; i ++) *(font++) = *(plane2+=4);
return 1;
}
int s3drv_restore_font (byte_t * vram, byte_t * font_buf, int buf_size)
{
int i;
byte_t * font;
byte_t * plane2;
if (!font_buf) return 0;
plane2 = vram + 2;
font = font_buf;
*plane2 = *font;
for (i = 0; i < buf_size; i ++) *(plane2+=4) = *(font++);
return 1;
}
int s3drv_get_mode (PixelTiming * timing, int bpp,
byte_t * mode_buf, int buf_size)
{
SVGAMode * s3mode;
if (!timing || !mode_buf) return 0;
if (buf_size < sizeof (SVGAMode)) return - sizeof (SVGAMode);
s3mode = (SVGAMode*) mode_buf;
__s3drv_get_svga_mode(s3mode, timing);
s3mode->pixel_size = bpp;
s3mode->pixel_width = timing->x.disp;
s3mode->pixel_height = timing->y.disp;
s3mode->seq_regs[0] = 0x01;
s3mode->seq_regs[1] = 0x0F;
s3mode->seq_regs[2] = 0x00;
s3mode->seq_regs[3] = 0x0E;
s3mode->attr_regs[0x10] = 0x01;
s3mode->attr_regs[0x11] = 0x00;
s3mode->attr_regs[0x12] = 0x0F;
s3mode->attr_regs[0x13] = 0x00;
s3mode->graph_regs[0] = 0x00;
s3mode->graph_regs[1] = 0x00;
s3mode->graph_regs[2] = 0x00;
s3mode->graph_regs[3] = 0x00;
s3mode->graph_regs[4] = 0x00;
s3mode->graph_regs[5] = 0x00;
s3mode->graph_regs[6] = 0x05;
s3mode->graph_regs[7] = 0x0F;
s3mode->graph_regs[8] = 0xFF;
s3mode->misc_ctrl = s3mode->misc_output & 0xc0;
s3mode->cr31 = 0x0d;
/* Savage3D and Savage/MX need double horizontal timing for 16bpp */
s3mode->cr43 = (!isSavage4Family(S3DC.device_id) &&
(((bpp + 7)/8) == 2) ) ? 0x80 : 0;
s3mode->cr50 = 0xC1 | ((((bpp+7)>>3) - 1) << 4);
s3mode->cr51 =
(((s3mode->pixel_width * s3mode->pixel_size + 31) >> 6) & 0x300) >> 4;
s3mode->cr58 = 0x13;
s3mode->cr66 = 0x89;
switch (bpp)
{
case 8:
s3mode->cr67 = 0x00;
break;
case 15:
s3mode->cr67 = 0x20;
break;
case 16:
s3mode->cr67 = 0x40;
break;
case 32:
s3mode->cr67 = 0xd0;
break;
default:
s3mode->cr67 = 0x00;
}
s3mode->cr69 = 0x80;
return 1;
}
int s3drv_display_is_off ()
{
return read_sr (S3DC.vga_base, 0x01) & 0x20;
}
void s3drv_turn_display_off ()
{
write_sr (S3DC.vga_base, 0x01, read_sr (S3DC.vga_base, 0x01) | 0x20);
}
void s3drv_turn_display_on ()
{
byte_t sr1 = read_sr (S3DC.vga_base, 0x01) & ~0x20;
s3drv_wait_for_vsync ();
write_sr (S3DC.vga_base, 0x01, sr1);
}
int s3drv_set_logical_width (int width)
{
if (width >= S3DC.width)
{
int stride;
width += 15;
width &= ~15;
stride = (width * S3DC.bpp + 7) >> 3;
S3DC.logical_width = width;
write32 (S3DC.mmio_base + 0x81c8, stride); /* set stride */
if (S3DC.global_bd)
{
S3DC.global_bd = (S3DC.global_bd & 0xffffe00f) | stride;
write32 (S3DC.mmio_base + 0x816c, S3DC.global_bd);
write32 (S3DC.mmio_base + 0x816c, S3DC.global_bd);
}
}
return S3DC.logical_width;
}
int s3drv_adjust_viewport (int x, int y)
{
int viewport_start;
if (x < 0 || y < 0) return 0;
S3DC.viewport_x = x;
S3DC.viewport_y = y;
viewport_start = ((y * S3DC.logical_width + x) * S3DC.bpp + 7) / 8;
viewport_start += S3DC.display_start;
if (S3DC.bpp == 32)
{
S3DC.cursor_adjustment = (viewport_start & 15) / 4;
viewport_start &= ~15;
}
write32 (S3DC.mmio_base + 0x81c0, viewport_start);
return 1;
}
int s3drv_set_display_start (int offset)
{
if (offset > -1)
{
S3DC.display_start = offset + DISPLAY_START;
write32 (S3DC.mmio_base + 0x8168, S3DC.display_start);
s3drv_adjust_viewport (S3DC.viewport_x, S3DC.viewport_y);
}
return offset;
}
void s3drv_wait_for_vsync ()
{
int i;
if (!s3drv_display_is_off ())
for (i = 0; i < 1000; i ++)
if ( (read8 (S3DC.vga_base + 0x3da) & 9) == 9) break;
}
void s3drv_wait_for_idle ()
{
int i;
if (isSavage4Family(S3DC.device_id)) for (i = 0; i < 10000000; i ++)
{
if ( (read32 (S3DC.mmio_base + 0x48c00) & 0x5e01ffff) == 0x5e000000)
break;
}
else for (i = 0; i < 10000000; i ++)
{
if ( (read32 (S3DC.mmio_base + 0x48c00) & 0x005fffff) == 0x005e0000)
break;
}
}
int s3drv_set_cursor_color (dword_t fg_color, dword_t bg_color)
{
read_cr (S3DC.vga_base, 0x45);
if (S3DC.bpp != 8)
{
write_cr (S3DC.vga_base, 0x4a, fg_color >> 16);
write_cr (S3DC.vga_base, 0x4a, fg_color >> 8);
}
write_cr (S3DC.vga_base, 0x4a, fg_color);
read_cr (S3DC.vga_base, 0x45);
if (S3DC.bpp != 8)
{
write_cr (S3DC.vga_base, 0x4b, bg_color >> 16);
write_cr (S3DC.vga_base, 0x4b, bg_color >> 8);
}
write_cr (S3DC.vga_base, 0x4b, bg_color);
return 1;
}
/* Assume width and height are byte-aligned. */
int s3drv_load_cursor (
byte_t * lfb, int offset, int width, int height,
byte_t * and_mask, byte_t * xor_mask)
{
int i, x, y, bit_shift;
byte_t and_buf[512];
byte_t xor_buf[512];
byte_t * and_ptr = (byte_t*)and_mask;
byte_t * xor_ptr = (byte_t*)xor_mask;
if (!lfb || !and_mask || !xor_mask) return 0;
bit_shift = width & 7;
width /= 8;
if (width != 64 || height != 64)
{
and_ptr = (byte_t*)and_buf;
xor_ptr = (byte_t*)xor_buf;
for (y = 0; y < height; y ++)
{
for (x = 0; x < width; x ++)
{
*and_ptr ++ = *and_mask ++;
*xor_ptr ++ = *xor_mask ++;
}
if (bit_shift)
{
x ++;
*and_ptr ++ = 0xFF ^ ((*and_mask ++) & (~(0xFF >> bit_shift)));
*xor_ptr ++ = (*xor_mask ++) & (~(0xFF >> bit_shift));
}
for ( ; x < 8; x ++)
{
*and_ptr ++ = 0xFF;
*xor_ptr ++ = 0x00;
}
}
for ( ; y < 64; y ++)
{
*(dword_t*)and_ptr = ~0; and_ptr += 4;
*(dword_t*)and_ptr = ~0; and_ptr += 4;
*(dword_t*)xor_ptr = 0; xor_ptr += 4;
*(dword_t*)xor_ptr = 0; xor_ptr += 4;
}
and_ptr = (byte_t*)and_buf;
xor_ptr = (byte_t*)xor_buf;
}
lfb += offset * 1024;
write_cr (S3DC.vga_base, 0x4d, offset);
write_cr (S3DC.vga_base, 0x4c, offset >> 8);
for (i = 0; i < 256; i ++)
{
#if 0
dword_t tmp = (*(word_t*)and_ptr << 16) | *(word_t*)xor_ptr;
*(dword_t*)lfb = tmp; lfb += 4;
#else
write16 (lfb, *(word_t*)and_ptr);
lfb += 2;
write16 (lfb, *(word_t*)xor_ptr);
lfb += 2;
#endif
and_ptr += 2; xor_ptr += 2;
}
return 1;
}
void s3drv_move_cursor (int x, int y)
{
int xoff = 0, yoff = 0;
x += S3DC.cursor_adjustment;
if (x < 0)
{
xoff = (x < -63) ? 63 : -x;
x = 0;
}
if (y < 0)
{
yoff = (y < -63) ? 63 : -y;
y = 0;
}
write_cr (S3DC.vga_base, 0x46, (x & 0xff00) >> 8);
write_cr (S3DC.vga_base, 0x47, (x & 0xff));
write_cr (S3DC.vga_base, 0x49, (y & 0xff));
write_cr (S3DC.vga_base, 0x4e, (xoff));
write_cr (S3DC.vga_base, 0x4f, (yoff));
write_cr (S3DC.vga_base, 0x48, (y & 0xff00) >> 8);
}
void s3drv_show_cursor ()
{
write_cr (S3DC.vga_base, 0x45, read_cr (S3DC.vga_base, 0x45) | 1);
}
void s3drv_hide_cursor ()
{
write_cr (S3DC.vga_base, 0x45, read_cr (S3DC.vga_base, 0x45) & ~1);
}
void s3drv_set_palette (int index, int red, int green, int blue)
{
byte_t * vga_base = S3DC.vga_base;
write8 (vga_base + 0x3c8, index);
write8 (vga_base + 0x3c9, red);
write8 (vga_base + 0x3c9, green);
write8 (vga_base + 0x3c9, blue);
}
void s3drv_get_palette (int index, int *red, int *green, int *blue)
{
byte_t * vga_base = S3DC.vga_base;
write8 (vga_base + 0x3c7, index);
*red = read8 (vga_base + 0x3c9);
*green = read8 (vga_base + 0x3c9);
*blue = read8 (vga_base + 0x3c9);
}
int s3drv_save_mode (byte_t * mode_buf, int buf_size)
{
int i;
byte_t * vga_base = S3DC.vga_base;
SVGAMode * mode = (SVGAMode*)(mode_buf);
if (!mode_buf || buf_size < sizeof (SVGAMode))
{
return - sizeof (SVGAMode);
}
s3drv_unlock_regs ();
for (i = 0; i < 4; i ++) mode->seq_regs[i] = read_sr (vga_base, i+1);
mode->misc_output = read8 (vga_base + 0x3cc);
for (i = 0; i < 0x19; i ++) mode->crtc_regs[i] = read_cr (vga_base, i);
for (i = 0; i < 0x14; i ++) mode->attr_regs[i] = read_ar (vga_base, i);
for (i = 0; i < 0x09; i ++) mode->graph_regs[i] = read_gr (vga_base, i);
mode->refresh_rate = 0xff;
mode->sr12 = read_sr (vga_base, 0x12);
mode->sr13 = read_sr (vga_base, 0x13);
mode->sr29 = read_sr (vga_base, 0x29);
mode->misc_ctrl = mode->misc_output & 0xc0;
mode->cr43 = read_cr (vga_base, 0x43);
mode->cr50 = read_cr (vga_base, 0x50);
mode->cr51 = read_cr (vga_base, 0x51);
mode->cr5d = read_cr (vga_base, 0x5d);
mode->cr5e = read_cr (vga_base, 0x5e);
mode->cr5f = read_cr (vga_base, 0x5f);
mode->cr66 = read_cr (vga_base, 0x66);
mode->cr67 = read_cr (vga_base, 0x67);
mode->cr31 = read_cr (vga_base, 0x31);
mode->cr58 = read_cr (vga_base, 0x58);
mode->cr69 = read_cr (vga_base, 0x69);
mode->pixel_width =
( ( ((mode->cr5f & 0x0c) << 7) |
((mode->cr5d & 0x02) << 7) |
( mode->crtc_regs[1] ) ) + 1 ) * 8;
mode->pixel_height = 1 +
( ((mode->cr5e & 0x02) << 9) |
((mode->crtc_regs[0x07] & 0x40) << 3) |
((mode->crtc_regs[0x07] & 0x02) << 7) |
( mode->crtc_regs[0x12] ) );
switch ( (mode->cr67 & 0xf0) >> 4)
{
case 0:
case 1:
mode->pixel_size = (read_cr (vga_base, 0x3a) & 0x10) ? 8 : 4;
break;
case 2:
case 3:
mode->pixel_size = 15;
break;
case 4:
case 5:
mode->pixel_size = 16;
break;
case 0xd:
mode->pixel_size = 32;
break;
default:
mode->pixel_size = 8;
}
s3drv_lock_regs ();
return sizeof (SVGAMode);
}
static word_t crtc_reg_defaults[] =
{
0x4838, 0xa539, 0x0531, 0x4032, 0x0833, 0x0034, 0x0035, 0x053a,
0x103c, 0x0040, 0x0042, 0x0043, 0x0045, 0x0050, 0x0051, 0x0053,
0x0055, 0x0058, 0x005d, 0x005e, 0x005f, 0x005b, 0x0066, 0x0067,
0x0069, 0x006a, 0xc071, 0x0090,
0x0087, 0x3070, 0xc071, 0x0772, 0x1f73, 0x1f74, 0x1f75, 0x0f76,
0x1f77, 0x0178, 0x0179, 0x1f7a, 0x1f7b, 0x171c, 0x177d, 0x177e,
0x0060,
0x0000
};
static word_t seq_reg_defaults[] =
{
0x0608, 0x0014, 0x4018, 0x0029, 0x601c,
0x0000
};
int s3drv_restore_mode (byte_t * mode_buf, int buf_size, int restore_vga)
{
int i;
byte_t cr3a;
byte_t * vga_base = S3DC.vga_base;
SVGAMode * mode = (SVGAMode*)(mode_buf);
if (!mode || buf_size < sizeof (SVGAMode))
{
return - sizeof (SVGAMode);
}
if (mode->pixel_size) S3DC.bpp = mode->pixel_size;
if (mode->pixel_width) S3DC.width = mode->pixel_width;
if (mode->pixel_height) S3DC.height = mode->pixel_height;
if (!S3DC.logical_width) S3DC.logical_width = mode->pixel_width;
S3DC.display_start = 0;
s3drv_unlock_regs ();
write_sr (vga_base, 0x01, read_sr (vga_base, 0x01) | 0x20);
for (i = 0; crtc_reg_defaults[i] != 0; i ++)
write16 (vga_base + CRTC_INDEX, crtc_reg_defaults[i]);
for (i = 0; seq_reg_defaults[i] != 0; i ++)
write16 (vga_base + SEQ_INDEX, seq_reg_defaults[i]);
if (restore_vga > 0)
{
write_cr (vga_base, 0x11, read_cr (vga_base, 0x11) & 0x7f);
for (i = 1; i < 4; i ++)
write_sr (vga_base, i+1, mode->seq_regs[i]);
for (i = 0; i < 0x0c; i ++)
write_cr (vga_base, i, mode->crtc_regs[i]);
for (i = 0x10; i < 0x19; i ++)
write_cr (vga_base, i, mode->crtc_regs[i]);
for (i = 0; i < 0x14; i ++)
write_ar (vga_base, i, mode->attr_regs[i]);
for (i = 0; i < 0x09; i ++)
write_gr (vga_base, i, mode->graph_regs[i]);
}
write8 (vga_base + 0x3c2, 0x23);
write_sr (vga_base, 0x15, (mode->misc_ctrl & 0x10) | 2);
write8 (vga_base + 0x3c2,
((mode->misc_output & 0x3f) |
(mode->misc_ctrl & 0xc0)));
if ((mode->misc_output & 0x0c) == 0x0c)
{
write_sr (vga_base, 0x12, mode->sr12);
write_sr (vga_base, 0x13, mode->sr13);
write_sr (vga_base, 0x29, mode->sr29);
}
if (mode->refresh_rate != 0)
{
write_cr (vga_base, 0x43, mode->cr43);
write_cr (vga_base, 0x50, mode->cr50);
write_cr (vga_base, 0x51, mode->cr51);
write_cr (vga_base, 0x5d, mode->cr5d);
write_cr (vga_base, 0x5e, mode->cr5e);
write_cr (vga_base, 0x5e, mode->cr5f);
write_cr (vga_base, 0x66, mode->cr66);
write_cr (vga_base, 0x67, mode->cr67);
write_cr (vga_base, 0x31, mode->cr31);
write_cr (vga_base, 0x58, mode->cr58);
write_cr (vga_base, 0x69, mode->cr69);
}
/* Turn off hardware graphics cursor */
write_cr (vga_base, 0x45, read_cr (vga_base, 0x45) & ~1);
cr3a = read_cr (vga_base, 0x3a);
/* Set attribute controller for enhanced mode */
if (mode->pixel_size < 8) cr3a &= ~0x10;
else cr3a |= 0x10;
write_cr (vga_base, 0x3a, cr3a);
/* RAMDAC mask */
write8 (vga_base + 0x3c6, 0xff);
write_sr (vga_base, 0x01, mode->seq_regs[0]);
s3drv_lock_regs ();
if (mode->cr66 & 1)
{
write32 (S3DC.mmio_base + 0x81c0, S3DC.display_start);
write32 (S3DC.mmio_base + 0x81c8, /* set stride */
(S3DC.logical_width * S3DC.bpp + 7) >> 3);
write32 (S3DC.mmio_base + 0x8168, S3DC.display_start);
/* Need to write GBD twice after an engine reset */
if (S3DC.global_bd)
{
write32 (S3DC.mmio_base + 0x816c, S3DC.global_bd);
write32 (S3DC.mmio_base + 0x816c, S3DC.global_bd);
}
}
return 1;
}
-118
View File
@@ -1,118 +0,0 @@
/*
* Copyright 1999 Erdi Chen
*/
#ifndef __S3DRV_H__
#define __S3DRV_H__
#include "datatype.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
word_t disp;
word_t sync_start;
word_t sync_end;
word_t total;
word_t polarity;
} CrtcTiming;
typedef struct
{
dword_t dot_clock_khz;
CrtcTiming x;
CrtcTiming y;
} PixelTiming;
typedef struct
{
byte_t * mmio_base;
byte_t * vga_base;
byte_t * rom_base;
byte_t * fb_base;
word_t device_id;
int fb_size;
int vram_size;
dword_t bpp;
dword_t width;
dword_t height;
dword_t logical_width;
dword_t display_start;
dword_t global_bd;
word_t viewport_x;
word_t viewport_y;
int cursor_adjustment;
} S3DriverContext;
extern void s3drv_dpf (const char * format, ...);
extern S3DriverContext * s3drv_get_context ();
extern int s3drv_init (byte_t * mmio_base);
extern void s3drv_lock_regs ();
extern void s3drv_unlock_regs ();
extern int s3drv_detect_vram_mb_size (
byte_t * vram_start, int max_mb);
extern int s3drv_is_text_mode ();
extern int s3drv_save_font (
byte_t * vram, byte_t * font_buf, int buf_size);
extern int s3drv_restore_font (
byte_t * vram, byte_t * font_buf, int buf_size);
extern int s3drv_get_mode (
PixelTiming * timing, int bpp,
byte_t * mode_buf, int buf_size);
#if 0
extern int s3drv_get_gtf_mode (
int width, int height, int depth,
int rrate, byte_t * mode_buf,
int buf_size);
#endif
extern int s3drv_get_bios_mode (
int vesamode, int refresh_rate,
byte_t * mode_buf, int buf_size,
byte_t * rom);
extern int s3drv_save_mode (
byte_t * mode_buf, int buf_size);
extern int s3drv_restore_mode (
byte_t * mode_buf, int buf_size,
int restore_vga);
extern int s3drv_display_is_off ();
extern void s3drv_turn_display_off ();
extern void s3drv_turn_display_on ();
extern int s3drv_set_logical_width (int width);
extern int s3drv_adjust_viewport (int x, int y);
extern int s3drv_set_display_start (int offset);
extern void s3drv_wait_for_vsync ();
extern void s3drv_wait_for_idle ();
extern int s3drv_set_cursor_color (
dword_t foreground, dword_t background);
extern int s3drv_load_cursor (
byte_t * lfb, int offset, int width, int height,
byte_t * image, byte_t * mask);
extern void s3drv_move_cursor (int x, int y);
extern void s3drv_show_cursor ();
extern void s3drv_hide_cursor ();
extern void s3drv_set_palette (
int index, int red,
int green, int blue);
extern void s3drv_get_palette (
int index, int *red,
int *green, int *blue);
#ifdef __cplusplus
}
#endif
#endif /* __S3DRV_H__ */
-133
View File
@@ -1,133 +0,0 @@
/*
* Copyright 1999 Erdi Chen
*/
#ifndef __S3MMIO_H__
#define __S3MMIO_H__
#include "datatype.h"
#ifdef __STRICT_ANSI__
#undef __inline__
#define __inline__
#define read8(addr) (*(volatile byte_t*) (addr))
#define read16(addr) (*(volatile word_t*) (addr))
#define read32(addr) (*(volatile dword_t*) (addr))
#define write8(addr, val) ((*(volatile byte_t*) (addr)) = (byte_t) (val))
#define write16(addr, val) ((*(volatile word_t*) (addr)) = (word_t) (val))
#define write32(addr, val) ((*(volatile dword_t*) (addr)) = (dword_t) (val))
#else
static __inline__ byte_t read8 (byte_t * addr)
{
return *(volatile byte_t*) addr;
}
static __inline__ word_t read16 (byte_t * addr)
{
return *(volatile word_t*) addr;
}
static __inline__ dword_t read32 (byte_t *addr)
{
return *(volatile dword_t*) addr;
}
static __inline__ void write8 (byte_t * addr, byte_t val)
{
*(volatile byte_t*) addr = val;
}
static __inline__ void write16 (byte_t * addr, word_t val)
{
*(volatile word_t*) addr = val;
}
static __inline__ void write32 (byte_t * addr, dword_t val)
{
*(volatile dword_t*) addr = val;
}
#endif /* __STRICT_ANSI__ */
static __inline__ byte_t read_sr (byte_t * vga_base, byte_t reg)
{
write8 (vga_base + SEQ_INDEX, reg);
return read8 (vga_base + SEQ_DATA);
}
static __inline__ void write_sr (byte_t * vga_base, byte_t reg, byte_t val)
{
write16 (vga_base + SEQ_INDEX, (val << 8) | reg);
}
static __inline__ byte_t read_cr (byte_t * vga_base, byte_t reg)
{
write8 (vga_base + CRTC_INDEX, reg);
return read8 (vga_base + CRTC_DATA);
}
static __inline__ void write_cr (byte_t * vga_base, byte_t reg, byte_t val)
{
write16 (vga_base + CRTC_INDEX, (val << 8) | reg);
}
static __inline__ byte_t read_gr (byte_t * vga_base, byte_t reg)
{
write8 (vga_base + 0x3ce, reg);
return read8 (vga_base + 0x3cf);
}
static __inline__ void write_gr (byte_t * vga_base, byte_t reg, byte_t val)
{
write16 (vga_base + 0x3ce, (val << 8) | reg);
}
static __inline__ byte_t read_ar (byte_t * vga_base, byte_t reg)
{
byte_t value, index;
read8 (vga_base + 0x3da);
index = read8 (vga_base + 0x3c0);
write8 (vga_base + 0x3c0, reg);
value = read8 (vga_base + 0x3c1);
read8 (vga_base + 0x3da);
write8 (vga_base + 0x3c0, index);
return value;
}
static __inline__ void write_ar (byte_t * vga_base, byte_t reg, byte_t val)
{
byte_t index;
read8 (vga_base + 0x3da);
index = read8 (vga_base + 0x3c0);
write8 (vga_base + 0x3c0, reg);
write8 (vga_base + 0x3c0, val);
write8 (vga_base + 0x3c0, index);
}
static __inline__ void s3_lock_regs (byte_t * vga_base)
{
write_cr (vga_base, 0x11, read_cr (vga_base, 0x11) | 0x80);
write_cr (vga_base, 0x33, (0x50 | read_cr (vga_base, 0x33)) & ~2);
write_cr (vga_base, 0x38, 0x00);
write_cr (vga_base, 0x39, 0x00);
write_sr (vga_base, 0x08, 0x00);
}
static __inline__ void s3_unlock_regs (byte_t * vga_base)
{
write_sr (vga_base, 0x08, 0x06);
write_cr (vga_base, 0x38, 0x48);
write_cr (vga_base, 0x39, 0xa0);
write_cr (vga_base, 0x40, 0x01);
write_cr (vga_base, 0x11, read_cr (vga_base, 0x11) & 0x7f);
write_cr (vga_base, 0x33, (~0x50 & read_cr (vga_base, 0x33)) | 2);
write_cr (vga_base, 0x35, 0x00);
}
#endif /* __S3MMIO_H__ */
-271
View File
@@ -1,271 +0,0 @@
/*
* Copyright 1999 Erdi Chen
*/
#include "datatype.h"
#include "s3drv.h"
#define BASE_FREQ 14.318
static int pll_limits[] =
{
1, 511, /* min M, max M */
1, 127, /* min N, max N */
0, 4, /* min R, max R */
317500, 635000 /* min VCO, max VCO */
};
typedef struct
{
word_t h_display_end;
word_t h_sync_start;
word_t h_sync_end;
word_t h_total;
word_t h_polarity;
word_t v_display_end;
word_t v_sync_start;
word_t v_sync_end;
word_t v_total;
word_t v_polarity;
word_t h_blank_start;
word_t h_blank_end;
word_t v_blank_start;
word_t v_blank_end;
} CharTiming;
static int vga_convert_timing(int pixel_per_char,
CharTiming * char_timing,
PixelTiming * pixel_timing)
{
int i, blank_offset;
char_timing->h_total = pixel_timing->x.total / pixel_per_char;
char_timing->h_sync_start = pixel_timing->x.sync_start / pixel_per_char;
char_timing->h_sync_end = pixel_timing->x.sync_end / pixel_per_char;
char_timing->h_display_end = pixel_timing->x.disp / pixel_per_char;
#if 0
char_timing->h_blank_start = char_timing->h_display_end;
char_timing->h_blank_end = char_timing->h_sync_end + 1;
#else
blank_offset = (pixel_timing->x.disp * 3 + 100) / 200;
if (blank_offset < 2) blank_offset = 2;
char_timing->h_blank_start = char_timing->h_display_end + blank_offset;
char_timing->h_blank_end = char_timing->h_total - blank_offset;
i = char_timing->h_blank_end - char_timing->h_blank_start - 127;
if (i > 0)
{
char_timing->h_blank_start += (i + 1) / 2;
char_timing->h_blank_end -= i / 2;
}
char_timing->h_blank_end ++;
#endif
char_timing->v_total = pixel_timing->y.total;
char_timing->v_sync_start = pixel_timing->y.sync_start;
char_timing->v_sync_end = pixel_timing->y.sync_end;
char_timing->v_display_end = pixel_timing->y.disp;
char_timing->v_blank_start = char_timing->v_display_end + 7;
char_timing->v_blank_end = (char_timing->v_total + 7) - 0x10;
char_timing->h_polarity = (pixel_timing->x.polarity ? 1 : 0) << 6;
char_timing->v_polarity = (pixel_timing->y.polarity ? 1 : 0) << 7;
return 1;
}
static int vga_get_mode (VGAMode * vgamode,
CharTiming * char_timing,
PixelTiming * pixel_timing)
{
word_t line_compare;
word_t double_scan;
word_t row_width;
word_t mem_addr_size;
word_t pixel_per_addr;
if (!vgamode || !pixel_timing) return 0;
double_scan = 0;
line_compare = 0x3ff;
mem_addr_size = 4;
pixel_per_addr = 1;
row_width = 2 * pixel_timing->x.disp / (pixel_per_addr * mem_addr_size);
char_timing->h_total -= 5;
char_timing->h_display_end --;
char_timing->v_total -= 2;
char_timing->v_display_end --;
char_timing->v_sync_start --;
char_timing->v_sync_end --;
vgamode->misc_output = 3 |
(!char_timing->h_polarity) << 6 |
(!char_timing->v_polarity) << 7;
vgamode->crtc_regs[0x00] = char_timing->h_total & 0xff;
vgamode->crtc_regs[0x01] = char_timing->h_display_end & 0xff;
vgamode->crtc_regs[0x02] = char_timing->h_blank_start & 0xff;
vgamode->crtc_regs[0x03] = 0x80 | (char_timing->h_blank_end & 0x1f);
vgamode->crtc_regs[0x04] = char_timing->h_sync_start & 0xff;
vgamode->crtc_regs[0x05] = ((char_timing->h_blank_end & 0x20) << 2) |
(char_timing->h_sync_end & 0x1f);
vgamode->crtc_regs[0x06] = char_timing->v_total & 0xff;
vgamode->crtc_regs[0x07] = ((char_timing->v_total & 0x100) >> 8) |
((char_timing->v_display_end & 0x100) >> 7) |
((char_timing->v_sync_start & 0x100) >> 6) |
((char_timing->v_blank_start & 0x100) >> 5) |
((line_compare & 0x100) >> 4) |
((char_timing->v_total & 0x200) >> 4) |
((char_timing->v_display_end & 0x200) >> 3) |
((char_timing->v_sync_start & 0x200) >> 2);
vgamode->crtc_regs[0x08] = 0;
vgamode->crtc_regs[0x09] = (double_scan & 0x80) |
((char_timing->v_blank_start & 0x200) >> 4) |
((line_compare & 0x200) >> 3);
vgamode->crtc_regs[0x2a] = 0;
vgamode->crtc_regs[0x0b] = 0;
vgamode->crtc_regs[0x0c] = 0;
vgamode->crtc_regs[0x0d] = 0;
vgamode->crtc_regs[0x0e] = 0xff;
vgamode->crtc_regs[0x0f] = 0;
vgamode->crtc_regs[0x10] = char_timing->v_sync_start & 0xff;
vgamode->crtc_regs[0x11] = (char_timing->v_sync_end & 0x0f) | 0x80;
vgamode->crtc_regs[0x12] = char_timing->v_display_end & 0xff;
vgamode->crtc_regs[0x13] = row_width & 0xff;
vgamode->crtc_regs[0x14] = ((mem_addr_size > 3) ? 0x60 : 0);
vgamode->crtc_regs[0x15] = char_timing->v_blank_start & 0xff;
vgamode->crtc_regs[0x16] = char_timing->v_blank_end & 0xff;
vgamode->crtc_regs[0x17] = ((mem_addr_size == 1) ? 0x40 : 0x08) | 0xa3;
vgamode->crtc_regs[0x18] = line_compare & 0xff;
return 1;
}
/* --------------------------------------------------------------
* 1, 511, min M, max M
* 1, 127, min N, max N
* 0, 4, min R, max R
* 317500, 635000 min VCO, max VCO
* --------------------------------------------------------------*/
void __s3drv_encode_clock (long freq, int * pll_limits,
int * mdiv, int * ndiv, int * pll_r)
{
double ffreq, ffreq_min, ffreq_max;
double div, diff, best_diff;
int m;
int n, r;
int best_n = 16 + 2;
int best_r = 2;
int best_m = 125 + 2;
int min_m, max_m;
int min_n, max_n;
int min_r, max_r;
long freq_min, freq_max;
min_m = pll_limits[0]; max_m = pll_limits[1];
min_n = pll_limits[2]; max_n = pll_limits[3];
min_r = pll_limits[4]; max_r = pll_limits[5];
freq_min = pll_limits[6]; freq_max = pll_limits[7];
ffreq = freq / 1000.0 / BASE_FREQ;
ffreq_min = freq_min / 1000.0 / BASE_FREQ;
ffreq_max = freq_max / 1000.0 / BASE_FREQ;
if (ffreq < ffreq_min / (1<<max_r))
{
ffreq = ffreq_min / (1<<max_r);
}
if (ffreq > ffreq_max / (1<<min_r))
{
ffreq = ffreq_max / (1 << min_r);
}
best_diff = ffreq;
for (r = min_r; r <= max_r; r ++)
{
for (n = min_n + 2; n <= max_n + 2; n ++)
{
m = (int)(ffreq * n * (1 << r) + 0.5);
if (m < min_m + 2 || m > max_m + 2)
continue;
div = (double)(m) / (double)(n);
if ((div >= ffreq_min) &&
(div <= ffreq_max))
{
diff = ffreq - div / (1 << r);
if (diff < 0.0)
diff = -diff;
if (diff < best_diff)
{
best_diff = diff;
best_m = m;
best_n = n;
best_r = r;
}
}
}
}
*ndiv = best_n - 2;
*pll_r = best_r;
*mdiv = best_m - 2;
}
static void __s3drv_convert_clock (SVGAMode * svgamode, dword_t dot_clock_khz)
{
int m, n, r;
__s3drv_encode_clock (dot_clock_khz, & pll_limits[0], &m, &n, &r);
svgamode->sr12 = (n & 0x3f) | ((r & 0x3) << 6);
svgamode->sr13 = (m & 0xff);
svgamode->sr29 = (r & 0x04) | ((m & 0x100) >> 5) | ((n & 0x40) >> 2);
}
int __s3drv_get_svga_mode(SVGAMode * svgamode,
PixelTiming * pixel_timing)
{
int blank_width, sync_width;
dword_t dot_clock;
CharTiming char_timing;
if (!svgamode || !pixel_timing) return 0;
vga_convert_timing (8, & char_timing, pixel_timing);
vga_get_mode ((VGAMode*) svgamode, & char_timing, pixel_timing);
svgamode->misc_output |= 0x0c;
dot_clock = pixel_timing->dot_clock_khz;
if (!dot_clock)
{
svgamode->refresh_rate = 60;
dot_clock = pixel_timing->x.total * pixel_timing->y.total * 60 / 1000;
}
else
svgamode->refresh_rate = dot_clock * 1000 /
(pixel_timing->x.total * pixel_timing->y.total);
__s3drv_convert_clock (svgamode, dot_clock);
blank_width = char_timing.h_blank_end - char_timing.h_blank_start;
sync_width = char_timing.h_sync_end - char_timing.h_sync_start;
svgamode->cr5d |= (char_timing.h_total & 0x100) >> 8 |
(char_timing.h_display_end & 0x100) >> 7 |
(char_timing.h_blank_start & 0x100) >> 6 |
(char_timing.h_sync_start & 0x100) >> 4;
if (blank_width > 32) svgamode->cr5d |= 0x20;
if (sync_width > 64) svgamode->cr5d |= 0x04;
svgamode->cr5e = (char_timing.v_total & 0x400) >> 10 |
(char_timing.v_display_end & 0x400) >> 9 |
(char_timing.v_blank_start & 0x400) >> 8 |
(char_timing.v_sync_start & 0x400) >> 6;
svgamode->cr5f |= (char_timing.h_total & 0x600) >> 9 |
(char_timing.h_display_end & 0x600) >> 7 |
(char_timing.h_blank_start & 0x600) >> 5 |
(char_timing.h_sync_start & 0x600) >> 3;
return 1;
}
+263
View File
@@ -0,0 +1,263 @@
/*
Haiku S3 Savage driver adapted from the X.org Savage driver.
Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
Copyright (c) 2003-2006, X.Org Foundation
Copyright 2007 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2006-2007
*/
#ifndef __SAVAGE_H__
#define __SAVAGE_H__
#define BASE_FREQ 14.31818
#define FIFO_CONTROL_REG 0x8200
#define MIU_CONTROL_REG 0x8204
#define STREAMS_TIMEOUT_REG 0x8208
#define MISC_TIMEOUT_REG 0x820c
#define ADVANCED_FUNC_CTRL 0x850C
#define SYSTEM_CONTROL_REG 0x83DA
#define VGA_ATTR_INDEX 0x83C0
#define VGA_ATTR_DATA_W 0x83C0
#define VGA_MISC_OUT_R 0x83CC /* read */
#define VGA_MISC_OUT_W 0x83C2 /* write */
#define VGA_SEQ_INDEX 0x83C4
#define VGA_SEQ_DATA 0x83C5
#define VGA_GRAPH_INDEX 0x83CE
#define VGA_GRAPH_DATA 0x83CF
#define VGA_CRTC_INDEX 0x83D4
#define VGA_CRTC_DATA 0x83D5
#define VGA_IN_STAT_1 SYSTEM_CONTROL_REG
/* Stream Processor 1 */
/* Primary Stream 1 Frame Buffer Address 0 */
#define PRI_STREAM_FBUF_ADDR0 0x81c0
/* Primary Stream 1 Frame Buffer Address 1 */
#define PRI_STREAM_FBUF_ADDR1 0x81c4
/* Primary Stream 1 Stride */
#define PRI_STREAM_STRIDE 0x81c8
/* Stream Processor 2 */
/* Primary Stream 2 Frame Buffer Address 0 */
#define PRI_STREAM2_FBUF_ADDR0 0x81b0
/* Primary Stream 2 Frame Buffer Address 1 */
#define PRI_STREAM2_FBUF_ADDR1 0x81b4
/* Primary Stream 2 Stride */
#define PRI_STREAM2_STRIDE 0x81b8
/* GX-3 Configuration/Status Registers */
#define S3_BUFFER_THRESHOLD 0x48C10
#define S3_OVERFLOW_BUFFER 0x48C14
#define S3_OVERFLOW_BUFFER_PTR 0x48C18
#define MEMORY_CTRL0_REG 0xCA
#define MEMORY_CONFIG_REG 0x31
/* bitmap descriptor register */
#define S3_GLB_BD_LOW 0x8168
#define S3_GLB_BD_HIGH 0x816C
#define S3_PRI_BD_LOW 0x8170
#define S3_PRI_BD_HIGH 0x8174
#define S3_SEC_BD_LOW 0x8178
#define S3_SEC_BD_HIGH 0x817c
/* duoview */
#define SELECT_IGA1 0x4026
#define SELECT_IGA2_READS_WRITES 0x4f26
#define MEM_PS1 0x10 /*CRCA_4 :Primary stream 1*/
#define MEM_PS2 0x20 /*CRCA_5 :Primary stream 2*/
#define MEM_SS1 0x40 /*CRCA_6 :Secondary stream 1*/
#define MEM_SS2 0x80 /*CRCA_7 :Secondary stream 2*/
#define SRC_BASE 0xa4d4
#define DEST_BASE 0xa4d8
#define CLIP_L_R 0xa4dc
#define CLIP_T_B 0xa4e0
#define DEST_SRC_STR 0xa4e4
#define MONO_PAT_0 0xa4e8
#define MONO_PAT_1 0xa4ec
/*
* CR88_4 =1 : disable block write
* the "2D" is partly to set this apart from "BLOCK_WRITE_DISABLE"
* constant used for bitmap descriptor
*/
#define DISABLE_BLOCK_WRITE_2D 0x10
#define BLOCK_WRITE_DISABLE 0x0
/* CR31[0] set = Enable 8MB display memory through 64K window at A0000H. */
#define ENABLE_CPUA_BASE_A0000 0x01
/*
* reads from SUBSYS_STAT
*/
#define STATUS_WORD0 (INREG(0x48C00))
#define ALT_STATUS_WORD0 (INREG(0x48C60))
#define MAXLOOP 0xffffff
#define MAXFIFO 0x7f00
// BCI definitions.
//=================
#define TILE_FORMAT_LINEAR 0
/* BD - BCI enable */
#define BCI_ENABLE 8 // savage4, MX, IX, 3D
#define BCI_ENABLE_TWISTER 0 // twister, prosavage, DDR, supersavage, 2000
#define S3_BIG_ENDIAN 4
#define S3_LITTLE_ENDIAN 0
#define S3_BD64 1
#define BCI_BUFFER_OFFSET 0x10000
#define BCI_GET_PTR vuint32* bci_ptr = ((uint32*)(regs + BCI_BUFFER_OFFSET))
#define BCI_SEND(dw) (*bci_ptr++ = ((uint32)(dw)))
#define BCI_CMD_NOP 0x40000000
#define BCI_CMD_RECT 0x48000000
#define BCI_CMD_RECT_XP 0x01000000
#define BCI_CMD_RECT_YP 0x02000000
#define BCI_CMD_GET_ROP(cmd) (((cmd) >> 16) & 0xFF)
#define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16))
#define BCI_CMD_SEND_COLOR 0x00008000
#define BCI_CMD_DEST_PBD_NEW 0x00000C00
#define BCI_CMD_SRC_SOLID 0x00000000
#define BCI_CMD_SRC_SBD_COLOR_NEW 0x00000140
#define BCI_BD_BW_DISABLE 0x10000000
#define BCI_BD_SET_BPP(bd, bpp) ((bd) |= (((bpp) & 0xFF) << 16))
#define BCI_BD_SET_STRIDE(bd, st) ((bd) |= ((st) & 0xFFFF))
#define BCI_W_H(w, h) ((((h) << 16) | (w)) & 0x0FFF0FFF)
#define BCI_X_Y(x, y) ((((y) << 16) | (x)) & 0x0FFF0FFF)
// Macros for memory mapped I/O.
//==============================
#define INREG8(addr) *((vuint8*)(regs + addr))
#define INREG16(addr) *((vuint16*)(regs + addr))
#define INREG32(addr) *((vuint32*)(regs + addr))
#define OUTREG8(addr, val) *((vuint8*)(regs + addr)) = val
#define OUTREG16(addr, val) *((vuint16*)(regs + addr)) = val
#define OUTREG32(addr, val) *((vuint32*)(regs + addr)) = val
#define INREG(addr) INREG32(addr)
#define OUTREG(addr, val) OUTREG32(addr, val)
static inline uint8 ReadCrtc(uint8 index)
{
OUTREG8(VGA_CRTC_INDEX, index);
return INREG8(VGA_CRTC_DATA);
}
static inline void WriteCrtc(uint8 index, uint8 value)
{
OUTREG8(VGA_CRTC_INDEX, index);
OUTREG8(VGA_CRTC_DATA, value);
}
static inline uint8 ReadSeq(uint8 index)
{
OUTREG8(VGA_SEQ_INDEX, index);
return INREG8(VGA_SEQ_DATA);
}
static inline void WriteSeq(uint8 index, uint8 value)
{
OUTREG8(VGA_SEQ_INDEX, index);
OUTREG8(VGA_SEQ_DATA, value);
}
static inline uint8 ReadST01()
{
return INREG8(VGA_IN_STAT_1);
}
/*
* unprotect CRTC[0-7]
* CR11_7 = 0: Writing to all CRT Controller registers enabled
* = 1: Writing to all bits of CR0~CR7 except CR7_4 disabled
*/
static inline void UnProtectCRTC()
{
unsigned char byte;
OUTREG8(VGA_CRTC_INDEX, 0x11);
byte = INREG8(VGA_CRTC_DATA) & 0x7F;
OUTREG16(VGA_CRTC_INDEX, byte << 8 | 0x11);
}
/*
* unlock extended regs
* CR38:unlock CR20~CR3F
* CR39:unlock CR40~CRFF
* SR08:unlock SR09~SRFF
*/
static inline void UnLockExtRegs()
{
OUTREG16(VGA_CRTC_INDEX, 0x4838);
OUTREG16(VGA_CRTC_INDEX, 0xA039);
OUTREG16(VGA_SEQ_INDEX, 0x0608);
}
static inline void VerticalRetraceWait()
{
INREG8(VGA_CRTC_INDEX);
OUTREG8(VGA_CRTC_INDEX, 0x17);
if (INREG8(VGA_CRTC_DATA) & 0x80)
{
int i = 0x10000;
while ((INREG8(SYSTEM_CONTROL_REG) & 0x08) == 0x08 && i--) ;
i = 0x10000;
while ((INREG8(SYSTEM_CONTROL_REG) & 0x08) == 0x00 && i--) ;
}
}
typedef struct
{
display_timing timing; // CRTC info
int bpp; // bits/pixel
int width; // screen width in pixels
int bytesPerRow; // number of bytes in one line/row
} DisplayMode;
bool SavageLoadCursorImage(int width, int height, uint8* and_mask, uint8* xor_mask);
void SavageSetCursorColors(int bg, int fg);
void SavageSetCursorPosition(int x, int y);
void SavageShowCursor(void);
void SavageHideCursor(void);
bool SavageDPMS(int mode);
bool SavagePreInit(void);
bool SavageModeInit(DisplayMode* pMode);
void SavageInitialize2DEngine(DisplayMode* pMode);
void SavageSetGBD(DisplayMode* pMode);
void SavageAdjustFrame(int x, int y);
#endif // __SAVAGE_H__
@@ -0,0 +1,768 @@
/*
Haiku S3 Savage driver adapted from the X.org Savage driver.
Copyright 1995-1997 The XFree86 Project, Inc.
Copyright 2007 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2006-2007
*/
#include "GlobalData.h"
#include "AccelerantPrototypes.h"
#include "savage.h"
static void
SavageSetGBD_Twister(DisplayMode* pMode)
{
uint32 ulTmp;
uint8 byte;
int bci_enable;
TRACE(("SavageSetGBD_Twister\n"));
if (si->chipset == S3_SAVAGE4)
bci_enable = BCI_ENABLE;
else
bci_enable = BCI_ENABLE_TWISTER;
/* MM81C0 and 81C4 are used to control primary stream. */
OUTREG32(PRI_STREAM_FBUF_ADDR0, 0);
OUTREG32(PRI_STREAM_FBUF_ADDR1, 0);
/*
* Program Primary Stream Stride Register.
*
* Tell engine if tiling on or off, set primary stream stride, and
* if tiling, set tiling bits/pixel and primary stream tile offset.
* Note that tile offset (bits 16 - 29) must be scanline width in
* bytes/128bytespertile * 256 Qwords/tile. This is equivalent to
* lDelta * 2. Remember that if tiling, lDelta is screenwidth in
* bytes padded up to an even number of tilewidths.
*/
OUTREG32(PRI_STREAM_STRIDE,
(((pMode->bytesPerRow * 2) << 16) & 0x3FFFE000) |
(pMode->bytesPerRow & 0x00001fff));
/*
* CR69, bit 7 = 1
* to use MM streams processor registers to control primary stream.
*/
OUTREG8(VGA_CRTC_INDEX, 0x69);
byte = INREG8(VGA_CRTC_DATA) | 0x80;
OUTREG8(VGA_CRTC_DATA, byte);
OUTREG32(0x8128, 0xFFFFFFFFL);
OUTREG32(0x812C, 0xFFFFFFFFL);
OUTREG32(S3_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
/* CR50, bit 7,6,0 = 111, Use GBD.*/
OUTREG8(VGA_CRTC_INDEX, 0x50);
byte = INREG8(VGA_CRTC_DATA) | 0xC1;
OUTREG8(VGA_CRTC_DATA, byte);
/*
* if MS1NB style linear tiling mode.
* bit MM850C[15] = 0 select NB linear tile mode.
* bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode.
*/
ulTmp = INREG32(ADVANCED_FUNC_CTRL) | 0x8000; /* use MS-s style tile mode*/
OUTREG32(ADVANCED_FUNC_CTRL, ulTmp);
/*
* Set up Tiled Surface Registers
* Bit 25:20 - Surface width in tiles.
* Bit 29 - Y Range Flag.
* Bit 31:30 = 00, 4 bpp.
* = 01, 8 bpp.
* = 10, 16 bpp.
* = 11, 32 bpp.
*/
/*
* Global Bitmap Descriptor Register MM816C - twister/prosavage
* bit 24~25: tile format
* 00: linear
* 01: destination tiling format
* 10: texture tiling format
* 11: reserved
* bit 28: block write disble/enable
* 0: disable
* 1: enable
*/
/*
* Global Bitmap Descriptor Register MM816C - savage4
* bit 24~25: tile format
* 00: linear
* 01: reserved
* 10: 16 bpp tiles
* 11: 32 bpp tiles
* bit 28: block write disable/enable
* 0: enable
* 1: disable
*/
/*
* Do not enable block_write even for non-tiling modes, because
* the driver cannot determine if the memory type is the certain
* type of SGRAM for which block_write can be used.
*/
si->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; /* linear */
si->GlobalBD.bd1.HighPart.ResBWTile |= 0x10; /* disable block write */
/* HW uses width */
si->GlobalBD.bd1.HighPart.Stride = (uint16) (pMode->width); // number of pixels per line
si->GlobalBD.bd1.HighPart.Bpp = (uint8) (pMode->bpp);
si->GlobalBD.bd1.Offset = si->frameBufferOffset;
/*
* CR88, bit 4 - Block write enabled/disabled.
*
* Note: Block write must be disabled when writing to tiled
* memory. Even when writing to non-tiled memory, block
* write should only be enabled for certain types of SGRAM.
*/
OUTREG8(VGA_CRTC_INDEX, 0x88);
byte = INREG8(VGA_CRTC_DATA) | DISABLE_BLOCK_WRITE_2D;
OUTREG8(VGA_CRTC_DATA, byte);
/*
* CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
* bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
* at A000:0.
*/
OUTREG8(VGA_CRTC_INDEX, MEMORY_CONFIG_REG); /* cr31 */
byte = INREG8(VGA_CRTC_DATA) & (~(ENABLE_CPUA_BASE_A0000));
OUTREG8(VGA_CRTC_DATA, byte); /* perhaps this should be 0x0c */
/* turn on screen */
OUTREG8(VGA_SEQ_INDEX, 0x01);
byte = INREG8(VGA_SEQ_DATA) & ~0x20;
OUTREG8(VGA_SEQ_DATA, byte);
/* program the GBD and SBD's */
OUTREG32(S3_GLB_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_GLB_BD_HIGH, si->GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
OUTREG32(S3_PRI_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_PRI_BD_HIGH, si->GlobalBD.bd2.HiPart);
}
static void
SavageSetGBD_3D(DisplayMode* pMode)
{
uint32 ulTmp;
uint8 byte;
int bci_enable;
TRACE(("SavageSetGBD_3D\n"));
bci_enable = BCI_ENABLE;
/* MM81C0 and 81C4 are used to control primary stream. */
OUTREG32(PRI_STREAM_FBUF_ADDR0, 0);
OUTREG32(PRI_STREAM_FBUF_ADDR1, 0);
/*
* Program Primary Stream Stride Register.
*
* Tell engine if tiling on or off, set primary stream stride, and
* if tiling, set tiling bits/pixel and primary stream tile offset.
* Note that tile offset (bits 16 - 29) must be scanline width in
* bytes/128bytespertile * 256 Qwords/tile. This is equivalent to
* lDelta * 2. Remember that if tiling, lDelta is screenwidth in
* bytes padded up to an even number of tilewidths.
*/
OUTREG32(PRI_STREAM_STRIDE,
(((pMode->bytesPerRow * 2) << 16) & 0x3FFFE000) |
(pMode->bytesPerRow & 0x00001fff));
/*
* CR69, bit 7 = 1
* to use MM streams processor registers to control primary stream.
*/
OUTREG8(VGA_CRTC_INDEX, 0x69);
byte = INREG8(VGA_CRTC_DATA) | 0x80;
OUTREG8(VGA_CRTC_DATA, byte);
OUTREG32(0x8128, 0xFFFFFFFFL);
OUTREG32(0x812C, 0xFFFFFFFFL);
OUTREG32(S3_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
/* CR50, bit 7,6,0 = 111, Use GBD.*/
OUTREG8(VGA_CRTC_INDEX, 0x50);
byte = INREG8(VGA_CRTC_DATA) | 0xC1;
OUTREG8(VGA_CRTC_DATA, byte);
/*
* if MS1NB style linear tiling mode.
* bit MM850C[15] = 0 select NB linear tile mode.
* bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode.
*/
ulTmp = INREG32(ADVANCED_FUNC_CTRL) | 0x8000; /* use MS-s style tile mode*/
OUTREG32(ADVANCED_FUNC_CTRL, ulTmp);
/*
* Tiled Surface 0 Registers MM48C40:
* bit 0~23: tile surface 0 frame buffer offset
* bit 24~29:tile surface 0 width
* bit 30~31:tile surface 0 bits/pixel
* 00: reserved
* 01, 8 bits
* 10, 16 Bits.
* 11, 32 Bits.
*/
/*
* Global Bitmap Descriptor Register MM816C
* bit 24~25: tile format
* 00: linear
* 01: reserved
* 10: 16 bpp tiles
* 11: 32 bpp tiles
* bit 28: block write disable/enable
* 0: enable
* 1: disable
*/
/*
* Do not enable block_write even for non-tiling modes, because
* the driver cannot determine if the memory type is the certain
* type of SGRAM for which block_write can be used.
*/
si->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; /* linear */
si->GlobalBD.bd1.HighPart.ResBWTile |= 0x10; /* disable block write */
/* HW uses width */
si->GlobalBD.bd1.HighPart.Stride = (uint16) (pMode->width); // number of pixels per line
si->GlobalBD.bd1.HighPart.Bpp = (uint8) (pMode->bpp);
si->GlobalBD.bd1.Offset = si->frameBufferOffset;
/*
* CR88, bit 4 - Block write enabled/disabled.
*
* Note: Block write must be disabled when writing to tiled
* memory. Even when writing to non-tiled memory, block
* write should only be enabled for certain types of SGRAM.
*/
OUTREG8(VGA_CRTC_INDEX, 0x88);
byte = INREG8(VGA_CRTC_DATA) | DISABLE_BLOCK_WRITE_2D;
OUTREG8(VGA_CRTC_DATA, byte);
/*
* CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
* bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
* at A000:0.
*/
OUTREG8(VGA_CRTC_INDEX, MEMORY_CONFIG_REG); /* cr31 */
byte = INREG8(VGA_CRTC_DATA) & (~(ENABLE_CPUA_BASE_A0000));
OUTREG8(VGA_CRTC_DATA, byte); /* perhaps this should be 0x0c */
/* turn on screen */
OUTREG8(VGA_SEQ_INDEX, 0x01);
byte = INREG8(VGA_SEQ_DATA) & ~0x20;
OUTREG8(VGA_SEQ_DATA, byte);
/* program the GBD and SBD's */
OUTREG32(S3_GLB_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_GLB_BD_HIGH, si->GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
OUTREG32(S3_PRI_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_PRI_BD_HIGH, si->GlobalBD.bd2.HiPart);
}
static void
SavageSetGBD_M7(DisplayMode* pMode)
{
uint8 byte;
int bci_enable;
TRACE(("SavageSetGBD_M7\n"));
bci_enable = BCI_ENABLE;
/* following is the enable case */
/* SR01:turn off screen */
OUTREG8 (VGA_SEQ_INDEX, 0x01);
byte = INREG8(VGA_SEQ_DATA) | 0x20;
OUTREG8(VGA_SEQ_DATA, byte);
/*
* CR67_3:
* = 1 stream processor MMIO address and stride register
* are used to control the primary stream
* = 0 standard VGA address and stride registers
* are used to control the primary streams
*/
OUTREG8(VGA_CRTC_INDEX, 0x67);
byte = INREG8(VGA_CRTC_DATA) | 0x08;
OUTREG8(VGA_CRTC_DATA, byte);
/* IGA 2 */
OUTREG16(VGA_SEQ_INDEX, SELECT_IGA2_READS_WRITES);
OUTREG8(VGA_CRTC_INDEX, 0x67);
byte = INREG8(VGA_CRTC_DATA) | 0x08;
OUTREG8(VGA_CRTC_DATA, byte);
OUTREG16(VGA_SEQ_INDEX, SELECT_IGA1);
/* Set primary stream to bank 0 */
OUTREG8(VGA_CRTC_INDEX, MEMORY_CTRL0_REG); /* CRCA */
byte = INREG8(VGA_CRTC_DATA) & ~(MEM_PS1 + MEM_PS2) ;
OUTREG8(VGA_CRTC_DATA, byte);
/* MM81C0 and 81C4 are used to control primary stream. */
OUTREG32(PRI_STREAM_FBUF_ADDR0, si->frameBufferOffset & 0x7fffff);
OUTREG32(PRI_STREAM_FBUF_ADDR1, si->frameBufferOffset & 0x7fffff);
OUTREG32(PRI_STREAM2_FBUF_ADDR0, si->frameBufferOffset & 0x7fffff);
OUTREG32(PRI_STREAM2_FBUF_ADDR1, si->frameBufferOffset & 0x7fffff);
/*
* Program Primary Stream Stride Register.
*
* Tell engine if tiling on or off, set primary stream stride, and
* if tiling, set tiling bits/pixel and primary stream tile offset.
* Note that tile offset (bits 16 - 29) must be scanline width in
* bytes/128bytespertile * 256 Qwords/tile. This is equivalent to
* lDelta * 2. Remember that if tiling, lDelta is screenwidth in
* bytes padded up to an even number of tilewidths.
*/
OUTREG32(PRI_STREAM_STRIDE,
(((pMode->bytesPerRow * 2) << 16) & 0x3FFF0000) |
(pMode->bytesPerRow & 0x00003fff));
OUTREG32(PRI_STREAM2_STRIDE,
(((pMode->bytesPerRow * 2) << 16) & 0x3FFF0000) |
(pMode->bytesPerRow & 0x00003fff));
OUTREG32(0x8128, 0xFFFFFFFFL);
OUTREG32(0x812C, 0xFFFFFFFFL);
OUTREG32(S3_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
/* CR50, bit 7,6,0 = 111, Use GBD.*/
OUTREG8(VGA_CRTC_INDEX, 0x50);
byte = INREG8(VGA_CRTC_DATA) | 0xC1;
OUTREG8(VGA_CRTC_DATA, byte);
/*
* CR78, bit 3 - Block write enabled(1)/disabled(0).
* bit 2 - Block write cycle time(0:2 cycles,1: 1 cycle)
* Note: Block write must be disabled when writing to tiled
* memory. Even when writing to non-tiled memory, block
* write should only be enabled for certain types of SGRAM.
*/
OUTREG8(VGA_CRTC_INDEX, 0x78);
byte = INREG8(VGA_CRTC_DATA) | 0xfb;
OUTREG8(VGA_CRTC_DATA, byte);
/*
* Tiled Surface 0 Registers MM48C40:
* bit 0~23: tile surface 0 frame buffer offset
* bit 24~29:tile surface 0 width
* bit 30~31:tile surface 0 bits/pixel
* 00: reserved
* 01, 8 bits
* 10, 16 Bits.
* 11, 32 Bits.
*/
/*
* Global Bitmap Descriptor Register MM816C
* bit 24~25: tile format
* 00: linear
* 01: reserved
* 10: 16 bit
* 11: 32 bit
* bit 28: block write disble/enable
* 0: enable
* 1: disable
*/
/*
* Do not enable block_write even for non-tiling modes, because
* the driver cannot determine if the memory type is the certain
* type of SGRAM for which block_write can be used.
*/
si->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; /* linear */
si->GlobalBD.bd1.HighPart.ResBWTile |= 0x10; /* disable block write */
/* HW uses width */
si->GlobalBD.bd1.HighPart.Stride = (uint16)(pMode->width); // number of pixels per line
si->GlobalBD.bd1.HighPart.Bpp = (uint8)(pMode->bpp);
si->GlobalBD.bd1.Offset = si->frameBufferOffset;
/*
* CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
* bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
* at A000:0.
*/
OUTREG8(VGA_CRTC_INDEX, MEMORY_CONFIG_REG); /* cr31 */
byte = (INREG8(VGA_CRTC_DATA) | 0x04) & 0xFE;
OUTREG8(VGA_CRTC_DATA, byte);
/* program the GBD and SBD's */
OUTREG32(S3_GLB_BD_LOW, si->GlobalBD.bd2.LoPart );
/* 8: bci enable */
OUTREG32(S3_GLB_BD_HIGH, (si->GlobalBD.bd2.HiPart
| bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
OUTREG32(S3_PRI_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_PRI_BD_HIGH, si->GlobalBD.bd2.HiPart);
OUTREG32(S3_SEC_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_SEC_BD_HIGH, si->GlobalBD.bd2.HiPart);
/* turn on screen */
OUTREG8(VGA_SEQ_INDEX, 0x01);
byte = INREG8(VGA_SEQ_DATA) & ~0x20;
OUTREG8(VGA_SEQ_DATA, byte);
}
static void
SavageSetGBD_PM(DisplayMode* pMode)
{
uint8 byte;
int bci_enable;
TRACE(("SavageSetGBD_PM\n"));
bci_enable = BCI_ENABLE_TWISTER;
/* following is the enable case */
/* SR01:turn off screen */
OUTREG8 (VGA_SEQ_INDEX, 0x01);
byte = INREG8(VGA_SEQ_DATA) | 0x20;
OUTREG8(VGA_SEQ_DATA, byte);
/*
* CR67_3:
* = 1 stream processor MMIO address and stride register
* are used to control the primary stream
* = 0 standard VGA address and stride registers
* are used to control the primary streams
*/
OUTREG8(VGA_CRTC_INDEX, 0x67);
byte = INREG8(VGA_CRTC_DATA) | 0x08;
OUTREG8(VGA_CRTC_DATA, byte);
/* IGA 2 */
OUTREG16(VGA_SEQ_INDEX, SELECT_IGA2_READS_WRITES);
OUTREG8(VGA_CRTC_INDEX, 0x67);
byte = INREG8(VGA_CRTC_DATA) | 0x08;
OUTREG8(VGA_CRTC_DATA, byte);
OUTREG16(VGA_SEQ_INDEX, SELECT_IGA1);
/*
* load ps1 active registers as determined by MM81C0/81C4
* load ps2 active registers as determined by MM81B0/81B4
*/
OUTREG8(VGA_CRTC_INDEX, 0x65);
byte = INREG8(VGA_CRTC_DATA) | 0x03;
OUTREG8(VGA_CRTC_DATA, byte);
/*
* Program Primary Stream Stride Register.
*
* Tell engine if tiling on or off, set primary stream stride, and
* if tiling, set tiling bits/pixel and primary stream tile offset.
* Note that tile offset (bits 16 - 29) must be scanline width in
* bytes/128bytespertile * 256 Qwords/tile. This is equivalent to
* lDelta * 2. Remember that if tiling, lDelta is screenwidth in
* bytes padded up to an even number of tilewidths.
*/
OUTREG32(PRI_STREAM_STRIDE,
(((pMode->bytesPerRow * 2) << 16) & 0x3FFF0000) |
(pMode->bytesPerRow & 0x00001fff));
OUTREG32(PRI_STREAM2_STRIDE,
(((pMode->bytesPerRow * 2) << 16) & 0x3FFF0000) |
(pMode->bytesPerRow & 0x00001fff));
/* MM81C0 and 81C4 are used to control primary stream. */
OUTREG32(PRI_STREAM_FBUF_ADDR0, si->frameBufferOffset);
OUTREG32(PRI_STREAM_FBUF_ADDR1, 0x80000000);
OUTREG32(PRI_STREAM2_FBUF_ADDR0, (si->frameBufferOffset & 0xfffffffc) | 0x80000000);
OUTREG32(PRI_STREAM2_FBUF_ADDR1, si->frameBufferOffset & 0xfffffffc);
OUTREG32(0x8128, 0xFFFFFFFFL);
OUTREG32(0x812C, 0xFFFFFFFFL);
/* bit 28:block write disable */
OUTREG32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000);
/* CR50, bit 7,6,0 = 111, Use GBD.*/
OUTREG8(VGA_CRTC_INDEX, 0x50);
byte = INREG8(VGA_CRTC_DATA) | 0xC1;
OUTREG8(VGA_CRTC_DATA, byte);
/*
* Do not enable block_write even for non-tiling modes, because
* the driver cannot determine if the memory type is the certain
* type of SGRAM for which block_write can be used.
*/
si->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; /* linear */
si->GlobalBD.bd1.HighPart.ResBWTile |= 0x10; /* disable block write */
/* HW uses width */
si->GlobalBD.bd1.HighPart.Stride = (uint16) (pMode->width); // number of pixels per line
si->GlobalBD.bd1.HighPart.Bpp = (uint8) (pMode->bpp);
si->GlobalBD.bd1.Offset = si->frameBufferOffset;
/*
* CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
* bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
* at A000:0.
*/
OUTREG8(VGA_CRTC_INDEX, MEMORY_CONFIG_REG);
byte = INREG8(VGA_CRTC_DATA) & (~(ENABLE_CPUA_BASE_A0000));
OUTREG8(VGA_CRTC_DATA, byte);
/* program the GBD and SBDs */
OUTREG32(S3_GLB_BD_LOW, si->GlobalBD.bd2.LoPart );
OUTREG32(S3_GLB_BD_HIGH, (si->GlobalBD.bd2.HiPart
| bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
OUTREG32(S3_PRI_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_PRI_BD_HIGH, si->GlobalBD.bd2.HiPart);
OUTREG32(S3_SEC_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_SEC_BD_HIGH, si->GlobalBD.bd2.HiPart);
/* turn on screen */
OUTREG8(VGA_SEQ_INDEX, 0x01);
byte = INREG8(VGA_SEQ_DATA) & ~0x20;
OUTREG8(VGA_SEQ_DATA, byte);
}
static void
SavageSetGBD_2000(DisplayMode* pMode)
{
uint32 ulYRange;
uint8 byte;
int bci_enable;
TRACE(("SavageSetGBD_2000\n"));
bci_enable = BCI_ENABLE_TWISTER;
if (pMode->width > 1024)
ulYRange = 0x40000000;
else
ulYRange = 0x20000000;
/* following is the enable case */
/* SR01:turn off screen */
OUTREG8 (VGA_SEQ_INDEX, 0x01);
byte = INREG8(VGA_SEQ_DATA) | 0x20;
OUTREG8(VGA_SEQ_DATA, byte);
/* MM81C0 and 81B0 are used to control primary stream. */
OUTREG32(PRI_STREAM_FBUF_ADDR0, si->frameBufferOffset);
OUTREG32(PRI_STREAM2_FBUF_ADDR0, si->frameBufferOffset);
/*
* Program Primary Stream Stride Register.
*
* Tell engine if tiling on or off, set primary stream stride, and
* if tiling, set tiling bits/pixel and primary stream tile offset.
* Note that tile offset (bits 16 - 29) must be scanline width in
* bytes/128bytespertile * 256 Qwords/tile. This is equivalent to
* lDelta * 2. Remember that if tiling, lDelta is screenwidth in
* bytes padded up to an even number of tilewidths.
*/
OUTREG32(PRI_STREAM_STRIDE, ((pMode->bytesPerRow << 4) & 0x7ff0));
OUTREG32(PRI_STREAM2_STRIDE, ((pMode->bytesPerRow << 4) & 0x7ff0));
/*
* CR67_3:
* = 1 stream processor MMIO address and stride register
* are used to control the primary stream
* = 0 standard VGA address and stride registers
* are used to control the primary streams
*/
OUTREG8(VGA_CRTC_INDEX, 0x67);
byte = INREG8(VGA_CRTC_DATA) | 0x08;
OUTREG8(VGA_CRTC_DATA, byte);
OUTREG32(0x8128, 0xFFFFFFFFL);
OUTREG32(0x812C, 0xFFFFFFFFL);
/* bit 28:block write disable */
OUTREG32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000);
/* CR50, bit 7,6,0 = 111, Use GBD.*/
OUTREG8(VGA_CRTC_INDEX, 0x50);
byte = INREG8(VGA_CRTC_DATA) | 0xC1;
OUTREG8(VGA_CRTC_DATA, byte);
/* CR73 bit 5 = 0 block write disable */
OUTREG8(VGA_CRTC_INDEX, 0x73);
byte = INREG8(VGA_CRTC_DATA) & ~0x20;
OUTREG8(VGA_CRTC_DATA, byte);
/*
* Do not enable block_write even for non-tiling modes, because
* the driver cannot determine if the memory type is the certain
* type of SGRAM for which block_write can be used.
*/
si->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; /* linear */
si->GlobalBD.bd1.HighPart.ResBWTile |= 0x10; /* disable block write */
/* HW uses width */
si->GlobalBD.bd1.HighPart.Stride = (uint16) (pMode->width); // number of pixels per line
si->GlobalBD.bd1.HighPart.Bpp = (uint8) (pMode->bpp);
si->GlobalBD.bd1.Offset = si->frameBufferOffset;
/*
* CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
* bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
* at A000:0.
*/
OUTREG8(VGA_CRTC_INDEX, MEMORY_CONFIG_REG);
byte = INREG8(VGA_CRTC_DATA) & (~(ENABLE_CPUA_BASE_A0000));
OUTREG8(VGA_CRTC_DATA, byte);
/* program the GBD and SBDs */
OUTREG32(S3_GLB_BD_LOW, si->GlobalBD.bd2.LoPart );
OUTREG32(S3_GLB_BD_HIGH, (si->GlobalBD.bd2.HiPart
| bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
OUTREG32(S3_PRI_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_PRI_BD_HIGH, si->GlobalBD.bd2.HiPart);
OUTREG32(S3_SEC_BD_LOW, si->GlobalBD.bd2.LoPart);
OUTREG32(S3_SEC_BD_HIGH, si->GlobalBD.bd2.HiPart);
/* turn on screen */
OUTREG8(VGA_SEQ_INDEX, 0x01);
byte = INREG8(VGA_SEQ_DATA) & ~0x20;
OUTREG8(VGA_SEQ_DATA, byte);
}
void
SavageSetGBD(DisplayMode* pMode)
{
TRACE(("SavageSetGBD\n"));
UnProtectCRTC();
UnLockExtRegs();
VerticalRetraceWait();
switch (si->chipset) {
case S3_SAVAGE3D:
SavageSetGBD_3D(pMode);
break;
case S3_SAVAGE_MX:
SavageSetGBD_M7(pMode);
break;
case S3_SAVAGE4:
case S3_PROSAVAGE:
case S3_TWISTER:
case S3_PROSAVAGEDDR:
SavageSetGBD_Twister(pMode);
break;
case S3_SUPERSAVAGE:
SavageSetGBD_PM(pMode);
break;
case S3_SAVAGE2000:
SavageSetGBD_2000(pMode);
break;
}
}
void
SavageInitialize2DEngine(DisplayMode* pMode)
{
uint32 thresholds;
TRACE(("SavageInitialize2DEngine\n"));
OUTREG16(VGA_CRTC_INDEX, 0x0140);
OUTREG8(VGA_CRTC_INDEX, 0x31);
OUTREG8(VGA_CRTC_DATA, 0x0c);
/* Setup plane masks */
OUTREG(0x8128, ~0); /* enable all write planes */
OUTREG(0x812C, ~0); /* enable all read planes */
OUTREG16(0x8134, 0x27);
OUTREG16(0x8136, 0x07);
switch (si->chipset) {
case S3_SAVAGE3D:
case S3_SAVAGE_MX:
/* Disable BCI */
OUTREG(0x48C18, INREG(0x48C18) & 0x3FF0);
/* Setup BCI command overflow buffer */
OUTREG(0x48C14, (si->cobOffset >> 11) | (si->cobIndex << 29)); /* tim */
/* Program shadow status update. */
thresholds = ((si->bciThresholdLo & 0xffff) << 16) |
(si->bciThresholdHi & 0xffff);
OUTREG(0x48C10, thresholds);
OUTREG(0x48C0C, 0);
/* Enable BCI and command overflow buffer */
OUTREG(0x48C18, INREG(0x48C18) | 0x0C);
break;
case S3_SAVAGE4:
case S3_PROSAVAGE:
case S3_TWISTER:
case S3_PROSAVAGEDDR:
case S3_SUPERSAVAGE:
/* Disable BCI */
OUTREG(0x48C18, INREG(0x48C18) & 0x3FF0);
if (!si->bDisableCOB) {
/* Setup BCI command overflow buffer */
OUTREG(0x48C14, (si->cobOffset >> 11) | (si->cobIndex << 29));
}
/* Program shadow status update */ /* AGD: what should this be? */
thresholds = ((si->bciThresholdLo & 0x1fffe0) << 11)
| ((si->bciThresholdHi & 0x1fffe0) >> 5);
OUTREG(0x48C10, thresholds);
OUTREG(0x48C0C, 0);
if (si->bDisableCOB)
OUTREG(0x48C18, INREG(0x48C18) | 0x08); // enable BCI without COB
else
OUTREG(0x48C18, INREG(0x48C18) | 0x0C); // enable BCI with COB
break;
case S3_SAVAGE2000:
/* Disable BCI */
OUTREG(0x48C18, 0);
/* Setup BCI command overflow buffer */
OUTREG(0x48C18, (si->cobOffset >> 7) | (si->cobIndex));
/* Disable shadow status update */
OUTREG(0x48A30, 0);
/* Enable BCI and command overflow buffer */
OUTREG(0x48C18, INREG(0x48C18) | 0x00280000 );
break;
}
/* Use and set global bitmap descriptor. */
/* For reasons I do not fully understand yet, on the Savage4, the */
/* write to the GBD register, MM816C, does not "take" at this time. */
/* Only the low-order byte is acknowledged, resulting in an incorrect */
/* stride. Writing the register later, after the mode switch, works */
/* correctly. This needs to get resolved. */
SavageSetGBD(pMode);
}
@@ -0,0 +1,209 @@
/*
Haiku S3 Savage driver adapted from the original BeSavage driver by
Erdi Chen and the X.org Savage driver.
Copyright 1999 Erdi Chen
Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
Copyright (c) 2003-2006, X.Org Foundation
Copyright 2007 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2006-2007
*/
#include "GlobalData.h"
#include "savage.h"
// Certain HW cursor operations seem to require a delay to prevent lockups.
static void
WaitHSync(int n)
{
while (n--) {
while ((ReadST01()) & 0x01) {};
while (!(ReadST01()) & 0x01) {};
}
}
void
SavageHideCursor(void)
{
/* Turn cursor off. */
if (S3_SAVAGE4_SERIES(si->chipset))
WaitHSync(5);
WriteCrtc(0x45, ReadCrtc(0x45) & 0xfe);
si->cursor.bIsVisible = false;
}
void
SavageShowCursor(void)
{
/* Turn cursor on. */
WriteCrtc(0x45, ReadCrtc(0x45) | 0x01);
si->cursor.bIsVisible = true;
}
void
SavageSetCursorPosition(int x, int y)
{
uint8 xoff, yoff;
if (S3_SAVAGE4_SERIES(si->chipset))
WaitHSync(5);
/* adjust for frame buffer base address granularity */
if (si->bitsPerPixel == 8)
x += ((si->frameX0) & 3);
else if (si->bitsPerPixel == 16)
x += ((si->frameX0) & 1);
else if (si->bitsPerPixel == 32)
x += ((si->frameX0 + 2) & 3) - 2;
/*
* Make these even when used. There is a bug/feature on at least
* some chipsets that causes a "shadow" of the cursor in interlaced
* mode. Making this even seems to have no visible effect, so just
* do it for the generic case.
*/
if (x < 0) {
xoff = (( -x) & 0xFE);
x = 0;
} else {
xoff = 0;
}
if (y < 0) {
yoff = (( -y) & 0xFE);
y = 0;
} else {
yoff = 0;
}
/* This is the recomended order to move the cursor */
WriteCrtc( 0x46, (x & 0xff00) >> 8 );
WriteCrtc( 0x47, (x & 0xff) );
WriteCrtc( 0x49, (y & 0xff) );
WriteCrtc( 0x4e, xoff );
WriteCrtc( 0x4f, yoff );
WriteCrtc( 0x48, (y & 0xff00) >> 8 );
}
void
SavageSetCursorColors(int bg, int fg)
{
/* With the streams engine on HW Cursor seems to be 24bpp ALWAYS */
//@ TRACE(("SavageSetCursorColors\n"));
/* Do it straight, full 24 bit color. */
/* Reset the cursor color stack pointer */
ReadCrtc(0x45);
/* Write low, mid, high bytes - foreground */
WriteCrtc(0x4a, fg);
WriteCrtc(0x4a, fg >> 8);
WriteCrtc(0x4a, fg >> 16);
/* Reset the cursor color stack pointer */
ReadCrtc(0x45);
/* Write low, mid, high bytes - background */
WriteCrtc(0x4b, bg);
WriteCrtc(0x4b, bg >> 8);
WriteCrtc(0x4b, bg >> 16);
}
/* Assume width and height are byte-aligned. */
bool
SavageLoadCursorImage(int width, int height, uint8* and_mask, uint8* xor_mask)
{
int i, x, y, bit_shift;
uint8 and_buf[64*64 / 8];
uint8 xor_buf[64*64 / 8];
uint8* and_ptr = and_mask;
uint8* xor_ptr = xor_mask;
uint16* pFB;
//@ TRACE(("SavageLoadCursorImage\n"));
if ( ! and_mask || ! xor_mask)
return false;
bit_shift = width & 7;
width /= 8;
if (width != 64 || height != 64) {
and_ptr = (uint8*)and_buf;
xor_ptr = (uint8*)xor_buf;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
*and_ptr++ = *and_mask++;
*xor_ptr++ = *xor_mask++;
}
if (bit_shift) {
x++;
*and_ptr++ = 0xFF ^ ((*and_mask++) & (~(0xFF >> bit_shift)));
*xor_ptr++ = (*xor_mask++) & (~(0xFF >> bit_shift));
}
for (; x < 8; x++) {
*and_ptr++ = 0xFF;
*xor_ptr++ = 0x00;
}
}
for (; y < 64; y++) {
*(uint32 *)and_ptr = ~0;
and_ptr += 4;
*(uint32 *)and_ptr = ~0;
and_ptr += 4;
*(uint32 *)xor_ptr = 0;
xor_ptr += 4;
*(uint32 *)xor_ptr = 0;
xor_ptr += 4;
}
and_ptr = (uint8 *)and_buf;
xor_ptr = (uint8 *)xor_buf;
}
/* Set cursor location in video memory. */
WriteCrtc(0x4d, (0xff & si->cursorOffset / 1024));
WriteCrtc(0x4c, (0xff00 & si->cursorOffset / 1024) >> 8);
pFB = (void *)((addr_t)si->videoMemAddr + si->cursorOffset);
for (i = 0; i < 64 * 64 / 16; i++) {
*pFB++ = *(uint16*)and_ptr;
*pFB++ = *(uint16*)xor_ptr;
and_ptr += 2;
xor_ptr += 2;
}
if (S3_SAVAGE4_SERIES(si->chipset)) {
/*
* Bug in Savage4 Rev B requires us to do an MMIO read after
* loading the cursor.
*/
volatile unsigned int k = ALT_STATUS_WORD0;
(void)k++; /* Not to be optimised out */
}
return true;
}
@@ -0,0 +1,133 @@
/*
Haiku S3 Savage driver adapted from the X.org Savage driver.
Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
Copyright (c) 2003-2006, X.Org Foundation
Copyright 2007 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2006-2007
*/
#include "GlobalData.h"
#include "AccelerantPrototypes.h"
#include "savage.h"
status_t
SET_DPMS_MODE(uint32 dpmsMode)
{
// Set the display into one of the Display Power Management modes,
// and return B_OK if successful, else return B_ERROR.
uint8 sr8 = 0x00, srd = 0x00;
TRACE(("SET_DPMS_MODE, mode: %d, display type: %d\n", dpmsMode, si->displayType));
if (si->displayType == MT_CRT) {
OUTREG8(VGA_SEQ_INDEX, 0x08);
sr8 = INREG8(VGA_SEQ_DATA);
sr8 |= 0x06;
OUTREG8(VGA_SEQ_DATA, sr8);
OUTREG8(VGA_SEQ_INDEX, 0x0d);
srd = INREG8(VGA_SEQ_DATA);
srd &= 0x03;
switch (dpmsMode) {
case B_DPMS_ON:
break;
case B_DPMS_STAND_BY:
srd |= 0x10;
break;
case B_DPMS_SUSPEND:
srd |= 0x40;
break;
case B_DPMS_OFF:
srd |= 0x50;
break;
default:
TRACE(("Invalid DPMS mode %d\n", dpmsMode));
return B_ERROR;
}
OUTREG8(VGA_SEQ_INDEX, 0x0d);
OUTREG8(VGA_SEQ_DATA, srd);
} else if (si->displayType == MT_LCD || si->displayType == MT_DFP) {
switch (dpmsMode) {
case B_DPMS_ON:
OUTREG8(VGA_SEQ_INDEX, 0x31); /* SR31 bit 4 - FP enable */
OUTREG8(VGA_SEQ_DATA, INREG8(VGA_SEQ_DATA) | 0x10);
break;
case B_DPMS_STAND_BY:
case B_DPMS_SUSPEND:
case B_DPMS_OFF:
OUTREG8(VGA_SEQ_INDEX, 0x31); /* SR31 bit 4 - FP enable */
OUTREG8(VGA_SEQ_DATA, INREG8(VGA_SEQ_DATA) & ~0x10);
break;
default:
TRACE(("Invalid DPMS mode %d\n", dpmsMode));
return B_ERROR;
}
}
return B_OK;
}
uint32
DPMS_CAPABILITIES (void)
{
// Return DPMS modes supported by this device.
return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF;
}
uint32
DPMS_MODE (void)
{
// Return the current DPMS mode.
// Note: I do not know whether the following code is correctly reading
// the current DPMS mode. I'm assuming that reading back the bits that
// were set by function SET_DPMS_MODE will give the current DPMS mode.
uint32 mode = B_DPMS_ON;
uint8 srd;
if (si->displayType == MT_CRT) {
OUTREG8(VGA_SEQ_INDEX, 0x0d);
srd = INREG8(VGA_SEQ_DATA);
switch (srd & 0x70) {
case 0:
mode = B_DPMS_ON;
break;
case 0x10:
mode = B_DPMS_STAND_BY;
break;
case 0x40:
mode = B_DPMS_SUSPEND;
break;
case 0x50:
mode = B_DPMS_OFF;
break;
default:
TRACE(("Unknown DPMS mode read from device %X\n", srd));
}
} else if (si->displayType == MT_LCD || si->displayType == MT_DFP) {
OUTREG8(VGA_SEQ_INDEX, 0x31); /* SR31 bit 4 - FP enable */
srd = INREG8(VGA_SEQ_DATA);
mode = ((srd & 0x10) ? B_DPMS_ON : B_DPMS_OFF);
}
TRACE(("DPMS_MODE = %d\n", mode));
return mode;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff