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:
@@ -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)
|
||||||
|
|||||||
+7
-3
@@ -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
|
||||||
@@ -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 ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 **)®s, B_ANY_ADDRESS,
|
regsArea = clone_area("SAVAGE regs area", (void**)®s, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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__ */
|
|
||||||
@@ -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 */
|
|
||||||
@@ -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__ */
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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__ */
|
|
||||||
@@ -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__ */
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
Reference in New Issue
Block a user