Commit 90a214c4 authored by Sam Lantinga's avatar Sam Lantinga

Nobody has stepped up to maintain a framebuffer console driver. Bye bye! :)

parent c14d8951
......@@ -1420,33 +1420,6 @@ AC_HELP_STRING([--enable-video-cocoa], [use Cocoa video driver [[default=yes]]])
fi
}
dnl Find the framebuffer console includes
CheckFBCON()
{
AC_ARG_ENABLE(video-fbcon,
AC_HELP_STRING([--enable-video-fbcon], [use framebuffer console video driver [[default=no]]]),
, enable_video_fbcon=no)
if test x$enable_video = xyes -a x$enable_video_fbcon = xyes; then
AC_MSG_CHECKING(for framebuffer console support)
video_fbcon=no
AC_TRY_COMPILE([
#include <linux/fb.h>
#include <linux/kd.h>
#include <linux/keyboard.h>
],[
],[
video_fbcon=yes
])
AC_MSG_RESULT($video_fbcon)
if test x$video_fbcon = xyes; then
AC_CHECK_FUNCS(getpagesize)
AC_DEFINE(SDL_VIDEO_DRIVER_FBCON)
SOURCES="$SOURCES $srcdir/src/video/fbcon/*.c"
have_video=yes
fi
fi
}
dnl Find DirectFB
CheckDirectFB()
{
......@@ -2300,7 +2273,6 @@ case "$host" in
CheckESD
CheckNAS
CheckX11
CheckFBCON
CheckDirectFB
CheckFusionSound
CheckPS3
......
......@@ -261,7 +261,6 @@
#undef SDL_VIDEO_DRIVER_DIRECTFB
#undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC
#undef SDL_VIDEO_DRIVER_DUMMY
#undef SDL_VIDEO_DRIVER_FBCON
#undef SDL_VIDEO_DRIVER_NDS
#undef SDL_VIDEO_DRIVER_PHOTON
#undef SDL_VIDEO_DRIVER_QNXGF
......
......@@ -408,9 +408,6 @@ extern VideoBootStrap COCOA_bootstrap;
#if SDL_VIDEO_DRIVER_X11
extern VideoBootStrap X11_bootstrap;
#endif
#if SDL_VIDEO_DRIVER_FBCON
extern VideoBootStrap FBCON_bootstrap;
#endif
#if SDL_VIDEO_DRIVER_DIRECTFB
extern VideoBootStrap DirectFB_bootstrap;
#endif
......
......@@ -62,9 +62,6 @@ static VideoBootStrap *bootstrap[] = {
#if SDL_VIDEO_DRIVER_X11
&X11_bootstrap,
#endif
#if SDL_VIDEO_DRIVER_FBCON
&FBCON_bootstrap,
#endif
#if SDL_VIDEO_DRIVER_DIRECTFB
&DirectFB_bootstrap,
#endif
......
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* 3Dfx register definitions */
#include "3dfx_regs.h"
/* 3Dfx control macros */
#define tdfx_in8(reg) *(volatile Uint8 *)(mapped_io + (reg))
#define tdfx_in32(reg) *(volatile Uint32 *)(mapped_io + (reg))
#define tdfx_out8(reg,v) *(volatile Uint8 *)(mapped_io + (reg)) = v;
#define tdfx_out32(reg,v) *(volatile Uint32 *)(mapped_io + (reg)) = v;
/* Wait for fifo space */
#define tdfx_wait(space) \
{ \
while ( (tdfx_in8(TDFX_STATUS) & 0x1F) < space ) \
; \
}
/* Wait for idle accelerator */
#define tdfx_waitidle() \
{ \
int i = 0; \
\
tdfx_wait(1); \
tdfx_out32(COMMAND_3D, COMMAND_3D_NOP); \
do { \
i = (tdfx_in32(TDFX_STATUS) & STATUS_BUSY) ? 0 : i + 1; \
} while ( i != 3 ); \
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#ifndef _3DFX_REGS_H
#define _3DFX_REGS_H
/* This information comes from the public 3Dfx specs for the Voodoo 3000 */
/* mapped_io register offsets */
#define TDFX_STATUS 0x00
#define INTCTRL (0x00100000 + 0x04)
#define CLIP0MIN (0x00100000 + 0x08)
#define CLIP0MAX (0x00100000 + 0x0c)
#define DSTBASE (0x00100000 + 0x10)
#define DSTFORMAT (0x00100000 + 0x14)
#define SRCCOLORKEYMIN (0x00100000 + 0x18)
#define SRCCOLORKEYMAX (0x00100000 + 0x1c)
#define DSTCOLORKEYMIN (0x00100000 + 0x20)
#define DSTCOLORKEYMAX (0x00100000 + 0x24)
#define BRESERROR0 (0x00100000 + 0x28)
#define BRESERROR1 (0x00100000 + 0x2c)
#define ROP_2D (0x00100000 + 0x30)
#define SRCBASE (0x00100000 + 0x34)
#define COMMANDEXTRA_2D (0x00100000 + 0x38)
#define PATTERN0 (0x00100000 + 0x44)
#define PATTERN1 (0x00100000 + 0x48)
#define CLIP1MIN (0x00100000 + 0x4c)
#define CLIP1MAX (0x00100000 + 0x50)
#define SRCFORMAT (0x00100000 + 0x54)
#define SRCSIZE (0x00100000 + 0x58)
#define SRCXY (0x00100000 + 0x5c)
#define COLORBACK (0x00100000 + 0x60)
#define COLORFORE (0x00100000 + 0x64)
#define DSTSIZE (0x00100000 + 0x68)
#define DSTXY (0x00100000 + 0x6c)
#define COMMAND_2D (0x00100000 + 0x70)
#define LAUNCH_2D (0x00100000 + 0x80)
#define PATTERNBASE (0x00100000 + 0x100)
#define COMMAND_3D (0x00200000 + 0x120)
/* register bitfields (not all, only as needed) */
#define BIT(x) (1UL << (x))
#define COMMAND_2D_BITBLT 0x01
#define COMMAND_2D_FILLRECT 0x05
#define COMMAND_2D_LINE 0x06
#define COMMAND_2D_POLYGON_FILL 0x08
#define COMMAND_2D_INITIATE BIT(8)
#define COMMAND_2D_REVERSELINE BIT(9)
#define COMMAND_2D_STIPPLELINE BIT(12)
#define COMMAND_2D_MONOCHROME_PATT BIT(13)
#define COMMAND_2D_MONOCHROME_TRANSP BIT(16)
#define COMMAND_3D_NOP 0x00
#define STATUS_RETRACE BIT(6)
#define STATUS_BUSY BIT(9)
#endif /* _3DFX_REGS_H */
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include "SDL_video.h"
#include "../SDL_blit.h"
#include "SDL_fb3dfx.h"
#include "3dfx_mmio.h"
/* Wait for vertical retrace */
static void
WaitVBL(_THIS)
{
/* find start of retrace */
tdfx_waitidle();
while ((tdfx_in32(TDFX_STATUS) & STATUS_RETRACE) == STATUS_RETRACE);
/* wait until we're past the start */
while ((tdfx_in32(TDFX_STATUS) & STATUS_RETRACE) == 0);
}
static void
WaitIdle(_THIS)
{
tdfx_waitidle();
}
/* Sets video mem colorkey and accelerated blit function */
static int
SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key)
{
return (0);
}
static int
FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * rect, Uint32 color)
{
int bpp;
char *dst_base;
Uint32 format;
int dstX, dstY;
/* Don't blit to the display surface when switched away */
if (switched_away) {
return -2; /* no hardware access */
}
if (dst == this->screen) {
SDL_mutexP(hw_lock);
}
/* Set the destination pixel format */
dst_base = (char *) ((char *) dst->pixels - mapped_mem);
bpp = dst->format->BitsPerPixel;
format = dst->pitch | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
/* Calculate source and destination base coordinates */
dstX = rect->x;
dstY = rect->y;
/* Execute the fill command */
tdfx_wait(6);
tdfx_out32(DSTBASE, (Uint32) dst_base);
tdfx_out32(DSTFORMAT, format);
tdfx_out32(COLORFORE, color);
tdfx_out32(COMMAND_2D, COMMAND_2D_FILLRECT);
tdfx_out32(DSTSIZE, rect->w | (rect->h << 16));
tdfx_out32(LAUNCH_2D, dstX | (dstY << 16));
FB_AddBusySurface(dst);
if (dst == this->screen) {
SDL_mutexV(hw_lock);
}
return (0);
}
static int
HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect)
{
SDL_VideoDevice *this = current_video;
int bpp;
Uint32 src_format;
Uint32 dst_format;
char *src_base;
char *dst_base;
int srcX, srcY;
int dstX, dstY;
Uint32 blitop;
Uint32 use_colorkey;
/* Don't blit to the display surface when switched away */
if (switched_away) {
return -2; /* no hardware access */
}
if (dst == this->screen) {
SDL_mutexP(hw_lock);
}
/* Set the source and destination pixel format */
src_base = (char *) ((char *) src->pixels - mapped_mem);
bpp = src->format->BitsPerPixel;
src_format = src->pitch | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
dst_base = (char *) ((char *) dst->pixels - mapped_mem);
bpp = dst->format->BitsPerPixel;
dst_format = dst->pitch | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
srcX = srcrect->x;
srcY = srcrect->y;
dstX = dstrect->x;
dstY = dstrect->y;
/* Assemble the blit operation */
blitop = COMMAND_2D_BITBLT | (0xCC << 24);
if (srcX <= dstX) {
blitop |= BIT(14);
srcX += (dstrect->w - 1);
dstX += (dstrect->w - 1);
}
if (srcY <= dstY) {
blitop |= BIT(15);
srcY += (dstrect->h - 1);
dstY += (dstrect->h - 1);
}
/* Perform the blit! */
if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
tdfx_wait(3);
tdfx_out32(SRCCOLORKEYMIN, src->format->colorkey);
tdfx_out32(SRCCOLORKEYMAX, src->format->colorkey);
tdfx_out32(ROP_2D, 0xAA00);
use_colorkey = 1;
} else {
use_colorkey = 0;
}
tdfx_wait(9);
tdfx_out32(SRCBASE, (Uint32) src_base);
tdfx_out32(SRCFORMAT, src_format);
tdfx_out32(DSTBASE, (Uint32) dst_base);
tdfx_out32(DSTFORMAT, src_format);
tdfx_out32(COMMAND_2D, blitop);
tdfx_out32(COMMANDEXTRA_2D, use_colorkey);
tdfx_out32(DSTSIZE, dstrect->w | (dstrect->h << 16));
tdfx_out32(DSTXY, dstX | (dstY << 16));
tdfx_out32(LAUNCH_2D, srcX | (srcY << 16));
FB_AddBusySurface(src);
FB_AddBusySurface(dst);
if (dst == this->screen) {
SDL_mutexV(hw_lock);
}
return (0);
}
static int
CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst)
{
int accelerated;
/* Set initial acceleration on */
src->flags |= SDL_HWACCEL;
/* Set the surface attributes */
if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
if (!this->info.blit_hw_A) {
src->flags &= ~SDL_HWACCEL;
}
}
if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
if (!this->info.blit_hw_CC) {
src->flags &= ~SDL_HWACCEL;
}
}
/* Check to see if final surface blit is accelerated */
accelerated = !!(src->flags & SDL_HWACCEL);
if (accelerated) {
src->map->hw_blit = HWAccelBlit;
}
return (accelerated);
}
void
FB_3DfxAccel(_THIS, __u32 card)
{
/* We have hardware accelerated surface functions */
this->CheckHWBlit = CheckHWBlit;
wait_vbl = WaitVBL;
wait_idle = WaitIdle;
/* Reset the 3Dfx controller */
tdfx_out32(BRESERROR0, 0);
tdfx_out32(BRESERROR1, 0);
/* The 3Dfx has an accelerated color fill */
this->info.blit_fill = 1;
this->FillHWRect = FillHWRect;
/* The 3Dfx has accelerated normal and colorkey blits */
this->info.blit_hw = 1;
this->info.blit_hw_CC = 1;
this->SetHWColorKey = SetHWColorKey;
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* 3Dfx hardware acceleration for the SDL framebuffer console driver */
#include "SDL_fbvideo.h"
/* Set up the driver for 3Dfx acceleration */
extern void FB_3DfxAccel(_THIS, __u32 card);
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include <unistd.h>
#include <sys/time.h>
#include <ctype.h>
#include "SDL_stdinc.h"
#include "SDL_fbvideo.h"
#include "SDL_fbelo.h"
/*
calibration default values
values are read from the following environment variables:
SDL_ELO_MIN_X
SDL_ELO_MAX_X
SDL_ELO_MIN_Y
SDL_ELO_MAX_Y
*/
static int ELO_MIN_X = 400;
static int ELO_MAX_X = 3670;
static int ELO_MIN_Y = 500;
static int ELO_MAX_Y = 3540;
#define ELO_SNAP_SIZE 6
#define ELO_TOUCH_BYTE 'T'
#define ELO_ID 'I'
#define ELO_MODE 'M'
#define ELO_PARAMETER 'P'
#define ELO_REPORT 'B'
#define ELO_ACK 'A'
#define ELO_INIT_CHECKSUM 0xAA
#define ELO_BTN_PRESS 0x01
#define ELO_STREAM 0x02
#define ELO_BTN_RELEASE 0x04
#define ELO_TOUCH_MODE 0x01
#define ELO_STREAM_MODE 0x02
#define ELO_UNTOUCH_MODE 0x04
#define ELO_RANGE_CHECK_MODE 0x40
#define ELO_TRIM_MODE 0x02
#define ELO_CALIB_MODE 0x04
#define ELO_SCALING_MODE 0x08
#define ELO_TRACKING_MODE 0x40
#define ELO_SERIAL_MASK 0xF8
#define ELO_SERIAL_IO '0'
#define ELO_MAX_TRIALS 3
#define ELO_MAX_WAIT 100000
#define ELO_UNTOUCH_DELAY 5
#define ELO_REPORT_DELAY 1
/* eloParsePacket
*/
int
eloParsePacket(unsigned char *mousebuf, int *dx, int *dy, int *button_state)
{
static int elo_button = 0;
static int last_x = 0;
static int last_y = 0;
int x, y;
/* Check if we have a touch packet */
if (mousebuf[1] != ELO_TOUCH_BYTE) {
return 0;
}
x = ((mousebuf[4] << 8) | mousebuf[3]);
y = ((mousebuf[6] << 8) | mousebuf[5]);
if ((SDL_abs(x - last_x) > ELO_SNAP_SIZE)
|| (SDL_abs(y - last_y) > ELO_SNAP_SIZE)) {
*dx = ((mousebuf[4] << 8) | mousebuf[3]);
*dy = ((mousebuf[6] << 8) | mousebuf[5]);
} else {
*dx = last_x;
*dy = last_y;
}
last_x = *dx;
last_y = *dy;
if ((mousebuf[2] & 0x07) == ELO_BTN_PRESS) {
elo_button = 1;
}
if ((mousebuf[2] & 0x07) == ELO_BTN_RELEASE) {
elo_button = 0;
}
*button_state = elo_button;
return 1;
}
/* Convert the raw coordinates from the ELO controller
to a screen position.
*/
void
eloConvertXY(_THIS, int *dx, int *dy)
{
int input_x = *dx;
int input_y = *dy;
int width = ELO_MAX_X - ELO_MIN_X;
int height = ELO_MAX_Y - ELO_MIN_Y;
*dx =
((int) cache_vinfo.xres -
((int) cache_vinfo.xres * (input_x - ELO_MIN_X)) / width);
*dy = (cache_vinfo.yres * (input_y - ELO_MIN_Y)) / height;
}
/* eloGetPacket
*/
int
eloGetPacket(unsigned char *buffer, int *buffer_p, int *checksum, int fd)
{
int num_bytes;
int ok;
if (fd == 0) {
num_bytes = ELO_PACKET_SIZE;
} else {
num_bytes = read(fd,
(char *) (buffer + *buffer_p),
ELO_PACKET_SIZE - *buffer_p);
}
if (num_bytes < 0) {
#ifdef DEBUG_MOUSE
fprintf(stderr,
"System error while reading from Elographics touchscreen.\n");
#endif
return 0;
}
while (num_bytes) {
if ((*buffer_p == 0) && (buffer[0] != ELO_START_BYTE)) {
SDL_memcpy(&buffer[0], &buffer[1], num_bytes - 1);
} else {
if (*buffer_p < ELO_PACKET_SIZE - 1) {
*checksum = *checksum + buffer[*buffer_p];
*checksum = *checksum % 256;
}
(*buffer_p)++;
}
num_bytes--;
}
if (*buffer_p == ELO_PACKET_SIZE) {
ok = (*checksum == buffer[ELO_PACKET_SIZE - 1]);
*checksum = ELO_INIT_CHECKSUM;
*buffer_p = 0;
if (!ok) {
return 0;
}
return 1;
} else {
return 0;
}
}
/* eloSendPacket
*/
int
eloSendPacket(unsigned char *packet, int fd)
{
int i, result;
int sum = ELO_INIT_CHECKSUM;
packet[0] = ELO_START_BYTE;
for (i = 0; i < ELO_PACKET_SIZE - 1; i++) {
sum += packet[i];
sum &= 0xFF;
}
packet[ELO_PACKET_SIZE - 1] = sum;
result = write(fd, packet, ELO_PACKET_SIZE);
if (result != ELO_PACKET_SIZE) {
#ifdef DEBUG_MOUSE
printf("System error while sending to Elographics touchscreen.\n");
#endif
return 0;
} else {
return 1;
}
}
/* eloWaitForInput
*/
int
eloWaitForInput(int fd, int timeout)
{
fd_set readfds;
struct timeval to;
int r;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
to.tv_sec = 0;
to.tv_usec = timeout;
r = select(FD_SETSIZE, &readfds, NULL, NULL, &to);
return r;
}
/* eloWaitReply
*/
int
eloWaitReply(unsigned char type, unsigned char *reply, int fd)
{
int ok;
int i, result;
int reply_p = 0;
int sum = ELO_INIT_CHECKSUM;
i = ELO_MAX_TRIALS;
do {
ok = 0;
result = eloWaitForInput(fd, ELO_MAX_WAIT);
if (result > 0) {
ok = eloGetPacket(reply, &reply_p, &sum, fd);
if (ok && reply[1] != type && type != ELO_PARAMETER) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Wrong reply received\n");
#endif
ok = 0;
}
} else {
#ifdef DEBUG_MOUSE
fprintf(stderr, "No input!\n");
#endif
}
if (result == 0) {
i--;
}
} while (!ok && (i > 0));
return ok;
}
/* eloWaitAck
*/
int
eloWaitAck(int fd)
{
unsigned char packet[ELO_PACKET_SIZE];
int i, nb_errors;
if (eloWaitReply(ELO_ACK, packet, fd)) {
for (i = 0, nb_errors = 0; i < 4; i++) {
if (packet[2 + i] != '0') {
nb_errors++;
}
}
if (nb_errors != 0) {
#ifdef DEBUG_MOUSE
fprintf(stderr,
"Elographics acknowledge packet reports %d errors\n",
nb_errors);
#endif
}
return 1;
} else {
return 0;
}
}
/* eloSendQuery --
*/
int
eloSendQuery(unsigned char *request, unsigned char *reply, int fd)
{
int ok;
if (eloSendPacket(request, fd)) {
ok = eloWaitReply(toupper(request[1]), reply, fd);
if (ok) {
ok = eloWaitAck(fd);
}
return ok;
} else {
return 0;
}
}
/* eloSendControl
*/
int
eloSendControl(unsigned char *control, int fd)
{
if (eloSendPacket(control, fd)) {
return eloWaitAck(fd);
} else {
return 0;
}
}
/* eloInitController
*/
int
eloInitController(int fd)
{
unsigned char req[ELO_PACKET_SIZE];
unsigned char reply[ELO_PACKET_SIZE];
const char *buffer = NULL;
int result = 0;
struct termios mouse_termios;
/* try to read the calibration values */
buffer = SDL_getenv("SDL_ELO_MIN_X");
if (buffer) {
ELO_MIN_X = SDL_atoi(buffer);
}
buffer = SDL_getenv("SDL_ELO_MAX_X");
if (buffer) {
ELO_MAX_X = SDL_atoi(buffer);
}
buffer = SDL_getenv("SDL_ELO_MIN_Y");
if (buffer) {
ELO_MIN_Y = SDL_atoi(buffer);
}
buffer = SDL_getenv("SDL_ELO_MAX_Y");
if (buffer) {
ELO_MAX_Y = SDL_atoi(buffer);
}
#ifdef DEBUG_MOUSE
fprintf(stderr,
"ELO calibration values:\nmin_x: %i\nmax_x: %i\nmin_y: %i\nmax_y: %i\n",
ELO_MIN_X, ELO_MAX_X, ELO_MIN_Y, ELO_MAX_Y);
#endif
/* set comm params */
SDL_memset(&mouse_termios, 0, sizeof(mouse_termios));
mouse_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
mouse_termios.c_cc[VMIN] = 1;
result = tcsetattr(fd, TCSANOW, &mouse_termios);
if (result < 0) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Unable to configure Elographics touchscreen port\n");
#endif
return 0;
}
SDL_memset(req, 0, ELO_PACKET_SIZE);
req[1] = tolower(ELO_PARAMETER);
if (!eloSendQuery(req, reply, fd)) {
#ifdef DEBUG_MOUSE
fprintf(stderr,
"Not at the specified rate or model 2310, will continue\n");
#endif
}
SDL_memset(req, 0, ELO_PACKET_SIZE);
req[1] = tolower(ELO_ID);
if (eloSendQuery(req, reply, fd)) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Ok, controller configured!\n");
#endif
} else {
#ifdef DEBUG_MOUSE
fprintf(stderr,
"Unable to ask Elographics touchscreen identification\n");
#endif
return 0;
}
SDL_memset(req, 0, ELO_PACKET_SIZE);
req[1] = ELO_MODE;
req[3] = ELO_TOUCH_MODE | ELO_STREAM_MODE | ELO_UNTOUCH_MODE;
req[4] = ELO_TRACKING_MODE;
if (!eloSendControl(req, fd)) {
#ifdef DEBUG_MOUSE
fprintf(stderr,
"Unable to change Elographics touchscreen operating mode\n");
#endif
return 0;
}
SDL_memset(req, 0, ELO_PACKET_SIZE);
req[1] = ELO_REPORT;
req[2] = ELO_UNTOUCH_DELAY;
req[3] = ELO_REPORT_DELAY;
if (!eloSendControl(req, fd)) {
#ifdef DEBUG_MOUSE
fprintf(stderr,
"Unable to change Elographics touchscreen reports timings\n");
#endif
return 0;
}
return 1;
}
int
eloReadPosition(_THIS, int fd, int *x, int *y, int *button_state, int *realx,
int *realy)
{
unsigned char buffer[ELO_PACKET_SIZE];
int pointer = 0;
int checksum = ELO_INIT_CHECKSUM;
while (pointer < ELO_PACKET_SIZE) {
if (eloGetPacket(buffer, &pointer, &checksum, fd)) {
break;
}
}
if (!eloParsePacket(buffer, realx, realy, button_state)) {
return 0;
}
*x = *realx;
*y = *realy;
eloConvertXY(this, x, y);
return 1;
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#ifndef SDL_fbelo_h
#define SDL_fbelo_h
#include "SDL_fbvideo.h"
/* ELO */
#define ELO_PACKET_SIZE 10
#define ELO_START_BYTE 'U'
/* eloConvertXY
Convert the raw coordinates from the ELO controller
to a screen position.
*/
void eloConvertXY(_THIS, int *dx, int *dy);
/* eloInitController(int fd)
Initialize the ELO serial touchscreen controller
*/
int eloInitController(int fd);
/* eloParsePacket
extract position and button state from a packet
*/
int eloParsePacket(unsigned char *mousebuf, int *dx, int *dy,
int *button_state);
/* eloReadPosition
read a packet and get the cursor position
*/
int eloReadPosition(_THIS, int fd, int *x, int *y, int *button_state,
int *realx, int *realy);
#endif /* SDL_fbelo_h */
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* Handle the event stream, converting console events into SDL events */
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
/* For parsing /proc */
#include <dirent.h>
#include <ctype.h>
#include <linux/vt.h>
#include <linux/kd.h>
#include <linux/keyboard.h>
#include "SDL_timer.h"
#include "SDL_mutex.h"
#include "../SDL_sysvideo.h"
#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
#include "SDL_fbvideo.h"
#include "SDL_fbevents_c.h"
#include "SDL_fbkeys.h"
#include "SDL_fbelo.h"
#ifndef GPM_NODE_FIFO
#define GPM_NODE_FIFO "/dev/gpmdata"
#endif
/*#define DEBUG_KEYBOARD*/
/*#define DEBUG_MOUSE*/
/* The translation tables from a console scancode to a SDL keysym */
#define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT)
static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];
static SDLKey keymap[128];
static Uint16 keymap_temp[128]; /* only used at startup */
static SDL_keysym *TranslateKey(int scancode, SDL_keysym * keysym);
/* Ugh, we have to duplicate the kernel's keysym mapping code...
Oh, it's not so bad. :-)
FIXME: Add keyboard LED handling code
*/
static void
FB_vgainitkeymaps(int fd)
{
struct kbentry entry;
int map, i;
/* Don't do anything if we are passed a closed keyboard */
if (fd < 0) {
return;
}
/* Load all the keysym mappings */
for (map = 0; map < NUM_VGAKEYMAPS; ++map) {
SDL_memset(vga_keymap[map], 0, NR_KEYS * sizeof(Uint16));
for (i = 0; i < NR_KEYS; ++i) {
entry.kb_table = map;
entry.kb_index = i;
if (ioctl(fd, KDGKBENT, &entry) == 0) {
/* fill keytemp. This replaces SDL_fbkeys.h */
if ((map == 0) && (i < 128)) {
keymap_temp[i] = entry.kb_value;
}
/* The "Enter" key is a special case */
if (entry.kb_value == K_ENTER) {
entry.kb_value = K(KT_ASCII, 13);
}
/* Handle numpad specially as well */
if (KTYP(entry.kb_value) == KT_PAD) {
switch (entry.kb_value) {
case K_P0:
case K_P1:
case K_P2:
case K_P3:
case K_P4:
case K_P5:
case K_P6:
case K_P7:
case K_P8:
case K_P9:
vga_keymap[map][i] = entry.kb_value;
vga_keymap[map][i] += '0';
break;
case K_PPLUS:
vga_keymap[map][i] = K(KT_ASCII, '+');
break;
case K_PMINUS:
vga_keymap[map][i] = K(KT_ASCII, '-');
break;
case K_PSTAR:
vga_keymap[map][i] = K(KT_ASCII, '*');
break;
case K_PSLASH:
vga_keymap[map][i] = K(KT_ASCII, '/');
break;
case K_PENTER:
vga_keymap[map][i] = K(KT_ASCII, '\r');
break;
case K_PCOMMA:
vga_keymap[map][i] = K(KT_ASCII, ',');
break;
case K_PDOT:
vga_keymap[map][i] = K(KT_ASCII, '.');
break;
default:
break;
}
}
/* Do the normal key translation */
if ((KTYP(entry.kb_value) == KT_LATIN) ||
(KTYP(entry.kb_value) == KT_ASCII) ||
(KTYP(entry.kb_value) == KT_LETTER)) {
vga_keymap[map][i] = entry.kb_value;
}
}
}
}
}
int
FB_InGraphicsMode(_THIS)
{
return ((keyboard_fd >= 0) && (saved_kbd_mode >= 0));
}
int
FB_EnterGraphicsMode(_THIS)
{
struct termios keyboard_termios;
/* Set medium-raw keyboard mode */
if ((keyboard_fd >= 0) && !FB_InGraphicsMode(this)) {
/* Switch to the correct virtual terminal */
if (current_vt > 0) {
struct vt_stat vtstate;
if (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) {
saved_vt = vtstate.v_active;
}
if (ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0) {
ioctl(keyboard_fd, VT_WAITACTIVE, current_vt);
}
}
/* Set the terminal input mode */
if (tcgetattr(keyboard_fd, &saved_kbd_termios) < 0) {
SDL_SetError("Unable to get terminal attributes");
if (keyboard_fd > 0) {
close(keyboard_fd);
}
keyboard_fd = -1;
return (-1);
}
if (ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0) {
SDL_SetError("Unable to get current keyboard mode");
if (keyboard_fd > 0) {
close(keyboard_fd);
}
keyboard_fd = -1;
return (-1);
}
keyboard_termios = saved_kbd_termios;
keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
keyboard_termios.c_iflag &=
~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
keyboard_termios.c_cc[VMIN] = 0;
keyboard_termios.c_cc[VTIME] = 0;
if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) {
FB_CloseKeyboard(this);
SDL_SetError("Unable to set terminal attributes");
return (-1);
}
/* This will fail if we aren't root or this isn't our tty */
if (ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0) {
FB_CloseKeyboard(this);
SDL_SetError("Unable to set keyboard in raw mode");
return (-1);
}
if (ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0) {
FB_CloseKeyboard(this);
SDL_SetError("Unable to set keyboard in graphics mode");
return (-1);
}
/* Prevent switching the virtual terminal */
ioctl(keyboard_fd, VT_LOCKSWITCH, 1);
}
return (keyboard_fd);
}
void
FB_LeaveGraphicsMode(_THIS)
{
if (FB_InGraphicsMode(this)) {
ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);
tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
saved_kbd_mode = -1;
/* Head back over to the original virtual terminal */
ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1);
if (saved_vt > 0) {
ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
}
}
}
void
FB_CloseKeyboard(_THIS)
{
if (keyboard_fd >= 0) {
FB_LeaveGraphicsMode(this);
if (keyboard_fd > 0) {
close(keyboard_fd);
}
}
keyboard_fd = -1;
}
int
FB_OpenKeyboard(_THIS)
{
/* Open only if not already opened */
if (keyboard_fd < 0) {
static const char *const tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
static const char *const vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
int i, tty0_fd;
/* Try to query for a free virtual terminal */
tty0_fd = -1;
for (i = 0; tty0[i] && (tty0_fd < 0); ++i) {
tty0_fd = open(tty0[i], O_WRONLY, 0);
}
if (tty0_fd < 0) {
tty0_fd = dup(0); /* Maybe stdin is a VT? */
}
ioctl(tty0_fd, VT_OPENQRY, &current_vt);
close(tty0_fd);
if ((geteuid() == 0) && (current_vt > 0)) {
for (i = 0; vcs[i] && (keyboard_fd < 0); ++i) {
char vtpath[12];
SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i],
current_vt);
keyboard_fd = open(vtpath, O_RDWR, 0);
#ifdef DEBUG_KEYBOARD
fprintf(stderr, "vtpath = %s, fd = %d\n",
vtpath, keyboard_fd);
#endif /* DEBUG_KEYBOARD */
/* This needs to be our controlling tty
so that the kernel ioctl() calls work
*/
if (keyboard_fd >= 0) {
tty0_fd = open("/dev/tty", O_RDWR, 0);
if (tty0_fd >= 0) {
ioctl(tty0_fd, TIOCNOTTY, 0);
close(tty0_fd);
}
}
}
}
if (keyboard_fd < 0) {
/* Last resort, maybe our tty is a usable VT */
struct vt_stat vtstate;
keyboard_fd = open("/dev/tty", O_RDWR);
if (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) {
current_vt = vtstate.v_active;
} else {
current_vt = 0;
}
}
#ifdef DEBUG_KEYBOARD
fprintf(stderr, "Current VT: %d\n", current_vt);
#endif
saved_kbd_mode = -1;
/* Make sure that our input is a console terminal */
{
int dummy;
if (ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0) {
close(keyboard_fd);
keyboard_fd = -1;
SDL_SetError("Unable to open a console terminal");
}
}
/* Set up keymap */
FB_vgainitkeymaps(keyboard_fd);
}
return (keyboard_fd);
}
static enum
{
MOUSE_NONE = -1,
MOUSE_MSC, /* Note: GPM uses the MSC protocol */
MOUSE_PS2,
MOUSE_IMPS2,
MOUSE_MS,
MOUSE_BM,
MOUSE_ELO,
MOUSE_TSLIB,
NUM_MOUSE_DRVS
} mouse_drv = MOUSE_NONE;
void
FB_CloseMouse(_THIS)
{
#if SDL_INPUT_TSLIB
if (ts_dev != NULL) {
ts_close(ts_dev);
ts_dev = NULL;
mouse_fd = -1;
}
#endif /* SDL_INPUT_TSLIB */
if (mouse_fd > 0) {
close(mouse_fd);
}
mouse_fd = -1;
}
/* Returns processes listed in /proc with the desired name */
static int
find_pid(DIR * proc, const char *wanted_name)
{
struct dirent *entry;
int pid;
/* First scan proc for the gpm process */
pid = 0;
while ((pid == 0) && ((entry = readdir(proc)) != NULL)) {
if (isdigit(entry->d_name[0])) {
FILE *status;
char path[PATH_MAX];
char name[PATH_MAX];
SDL_snprintf(path, SDL_arraysize(path), "/proc/%s/status",
entry->d_name);
status = fopen(path, "r");
if (status) {
name[0] = '\0';
fscanf(status, "Name: %s", name);
if (SDL_strcmp(name, wanted_name) == 0) {
pid = SDL_atoi(entry->d_name);
}
fclose(status);
}
}
}
return pid;
}
/* Returns true if /dev/gpmdata is being written to by gpm */
static int
gpm_available(char *proto, size_t protolen)
{
int available;
DIR *proc;
int pid;
int cmdline, len, arglen;
char path[PATH_MAX];
char args[PATH_MAX], *arg;
/* Don't bother looking if the fifo isn't there */
#ifdef DEBUG_MOUSE
fprintf(stderr, "testing gpm\n");
#endif
if (access(GPM_NODE_FIFO, F_OK) < 0) {
return (0);
}
available = 0;
proc = opendir("/proc");
if (proc) {
char raw_proto[10] = { '\0' };
char repeat_proto[10] = { '\0' };
while (!available && (pid = find_pid(proc, "gpm")) > 0) {
SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid);
cmdline = open(path, O_RDONLY, 0);
if (cmdline >= 0) {
len = read(cmdline, args, sizeof(args));
arg = args;
while (len > 0) {
arglen = SDL_strlen(arg) + 1;
#ifdef DEBUG_MOUSE
fprintf(stderr, "gpm arg %s len %d\n", arg, arglen);
#endif
if (SDL_strcmp(arg, "-t") == 0) {
/* protocol string, keep it for later */
char *t, *s;
t = arg + arglen;
s = SDL_strchr(t, ' ');
if (s)
*s = 0;
SDL_strlcpy(raw_proto, t, SDL_arraysize(raw_proto));
if (s)
*s = ' ';
}
if (SDL_strncmp(arg, "-R", 2) == 0) {
char *t, *s;
available = 1;
t = arg + 2;
s = SDL_strchr(t, ' ');
if (s)
*s = 0;
SDL_strlcpy(repeat_proto, t,
SDL_arraysize(repeat_proto));
if (s)
*s = ' ';
}
len -= arglen;
arg += arglen;
}
close(cmdline);
}
}
closedir(proc);
if (available) {
if (SDL_strcmp(repeat_proto, "raw") == 0) {
SDL_strlcpy(proto, raw_proto, protolen);
} else if (*repeat_proto) {
SDL_strlcpy(proto, repeat_proto, protolen);
} else {
SDL_strlcpy(proto, "msc", protolen);
}
}
}
return available;
}
/* rcg06112001 Set up IMPS/2 mode, if possible. This gives
* us access to the mousewheel, etc. Returns zero if
* writes to device failed, but you still need to query the
* device to see which mode it's actually in.
*/
static int
set_imps2_mode(int fd)
{
/* If you wanted to control the mouse mode (and we do :) ) ...
Set IMPS/2 protocol:
{0xf3,200,0xf3,100,0xf3,80}
Reset mouse device:
{0xFF}
*/
Uint8 set_imps2[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
/*Uint8 reset = 0xff; */
fd_set fdset;
struct timeval tv;
int retval = 0;
if (write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2)) {
/* Don't reset it, that'll clear IMPS/2 mode on some mice
if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {
retval = 1;
}
*/
}
/* Get rid of any chatter from the above */
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = 0;
tv.tv_usec = 0;
while (select(fd + 1, &fdset, 0, 0, &tv) > 0) {
char temp[32];
read(fd, temp, sizeof(temp));
}
return retval;
}
/* Returns true if the mouse uses the IMPS/2 protocol */
static int
detect_imps2(int fd)
{
int imps2;
imps2 = 0;
if (SDL_getenv("SDL_MOUSEDEV_IMPS2")) {
imps2 = 1;
}
if (!imps2) {
Uint8 query_ps2 = 0xF2;
fd_set fdset;
struct timeval tv;
/* Get rid of any mouse motion noise */
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = 0;
tv.tv_usec = 0;
while (select(fd + 1, &fdset, 0, 0, &tv) > 0) {
char temp[32];
read(fd, temp, sizeof(temp));
}
/* Query for the type of mouse protocol */
if (write(fd, &query_ps2, sizeof(query_ps2)) == sizeof(query_ps2)) {
Uint8 ch = 0;
/* Get the mouse protocol response */
do {
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = 1;
tv.tv_usec = 0;
if (select(fd + 1, &fdset, 0, 0, &tv) < 1) {
break;
}
} while ((read(fd, &ch, sizeof(ch)) == sizeof(ch)) &&
((ch == 0xFA) || (ch == 0xAA)));
/* Experimental values (Logitech wheelmouse) */
#ifdef DEBUG_MOUSE
fprintf(stderr, "Last mouse mode: 0x%x\n", ch);
#endif
if ((ch == 3) || (ch == 4)) {
imps2 = 1;
}
}
}
return imps2;
}
int
FB_OpenMouse(_THIS)
{
int i;
const char *mousedev;
const char *mousedrv;
mousedrv = SDL_getenv("SDL_MOUSEDRV");
mousedev = SDL_getenv("SDL_MOUSEDEV");
mouse_fd = -1;
#if SDL_INPUT_TSLIB
if (mousedrv && (SDL_strcmp(mousedrv, "TSLIB") == 0)) {
if (mousedev == NULL)
mousedev = SDL_getenv("TSLIB_TSDEVICE");
if (mousedev != NULL) {
ts_dev = ts_open(mousedev, 1);
if ((ts_dev != NULL) && (ts_config(ts_dev) >= 0)) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using tslib touchscreen\n");
#endif
mouse_drv = MOUSE_TSLIB;
mouse_fd = ts_fd(ts_dev);
return mouse_fd;
}
}
mouse_drv = MOUSE_NONE;
return mouse_fd;
}
#endif /* SDL_INPUT_TSLIB */
/* ELO TOUCHSCREEN SUPPORT */
if (mousedrv && (SDL_strcmp(mousedrv, "ELO") == 0)) {
mouse_fd = open(mousedev, O_RDWR);
if (mouse_fd >= 0) {
if (eloInitController(mouse_fd)) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using ELO touchscreen\n");
#endif
mouse_drv = MOUSE_ELO;
}
} else if (mouse_fd < 0) {
mouse_drv = MOUSE_NONE;
}
return (mouse_fd);
}
/* STD MICE */
if (mousedev == NULL) {
/* FIXME someday... allow multiple mice in this driver */
static const char *ps2mice[] = {
"/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL
};
/* First try to use GPM in repeater mode */
if (mouse_fd < 0) {
char proto[10];
if (gpm_available(proto, SDL_arraysize(proto))) {
mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0);
if (mouse_fd >= 0) {
if (SDL_strcmp(proto, "msc") == 0) {
mouse_drv = MOUSE_MSC;
} else if (SDL_strcmp(proto, "ps2") == 0) {
mouse_drv = MOUSE_PS2;
} else if (SDL_strcmp(proto, "imps2") == 0) {
mouse_drv = MOUSE_IMPS2;
} else if (SDL_strcmp(proto, "ms") == 0 ||
SDL_strcmp(proto, "bare") == 0) {
mouse_drv = MOUSE_MS;
} else if (SDL_strcmp(proto, "bm") == 0) {
mouse_drv = MOUSE_BM;
} else {
/* Unknown protocol... */
#ifdef DEBUG_MOUSE
fprintf(stderr,
"GPM mouse using unknown protocol = %s\n",
proto);
#endif
close(mouse_fd);
mouse_fd = -1;
}
}
#ifdef DEBUG_MOUSE
if (mouse_fd >= 0) {
fprintf(stderr,
"Using GPM mouse, protocol = %s\n", proto);
}
#endif /* DEBUG_MOUSE */
}
}
/* Now try to use a modern PS/2 mouse */
for (i = 0; (mouse_fd < 0) && ps2mice[i]; ++i) {
mouse_fd = open(ps2mice[i], O_RDWR, 0);
if (mouse_fd < 0) {
mouse_fd = open(ps2mice[i], O_RDONLY, 0);
}
if (mouse_fd >= 0) {
/* rcg06112001 Attempt to set IMPS/2 mode */
set_imps2_mode(mouse_fd);
if (detect_imps2(mouse_fd)) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using IMPS2 mouse\n");
#endif
mouse_drv = MOUSE_IMPS2;
} else {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using PS2 mouse\n");
#endif
mouse_drv = MOUSE_PS2;
}
}
}
/* Next try to use a PPC ADB port mouse */
if (mouse_fd < 0) {
mouse_fd = open("/dev/adbmouse", O_RDONLY, 0);
if (mouse_fd >= 0) {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using ADB mouse\n");
#endif
mouse_drv = MOUSE_BM;
}
}
}
/* Default to a serial Microsoft mouse */
if (mouse_fd < 0) {
if (mousedev == NULL) {
mousedev = "/dev/mouse";
}
mouse_fd = open(mousedev, O_RDONLY, 0);
if (mouse_fd >= 0) {
struct termios mouse_termios;
/* Set the sampling speed to 1200 baud */
tcgetattr(mouse_fd, &mouse_termios);
mouse_termios.c_iflag = IGNBRK | IGNPAR;
mouse_termios.c_oflag = 0;
mouse_termios.c_lflag = 0;
mouse_termios.c_line = 0;
mouse_termios.c_cc[VTIME] = 0;
mouse_termios.c_cc[VMIN] = 1;
mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL;
mouse_termios.c_cflag |= CS8;
mouse_termios.c_cflag |= B1200;
tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios);
if (mousedrv && (SDL_strcmp(mousedrv, "PS2") == 0)) {
#ifdef DEBUG_MOUSE
fprintf(stderr,
"Using (user specified) PS2 mouse on %s\n", mousedev);
#endif
mouse_drv = MOUSE_PS2;
} else {
#ifdef DEBUG_MOUSE
fprintf(stderr, "Using (default) MS mouse on %s\n", mousedev);
#endif
mouse_drv = MOUSE_MS;
}
}
}
if (mouse_fd < 0) {
mouse_drv = MOUSE_NONE;
}
return (mouse_fd);
}
static int posted = 0;
void
FB_vgamousecallback(int button, int relative, int dx, int dy)
{
int button_1, button_3;
int button_state;
int state_changed;
int i;
Uint8 state;
if (dx || dy) {
posted += SDL_PrivateMouseMotion(0, relative, dx, dy);
}
/* Swap button 1 and 3 */
button_1 = (button & 0x04) >> 2;
button_3 = (button & 0x01) << 2;
button &= ~0x05;
button |= (button_1 | button_3);
/* See what changed */
button_state = SDL_GetMouseState(NULL, NULL);
state_changed = button_state ^ button;
for (i = 0; i < 8; ++i) {
if (state_changed & (1 << i)) {
if (button & (1 << i)) {
state = SDL_PRESSED;
} else {
state = SDL_RELEASED;
}
posted += SDL_PrivateMouseButton(state, i + 1, 0, 0);
}
}
}
/* Handle input from tslib */
#if SDL_INPUT_TSLIB
static void
handle_tslib(_THIS)
{
struct ts_sample sample;
int button;
while (ts_read(ts_dev, &sample, 1) > 0) {
button = (sample.pressure > 0) ? 1 : 0;
button <<= 2; /* must report it as button 3 */
FB_vgamousecallback(button, 0, sample.x, sample.y);
}
return;
}
#endif /* SDL_INPUT_TSLIB */
/* For now, use MSC, PS/2, and MS protocols
Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.)
*/
static void
handle_mouse(_THIS)
{
static int start = 0;
static unsigned char mousebuf[BUFSIZ];
static int relative = 1;
int i, nread;
int button = 0;
int dx = 0, dy = 0;
int packetsize = 0;
int realx, realy;
/* Figure out the mouse packet size */
switch (mouse_drv) {
case MOUSE_NONE:
/* Ack! */
read(mouse_fd, mousebuf, BUFSIZ);
return;
case MOUSE_MSC:
packetsize = 5;
break;
case MOUSE_IMPS2:
packetsize = 4;
break;
case MOUSE_PS2:
case MOUSE_MS:
case MOUSE_BM:
packetsize = 3;
break;
case MOUSE_ELO:
/* try to read the next packet */
if (eloReadPosition
(this, mouse_fd, &dx, &dy, &button, &realx, &realy)) {
button = (button & 0x01) << 2;
FB_vgamousecallback(button, 0, dx, dy);
}
return; /* nothing left to do */
case MOUSE_TSLIB:
#if SDL_INPUT_TSLIB
handle_tslib(this);
#endif
return; /* nothing left to do */
default:
/* Uh oh.. */
packetsize = 0;
break;
}
/* Special handling for the quite sensitive ELO controller */
if (mouse_drv == MOUSE_ELO) {
}
/* Read as many packets as possible */
nread = read(mouse_fd, &mousebuf[start], BUFSIZ - start);
if (nread < 0) {
return;
}
nread += start;
#ifdef DEBUG_MOUSE
fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start);
#endif
for (i = 0; i < (nread - (packetsize - 1)); i += packetsize) {
switch (mouse_drv) {
case MOUSE_NONE:
break;
case MOUSE_MSC:
/* MSC protocol has 0x80 in high byte */
if ((mousebuf[i] & 0xF8) != 0x80) {
/* Go to next byte */
i -= (packetsize - 1);
continue;
}
/* Get current mouse state */
button = (~mousebuf[i]) & 0x07;
dx = (signed char) (mousebuf[i + 1]) +
(signed char) (mousebuf[i + 3]);
dy = -((signed char) (mousebuf[i + 2]) +
(signed char) (mousebuf[i + 4]));
break;
case MOUSE_PS2:
/* PS/2 protocol has nothing in high byte */
if ((mousebuf[i] & 0xC0) != 0) {
/* Go to next byte */
i -= (packetsize - 1);
continue;
}
/* Get current mouse state */
button = (mousebuf[i] & 0x04) >> 1 | /*Middle */
(mousebuf[i] & 0x02) >> 1 | /*Right */
(mousebuf[i] & 0x01) << 2; /*Left */
dx = (mousebuf[i] & 0x10) ?
mousebuf[i + 1] - 256 : mousebuf[i + 1];
dy = (mousebuf[i] & 0x20) ?
-(mousebuf[i + 2] - 256) : -mousebuf[i + 2];
break;
case MOUSE_IMPS2:
/* Get current mouse state */
button = (mousebuf[i] & 0x04) >> 1 | /*Middle */
(mousebuf[i] & 0x02) >> 1 | /*Right */
(mousebuf[i] & 0x01) << 2 | /*Left */
(mousebuf[i] & 0x40) >> 3 | /* 4 */
(mousebuf[i] & 0x80) >> 3; /* 5 */
dx = (mousebuf[i] & 0x10) ?
mousebuf[i + 1] - 256 : mousebuf[i + 1];
dy = (mousebuf[i] & 0x20) ?
-(mousebuf[i + 2] - 256) : -mousebuf[i + 2];
switch (mousebuf[i + 3] & 0x0F) {
case 0x0E: /* DX = +1 */
case 0x02: /* DX = -1 */
break;
case 0x0F: /* DY = +1 (map button 4) */
FB_vgamousecallback(button | (1 << 3), 1, 0, 0);
break;
case 0x01: /* DY = -1 (map button 5) */
FB_vgamousecallback(button | (1 << 4), 1, 0, 0);
break;
}
break;
case MOUSE_MS:
/* Microsoft protocol has 0x40 in high byte */
if ((mousebuf[i] & 0x40) != 0x40) {
/* Go to next byte */
i -= (packetsize - 1);
continue;
}
/* Get current mouse state */
button = ((mousebuf[i] & 0x20) >> 3) |
((mousebuf[i] & 0x10) >> 4);
dx = (signed char) (((mousebuf[i] & 0x03) << 6) |
(mousebuf[i + 1] & 0x3F));
dy = (signed char) (((mousebuf[i] & 0x0C) << 4) |
(mousebuf[i + 2] & 0x3F));
break;
case MOUSE_BM:
/* BusMouse protocol has 0xF8 in high byte */
if ((mousebuf[i] & 0xF8) != 0x80) {
/* Go to next byte */
i -= (packetsize - 1);
continue;
}
/* Get current mouse state */
button = (~mousebuf[i]) & 0x07;
dx = (signed char) mousebuf[i + 1];
dy = -(signed char) mousebuf[i + 2];
break;
default:
/* Uh oh.. */
dx = 0;
dy = 0;
break;
}
FB_vgamousecallback(button, relative, dx, dy);
}
if (i < nread) {
SDL_memcpy(mousebuf, &mousebuf[i], (nread - i));
start = (nread - i);
} else {
start = 0;
}
return;
}
/* Handle switching to another VC, returns when our VC is back */
static void
switch_vt_prep(_THIS)
{
SDL_Surface *screen = SDL_VideoSurface;
SDL_PrivateAppActive(0,
(SDL_APPACTIVE | SDL_APPINPUTFOCUS |
SDL_APPMOUSEFOCUS));
/* Save the contents of the screen, and go to text mode */
wait_idle(this);
screen_arealen = ((screen->h + (2 * this->offset_y)) * screen->pitch);
screen_contents = (Uint8 *) SDL_malloc(screen_arealen);
if (screen_contents) {
SDL_memcpy(screen_contents, screen->pixels, screen_arealen);
}
FB_SavePaletteTo(this, 256, screen_palette);
ioctl(console_fd, FBIOGET_VSCREENINFO, &screen_vinfo);
ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1);
}
static void
switch_vt_done(_THIS)
{
SDL_Surface *screen = SDL_VideoSurface;
/* Restore graphics mode and the contents of the screen */
ioctl(keyboard_fd, VT_LOCKSWITCH, 1);
ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
ioctl(console_fd, FBIOPUT_VSCREENINFO, &screen_vinfo);
FB_RestorePaletteFrom(this, 256, screen_palette);
if (screen_contents) {
SDL_memcpy(screen->pixels, screen_contents, screen_arealen);
SDL_free(screen_contents);
screen_contents = NULL;
}
/* Get updates to the shadow surface while switched away */
if (SDL_ShadowSurface) {
SDL_UpdateRect(SDL_ShadowSurface, 0, 0, 0, 0);
}
SDL_PrivateAppActive(1,
(SDL_APPACTIVE | SDL_APPINPUTFOCUS |
SDL_APPMOUSEFOCUS));
}
static void
switch_vt(_THIS, unsigned short which)
{
struct vt_stat vtstate;
/* Figure out whether or not we're switching to a new console */
if ((ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
(which == vtstate.v_active)) {
return;
}
/* New console, switch to it */
SDL_mutexP(hw_lock);
switch_vt_prep(this);
if (ioctl(keyboard_fd, VT_ACTIVATE, which) == 0) {
ioctl(keyboard_fd, VT_WAITACTIVE, which);
switched_away = 1;
} else {
switch_vt_done(this);
}
SDL_mutexV(hw_lock);
}
static void
handle_keyboard(_THIS)
{
unsigned char keybuf[BUFSIZ];
int i, nread;
int pressed;
int scancode;
SDL_keysym keysym;
nread = read(keyboard_fd, keybuf, BUFSIZ);
for (i = 0; i < nread; ++i) {
scancode = keybuf[i] & 0x7F;
if (keybuf[i] & 0x80) {
pressed = SDL_RELEASED;
} else {
pressed = SDL_PRESSED;
}
TranslateKey(scancode, &keysym);
/* Handle Ctrl-Alt-FN for vt switch */
switch (keysym.sym) {
case SDLK_F1:
case SDLK_F2:
case SDLK_F3:
case SDLK_F4:
case SDLK_F5:
case SDLK_F6:
case SDLK_F7:
case SDLK_F8:
case SDLK_F9:
case SDLK_F10:
case SDLK_F11:
case SDLK_F12:
if ((SDL_GetModState() & KMOD_CTRL) &&
(SDL_GetModState() & KMOD_ALT)) {
if (pressed) {
switch_vt(this, (keysym.sym - SDLK_F1) + 1);
}
break;
}
/* Fall through to normal processing */
default:
posted += SDL_PrivateKeyboard(pressed, &keysym);
break;
}
}
}
void
FB_PumpEvents(_THIS)
{
fd_set fdset;
int max_fd;
static struct timeval zero;
do {
if (switched_away) {
struct vt_stat vtstate;
SDL_mutexP(hw_lock);
if ((ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) &&
vtstate.v_active == current_vt) {
switched_away = 0;
switch_vt_done(this);
}
SDL_mutexV(hw_lock);
}
posted = 0;
FD_ZERO(&fdset);
max_fd = 0;
if (keyboard_fd >= 0) {
FD_SET(keyboard_fd, &fdset);
if (max_fd < keyboard_fd) {
max_fd = keyboard_fd;
}
}
if (mouse_fd >= 0) {
FD_SET(mouse_fd, &fdset);
if (max_fd < mouse_fd) {
max_fd = mouse_fd;
}
}
if (select(max_fd + 1, &fdset, NULL, NULL, &zero) > 0) {
if (keyboard_fd >= 0) {
if (FD_ISSET(keyboard_fd, &fdset)) {
handle_keyboard(this);
}
}
if (mouse_fd >= 0) {
if (FD_ISSET(mouse_fd, &fdset)) {
handle_mouse(this);
}
}
}
} while (posted);
}
void
FB_InitOSKeymap(_THIS)
{
int i;
/* Initialize the Linux key translation table */
/* First get the ascii keys and others not well handled */
for (i = 0; i < SDL_arraysize(keymap); ++i) {
switch (i) {
/* These aren't handled by the x86 kernel keymapping (?) */
case SCANCODE_PRINTSCREEN:
keymap[i] = SDLK_PRINT;
break;
case SCANCODE_BREAK:
keymap[i] = SDLK_BREAK;
break;
case SCANCODE_BREAK_ALTERNATIVE:
keymap[i] = SDLK_PAUSE;
break;
case SCANCODE_LEFTSHIFT:
keymap[i] = SDLK_LSHIFT;
break;
case SCANCODE_RIGHTSHIFT:
keymap[i] = SDLK_RSHIFT;
break;
case SCANCODE_LEFTCONTROL:
keymap[i] = SDLK_LCTRL;
break;
case SCANCODE_RIGHTCONTROL:
keymap[i] = SDLK_RCTRL;
break;
case SCANCODE_RIGHTWIN:
keymap[i] = SDLK_RSUPER;
break;
case SCANCODE_LEFTWIN:
keymap[i] = SDLK_LSUPER;
break;
case SCANCODE_LEFTALT:
keymap[i] = SDLK_LALT;
break;
case SCANCODE_RIGHTALT:
keymap[i] = SDLK_RALT;
break;
case 127:
keymap[i] = SDLK_MENU;
break;
/* this should take care of all standard ascii keys */
default:
keymap[i] = KVAL(vga_keymap[0][i]);
break;
}
}
for (i = 0; i < SDL_arraysize(keymap); ++i) {
switch (keymap_temp[i]) {
case K_F1:
keymap[i] = SDLK_F1;
break;
case K_F2:
keymap[i] = SDLK_F2;
break;
case K_F3:
keymap[i] = SDLK_F3;
break;
case K_F4:
keymap[i] = SDLK_F4;
break;
case K_F5:
keymap[i] = SDLK_F5;
break;
case K_F6:
keymap[i] = SDLK_F6;
break;
case K_F7:
keymap[i] = SDLK_F7;
break;
case K_F8:
keymap[i] = SDLK_F8;
break;
case K_F9:
keymap[i] = SDLK_F9;
break;
case K_F10:
keymap[i] = SDLK_F10;
break;
case K_F11:
keymap[i] = SDLK_F11;
break;
case K_F12:
keymap[i] = SDLK_F12;
break;
case K_DOWN:
keymap[i] = SDLK_DOWN;
break;
case K_LEFT:
keymap[i] = SDLK_LEFT;
break;
case K_RIGHT:
keymap[i] = SDLK_RIGHT;
break;
case K_UP:
keymap[i] = SDLK_UP;
break;
case K_P0:
keymap[i] = SDLK_KP0;
break;
case K_P1:
keymap[i] = SDLK_KP1;
break;
case K_P2:
keymap[i] = SDLK_KP2;
break;
case K_P3:
keymap[i] = SDLK_KP3;
break;
case K_P4:
keymap[i] = SDLK_KP4;
break;
case K_P5:
keymap[i] = SDLK_KP5;
break;
case K_P6:
keymap[i] = SDLK_KP6;
break;
case K_P7:
keymap[i] = SDLK_KP7;
break;
case K_P8:
keymap[i] = SDLK_KP8;
break;
case K_P9:
keymap[i] = SDLK_KP9;
break;
case K_PPLUS:
keymap[i] = SDLK_KP_PLUS;
break;
case K_PMINUS:
keymap[i] = SDLK_KP_MINUS;
break;
case K_PSTAR:
keymap[i] = SDLK_KP_MULTIPLY;
break;
case K_PSLASH:
keymap[i] = SDLK_KP_DIVIDE;
break;
case K_PENTER:
keymap[i] = SDLK_KP_ENTER;
break;
case K_PDOT:
keymap[i] = SDLK_KP_PERIOD;
break;
case K_SHIFT:
if (keymap[i] != SDLK_RSHIFT)
keymap[i] = SDLK_LSHIFT;
break;
case K_SHIFTL:
keymap[i] = SDLK_LSHIFT;
break;
case K_SHIFTR:
keymap[i] = SDLK_RSHIFT;
break;
case K_CTRL:
if (keymap[i] != SDLK_RCTRL)
keymap[i] = SDLK_LCTRL;
break;
case K_CTRLL:
keymap[i] = SDLK_LCTRL;
break;
case K_CTRLR:
keymap[i] = SDLK_RCTRL;
break;
case K_ALT:
keymap[i] = SDLK_LALT;
break;
case K_ALTGR:
keymap[i] = SDLK_RALT;
break;
case K_INSERT:
keymap[i] = SDLK_INSERT;
break;
case K_REMOVE:
keymap[i] = SDLK_DELETE;
break;
case K_PGUP:
keymap[i] = SDLK_PAGEUP;
break;
case K_PGDN:
keymap[i] = SDLK_PAGEDOWN;
break;
case K_FIND:
keymap[i] = SDLK_HOME;
break;
case K_SELECT:
keymap[i] = SDLK_END;
break;
case K_NUM:
keymap[i] = SDLK_NUMLOCK;
break;
case K_CAPS:
keymap[i] = SDLK_CAPSLOCK;
break;
case K_F13:
keymap[i] = SDLK_PRINT;
break;
case K_HOLD:
keymap[i] = SDLK_SCROLLOCK;
break;
case K_PAUSE:
keymap[i] = SDLK_PAUSE;
break;
case 127:
keymap[i] = SDLK_BACKSPACE;
break;
default:
break;
}
}
}
static SDL_keysym *
TranslateKey(int scancode, SDL_keysym * keysym)
{
/* Set the keysym information */
keysym->scancode = scancode;
keysym->sym = keymap[scancode];
keysym->mod = KMOD_NONE;
/* If UNICODE is on, get the UNICODE value for the key */
keysym->unicode = 0;
if (SDL_TranslateUNICODE) {
int map;
SDLMod modstate;
modstate = SDL_GetModState();
map = 0;
if (modstate & KMOD_SHIFT) {
map |= (1 << KG_SHIFT);
}
if (modstate & KMOD_CTRL) {
map |= (1 << KG_CTRL);
}
if (modstate & KMOD_LALT) {
map |= (1 << KG_ALT);
}
if (modstate & KMOD_RALT) {
map |= (1 << KG_ALTGR);
}
if (KTYP(vga_keymap[map][scancode]) == KT_LETTER) {
if (modstate & KMOD_CAPS) {
map ^= (1 << KG_SHIFT);
}
}
if (KTYP(vga_keymap[map][scancode]) == KT_PAD) {
if (modstate & KMOD_NUM) {
keysym->unicode = KVAL(vga_keymap[map][scancode]);
}
} else {
keysym->unicode = KVAL(vga_keymap[map][scancode]);
}
}
return (keysym);
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include "SDL_fbvideo.h"
/* Variables and functions exported by SDL_sysevents.c to other parts
of the native video subsystem (SDL_sysvideo.c)
*/
extern int FB_OpenKeyboard(_THIS);
extern void FB_CloseKeyboard(_THIS);
extern int FB_OpenMouse(_THIS);
extern void FB_CloseMouse(_THIS);
extern int FB_EnterGraphicsMode(_THIS);
extern int FB_InGraphicsMode(_THIS);
extern void FB_LeaveGraphicsMode(_THIS);
extern void FB_InitOSKeymap(_THIS);
extern void FB_PumpEvents(_THIS);
/* vi: set ts=4 sw=4 expandtab: */
/* Scancodes for the Linux framebuffer console
- Taken with thanks from SVGAlib 1.4.0
*/
#define SCANCODE_ESCAPE 1
#define SCANCODE_1 2
#define SCANCODE_2 3
#define SCANCODE_3 4
#define SCANCODE_4 5
#define SCANCODE_5 6
#define SCANCODE_6 7
#define SCANCODE_7 8
#define SCANCODE_8 9
#define SCANCODE_9 10
#define SCANCODE_0 11
#define SCANCODE_MINUS 12
#define SCANCODE_EQUAL 13
#define SCANCODE_BACKSPACE 14
#define SCANCODE_TAB 15
#define SCANCODE_Q 16
#define SCANCODE_W 17
#define SCANCODE_E 18
#define SCANCODE_R 19
#define SCANCODE_T 20
#define SCANCODE_Y 21
#define SCANCODE_U 22
#define SCANCODE_I 23
#define SCANCODE_O 24
#define SCANCODE_P 25
#define SCANCODE_BRACKET_LEFT 26
#define SCANCODE_BRACKET_RIGHT 27
#define SCANCODE_ENTER 28
#define SCANCODE_LEFTCONTROL 29
#define SCANCODE_A 30
#define SCANCODE_S 31
#define SCANCODE_D 32
#define SCANCODE_F 33
#define SCANCODE_G 34
#define SCANCODE_H 35
#define SCANCODE_J 36
#define SCANCODE_K 37
#define SCANCODE_L 38
#define SCANCODE_SEMICOLON 39
#define SCANCODE_APOSTROPHE 40
#define SCANCODE_GRAVE 41
#define SCANCODE_LEFTSHIFT 42
#define SCANCODE_BACKSLASH 43
#define SCANCODE_Z 44
#define SCANCODE_X 45
#define SCANCODE_C 46
#define SCANCODE_V 47
#define SCANCODE_B 48
#define SCANCODE_N 49
#define SCANCODE_M 50
#define SCANCODE_COMMA 51
#define SCANCODE_PERIOD 52
#define SCANCODE_SLASH 53
#define SCANCODE_RIGHTSHIFT 54
#define SCANCODE_KEYPADMULTIPLY 55
#define SCANCODE_LEFTALT 56
#define SCANCODE_SPACE 57
#define SCANCODE_CAPSLOCK 58
#define SCANCODE_F1 59
#define SCANCODE_F2 60
#define SCANCODE_F3 61
#define SCANCODE_F4 62
#define SCANCODE_F5 63
#define SCANCODE_F6 64
#define SCANCODE_F7 65
#define SCANCODE_F8 66
#define SCANCODE_F9 67
#define SCANCODE_F10 68
#define SCANCODE_NUMLOCK 69
#define SCANCODE_SCROLLLOCK 70
#define SCANCODE_KEYPAD7 71
#define SCANCODE_CURSORUPLEFT 71
#define SCANCODE_KEYPAD8 72
#define SCANCODE_CURSORUP 72
#define SCANCODE_KEYPAD9 73
#define SCANCODE_CURSORUPRIGHT 73
#define SCANCODE_KEYPADMINUS 74
#define SCANCODE_KEYPAD4 75
#define SCANCODE_CURSORLEFT 75
#define SCANCODE_KEYPAD5 76
#define SCANCODE_KEYPAD6 77
#define SCANCODE_CURSORRIGHT 77
#define SCANCODE_KEYPADPLUS 78
#define SCANCODE_KEYPAD1 79
#define SCANCODE_CURSORDOWNLEFT 79
#define SCANCODE_KEYPAD2 80
#define SCANCODE_CURSORDOWN 80
#define SCANCODE_KEYPAD3 81
#define SCANCODE_CURSORDOWNRIGHT 81
#define SCANCODE_KEYPAD0 82
#define SCANCODE_KEYPADPERIOD 83
#define SCANCODE_LESS 86
#define SCANCODE_F11 87
#define SCANCODE_F12 88
#define SCANCODE_KEYPADENTER 96
#define SCANCODE_RIGHTCONTROL 97
#define SCANCODE_CONTROL 97
#define SCANCODE_KEYPADDIVIDE 98
#define SCANCODE_PRINTSCREEN 99
#define SCANCODE_RIGHTALT 100
#define SCANCODE_BREAK 101 /* Beware: is 119 */
#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */
#define SCANCODE_HOME 102
#define SCANCODE_CURSORBLOCKUP 103 /* Cursor key block */
#define SCANCODE_PAGEUP 104
#define SCANCODE_CURSORBLOCKLEFT 105 /* Cursor key block */
#define SCANCODE_CURSORBLOCKRIGHT 106 /* Cursor key block */
#define SCANCODE_END 107
#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */
#define SCANCODE_PAGEDOWN 109
#define SCANCODE_INSERT 110
#define SCANCODE_REMOVE 111
#define SCANCODE_RIGHTWIN 126
#define SCANCODE_LEFTWIN 125
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include "SDL_video.h"
#include "../SDL_blit.h"
#include "SDL_fbmatrox.h"
#include "matrox_mmio.h"
/* Wait for vertical retrace - taken from the XFree86 Matrox driver */
static void
WaitVBL(_THIS)
{
int count;
/* find start of retrace */
mga_waitidle();
while ((mga_in8(0x1FDA) & 0x08));
while (!(mga_in8(0x1FDA) & 0x08));
/* wait until we're past the start */
count = mga_in32(0x1E20) + 2;
while (mga_in32(0x1E20) < count);
}
static void
WaitIdle(_THIS)
{
mga_waitidle();
}
/* Sets video mem colorkey and accelerated blit function */
static int
SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key)
{
return (0);
}
/* Sets per surface hardware alpha value */
#if 0
static int
SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 value)
{
return (0);
}
#endif
static int
FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * rect, Uint32 color)
{
int dstX, dstY;
Uint32 fxbndry;
Uint32 ydstlen;
Uint32 fillop;
/* Don't blit to the display surface when switched away */
if (switched_away) {
return -2; /* no hardware access */
}
if (dst == this->screen) {
SDL_mutexP(hw_lock);
}
switch (dst->format->BytesPerPixel) {
case 1:
color |= (color << 8);
case 2:
color |= (color << 16);
break;
}
/* Set up the X/Y base coordinates */
FB_dst_to_xy(this, dst, &dstX, &dstY);
/* Adjust for the current rectangle */
dstX += rect->x;
dstY += rect->y;
/* Set up the X boundaries */
fxbndry = (dstX | ((dstX + rect->w) << 16));
/* Set up the Y boundaries */
ydstlen = (rect->h | (dstY << 16));
/* Set up for color fill operation */
fillop = MGADWG_TRAP | MGADWG_SOLID |
MGADWG_ARZERO | MGADWG_SGNZERO | MGADWG_SHIFTZERO;
/* Execute the operations! */
mga_wait(5);
mga_out32(MGAREG_DWGCTL, fillop | MGADWG_REPLACE);
mga_out32(MGAREG_FCOL, color);
mga_out32(MGAREG_FXBNDRY, fxbndry);
mga_out32(MGAREG_YDSTLEN + MGAREG_EXEC, ydstlen);
FB_AddBusySurface(dst);
if (dst == this->screen) {
SDL_mutexV(hw_lock);
}
return (0);
}
static int
HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect)
{
SDL_VideoDevice *this = current_video;
int pitch, w, h;
int srcX, srcY;
int dstX, dstY;
Uint32 sign;
Uint32 start, stop;
int skip;
Uint32 blitop;
/* FIXME: For now, only blit to display surface */
if (dst->pitch != SDL_VideoSurface->pitch) {
return (src->map->sw_blit(src, srcrect, dst, dstrect));
}
/* Don't blit to the display surface when switched away */
if (switched_away) {
return -2; /* no hardware access */
}
if (dst == this->screen) {
SDL_mutexP(hw_lock);
}
/* Calculate source and destination base coordinates (in pixels) */
w = dstrect->w;
h = dstrect->h;
FB_dst_to_xy(this, src, &srcX, &srcY);
FB_dst_to_xy(this, dst, &dstX, &dstY);
/* Adjust for the current blit rectangles */
srcX += srcrect->x;
srcY += srcrect->y;
dstX += dstrect->x;
dstY += dstrect->y;
pitch = dst->pitch / dst->format->BytesPerPixel;
/* Set up the blit direction (sign) flags */
sign = 0;
if (srcX < dstX) {
sign |= 1;
}
if (srcY < dstY) {
sign |= 4;
srcY += (h - 1);
dstY += (h - 1);
}
/* Set up the blit source row start, end, and skip (in pixels) */
stop = start = (srcY * pitch) + srcX;
if (srcX < dstX) {
start += (w - 1);
} else {
stop += (w - 1);
}
if (srcY < dstY) {
skip = -pitch;
} else {
skip = pitch;
}
/* Set up the blit operation */
if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
Uint32 colorkey;
blitop = MGADWG_BFCOL | MGADWG_BITBLT |
MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16) | MGADWG_TRANSC;
colorkey = src->format->colorkey;
switch (dst->format->BytesPerPixel) {
case 1:
colorkey |= (colorkey << 8);
case 2:
colorkey |= (colorkey << 16);
break;
}
mga_wait(2);
mga_out32(MGAREG_FCOL, colorkey);
mga_out32(MGAREG_BCOL, 0xFFFFFFFF);
} else {
blitop = MGADWG_BFCOL | MGADWG_BITBLT |
MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16);
}
mga_wait(7);
mga_out32(MGAREG_SGN, sign);
mga_out32(MGAREG_AR3, start);
mga_out32(MGAREG_AR0, stop);
mga_out32(MGAREG_AR5, skip);
mga_out32(MGAREG_FXBNDRY, (dstX | ((dstX + w - 1) << 16)));
mga_out32(MGAREG_YDSTLEN, (dstY << 16) | h);
mga_out32(MGAREG_DWGCTL + MGAREG_EXEC, blitop);
FB_AddBusySurface(src);
FB_AddBusySurface(dst);
if (dst == this->screen) {
SDL_mutexV(hw_lock);
}
return (0);
}
static int
CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst)
{
int accelerated;
/* Set initial acceleration on */
src->flags |= SDL_HWACCEL;
/* Set the surface attributes */
if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
if (!this->info.blit_hw_A) {
src->flags &= ~SDL_HWACCEL;
}
}
if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
if (!this->info.blit_hw_CC) {
src->flags &= ~SDL_HWACCEL;
}
}
/* Check to see if final surface blit is accelerated */
accelerated = !!(src->flags & SDL_HWACCEL);
if (accelerated) {
src->map->hw_blit = HWAccelBlit;
}
return (accelerated);
}
void
FB_MatroxAccel(_THIS, __u32 card)
{
/* We have hardware accelerated surface functions */
this->CheckHWBlit = CheckHWBlit;
wait_vbl = WaitVBL;
wait_idle = WaitIdle;
/* The Matrox has an accelerated color fill */
this->info.blit_fill = 1;
this->FillHWRect = FillHWRect;
/* The Matrox has accelerated normal and colorkey blits. */
this->info.blit_hw = 1;
/* The Millenium I appears to do the colorkey test a word
at a time, and the transparency is intverted. (?)
*/
if (card != FB_ACCEL_MATROX_MGA2064W) {
this->info.blit_hw_CC = 1;
this->SetHWColorKey = SetHWColorKey;
}
#if 0 /* Not yet implemented? */
/* The Matrox G200/G400 has an accelerated alpha blit */
if ((card == FB_ACCEL_MATROX_MGAG200)
|| (card == FB_ACCEL_MATROX_MGAG400)) {
this->info.blit_hw_A = 1;
this->SetHWAlpha = SetHWAlpha;
}
#endif
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* Matrox hardware acceleration for the SDL framebuffer console driver */
#include "SDL_fbvideo.h"
/* Set up the driver for Matrox acceleration */
extern void FB_MatroxAccel(_THIS, __u32 card);
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include "SDL_mouse.h"
#include "../../events/SDL_events_c.h"
#include "SDL_fbvideo.h"
#include "SDL_fbmouse_c.h"
/* The implementation dependent data for the window manager cursor */
struct WMcursor
{
int unused;
};
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include "SDL_fbvideo.h"
/* Functions to be exported */
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include "SDL_video.h"
#include "../SDL_blit.h"
#include "SDL_fbriva.h"
#include "riva_mmio.h"
#include "riva_regs.h"
static int FifoEmptyCount = 0;
static int FifoFreeCount = 0;
/* Wait for vertical retrace */
static void
WaitVBL(_THIS)
{
volatile Uint8 *port = (Uint8 *) (mapped_io + PCIO_OFFSET + 0x3DA);
while ((*port & 0x08));
while (!(*port & 0x08));
}
static void
NV3WaitIdle(_THIS)
{
RivaRop *Rop = (RivaRop *) (mapped_io + ROP_OFFSET);
while ((Rop->FifoFree < FifoEmptyCount) ||
(*(mapped_io + PGRAPH_OFFSET + 0x000006B0) & 0x01));
}
static void
NV4WaitIdle(_THIS)
{
RivaRop *Rop = (RivaRop *) (mapped_io + ROP_OFFSET);
while ((Rop->FifoFree < FifoEmptyCount) ||
(*(mapped_io + PGRAPH_OFFSET + 0x00000700) & 0x01));
}
#if 0 /* Not yet implemented? */
/* Sets video mem colorkey and accelerated blit function */
static int
SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key)
{
return (0);
}
/* Sets per surface hardware alpha value */
static int
SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 value)
{
return (0);
}
#endif /* Not yet implemented */
static int
FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * rect, Uint32 color)
{
int dstX, dstY;
int dstW, dstH;
RivaBitmap *Bitmap = (RivaBitmap *) (mapped_io + BITMAP_OFFSET);
/* Don't blit to the display surface when switched away */
if (switched_away) {
return -2; /* no hardware access */
}
if (dst == this->screen) {
SDL_mutexP(hw_lock);
}
/* Set up the X/Y base coordinates */
dstW = rect->w;
dstH = rect->h;
FB_dst_to_xy(this, dst, &dstX, &dstY);
/* Adjust for the current rectangle */
dstX += rect->x;
dstY += rect->y;
RIVA_FIFO_FREE(Bitmap, 1);
Bitmap->Color1A = color;
RIVA_FIFO_FREE(Bitmap, 2);
Bitmap->UnclippedRectangle[0].TopLeft = (dstX << 16) | dstY;
Bitmap->UnclippedRectangle[0].WidthHeight = (dstW << 16) | dstH;
FB_AddBusySurface(dst);
if (dst == this->screen) {
SDL_mutexV(hw_lock);
}
return (0);
}
static int
HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect)
{
SDL_VideoDevice *this = current_video;
int srcX, srcY;
int dstX, dstY;
int dstW, dstH;
RivaScreenBlt *Blt = (RivaScreenBlt *) (mapped_io + BLT_OFFSET);
/* FIXME: For now, only blit to display surface */
if (dst->pitch != SDL_VideoSurface->pitch) {
return (src->map->sw_blit(src, srcrect, dst, dstrect));
}
/* Don't blit to the display surface when switched away */
if (switched_away) {
return -2; /* no hardware access */
}
if (dst == this->screen) {
SDL_mutexP(hw_lock);
}
/* Calculate source and destination base coordinates (in pixels) */
dstW = dstrect->w;
dstH = dstrect->h;
FB_dst_to_xy(this, src, &srcX, &srcY);
FB_dst_to_xy(this, dst, &dstX, &dstY);
/* Adjust for the current blit rectangles */
srcX += srcrect->x;
srcY += srcrect->y;
dstX += dstrect->x;
dstY += dstrect->y;
RIVA_FIFO_FREE(Blt, 3);
Blt->TopLeftSrc = (srcY << 16) | srcX;
Blt->TopLeftDst = (dstY << 16) | dstX;
Blt->WidthHeight = (dstH << 16) | dstW;
FB_AddBusySurface(src);
FB_AddBusySurface(dst);
if (dst == this->screen) {
SDL_mutexV(hw_lock);
}
return (0);
}
static int
CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst)
{
int accelerated;
/* Set initial acceleration on */
src->flags |= SDL_HWACCEL;
/* Set the surface attributes */
if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
if (!this->info.blit_hw_A) {
src->flags &= ~SDL_HWACCEL;
}
}
if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
if (!this->info.blit_hw_CC) {
src->flags &= ~SDL_HWACCEL;
}
}
/* Check to see if final surface blit is accelerated */
accelerated = !!(src->flags & SDL_HWACCEL);
if (accelerated) {
src->map->hw_blit = HWAccelBlit;
}
return (accelerated);
}
void
FB_RivaAccel(_THIS, __u32 card)
{
RivaRop *Rop = (RivaRop *) (mapped_io + ROP_OFFSET);
/* We have hardware accelerated surface functions */
this->CheckHWBlit = CheckHWBlit;
wait_vbl = WaitVBL;
switch (card) {
case FB_ACCEL_NV3:
wait_idle = NV3WaitIdle;
break;
case FB_ACCEL_NV4:
wait_idle = NV4WaitIdle;
break;
default:
/* Hmm... FIXME */
break;
}
FifoEmptyCount = Rop->FifoFree;
/* The Riva has an accelerated color fill */
this->info.blit_fill = 1;
this->FillHWRect = FillHWRect;
/* The Riva has accelerated normal and colorkey blits. */
this->info.blit_hw = 1;
#if 0 /* Not yet implemented? */
this->info.blit_hw_CC = 1;
this->SetHWColorKey = SetHWColorKey;
#endif
#if 0 /* Not yet implemented? */
/* The Riva has an accelerated alpha blit */
this->info.blit_hw_A = 1;
this->SetHWAlpha = SetHWAlpha;
#endif
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* Riva hardware acceleration for the SDL framebuffer console driver */
#include "SDL_fbvideo.h"
#ifndef FB_ACCEL_NV3
#define FB_ACCEL_NV3 27
#endif
#ifndef FB_ACCEL_NV4
#define FB_ACCEL_NV4 28
#endif
/* Set up the driver for Riva acceleration */
extern void FB_RivaAccel(_THIS, __u32 card);
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* Framebuffer console based SDL video driver implementation.
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#ifndef HAVE_GETPAGESIZE
#include <asm/page.h> /* For definition of PAGE_SIZE */
#endif
#include <linux/vt.h>
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
#include "SDL_fbvideo.h"
#include "SDL_fbmouse_c.h"
#include "SDL_fbevents_c.h"
#include "SDL_fb3dfx.h"
#include "SDL_fbmatrox.h"
#include "SDL_fbriva.h"
/*#define FBCON_DEBUG*/
#if defined(i386) && defined(FB_TYPE_VGA_PLANES)
#define VGA16_FBCON_SUPPORT
#include <sys/io.h> /* For ioperm() */
#ifndef FB_AUX_VGA_PLANES_VGA4
#define FB_AUX_VGA_PLANES_VGA4 0
#endif
/*
static inline void outb (unsigned char value, unsigned short port)
{
__asm__ __volatile__ ("outb %b0,%w1"::"a" (value), "Nd" (port));
}
*/
#endif /* FB_TYPE_VGA_PLANES */
/* A list of video resolutions that we query for (sorted largest to smallest) */
static const SDL_Rect checkres[] = {
{0, 0, 1600, 1200}, /* 16 bpp: 0x11E, or 286 */
{0, 0, 1408, 1056}, /* 16 bpp: 0x19A, or 410 */
{0, 0, 1280, 1024}, /* 16 bpp: 0x11A, or 282 */
{0, 0, 1152, 864}, /* 16 bpp: 0x192, or 402 */
{0, 0, 1024, 768}, /* 16 bpp: 0x117, or 279 */
{0, 0, 960, 720}, /* 16 bpp: 0x18A, or 394 */
{0, 0, 800, 600}, /* 16 bpp: 0x114, or 276 */
{0, 0, 768, 576}, /* 16 bpp: 0x182, or 386 */
{0, 0, 720, 576}, /* PAL */
{0, 0, 720, 480}, /* NTSC */
{0, 0, 640, 480}, /* 16 bpp: 0x111, or 273 */
{0, 0, 640, 400}, /* 8 bpp: 0x100, or 256 */
{0, 0, 512, 384},
{0, 0, 320, 240},
{0, 0, 320, 200}
};
static const struct
{
int xres;
int yres;
int pixclock;
int left;
int right;
int upper;
int lower;
int hslen;
int vslen;
int sync;
int vmode;
} vesa_timings[] = {
#ifdef USE_VESA_TIMINGS /* Only tested on Matrox Millenium I */
{
640, 400, 39771, 48, 16, 39, 8, 96, 2, 2, 0}, /* 70 Hz */
{
640, 480, 39683, 48, 16, 33, 10, 96, 2, 0, 0}, /* 60 Hz */
{
768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0}, /* 60 Hz */
{
800, 600, 24038, 144, 24, 28, 8, 112, 6, 0, 0}, /* 60 Hz */
{
960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0}, /* 60 Hz */
{
1024, 768, 15386, 160, 32, 30, 4, 128, 4, 0, 0}, /* 60 Hz */
{
1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0}, /* 60 Hz */
{
1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0}, /* 60 Hz */
{
1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0}, /* 60 Hz */
{
1600, 1200, /*? */ 0, 272, 48, 32, 5, 152, 5, 0, 0}, /* 60 Hz */
#else
/* You can generate these timings from your XF86Config file using
the 'modeline2fb' perl script included with the fbset package.
These timings were generated for Matrox Millenium I, 15" monitor.
*/
{
320, 200, 79440, 16, 16, 20, 4, 48, 1, 0, 2}, /* 70 Hz */
{
320, 240, 63492, 16, 16, 16, 4, 48, 2, 0, 2}, /* 72 Hz */
{
512, 384, 49603, 48, 16, 16, 1, 64, 3, 0, 0}, /* 78 Hz */
{
640, 400, 31746, 96, 32, 41, 1, 64, 3, 2, 0}, /* 85 Hz */
{
640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0}, /* 75 Hz */
{
768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0}, /* 60 Hz */
{
800, 600, 20000, 64, 56, 23, 37, 120, 6, 3, 0}, /* 72 Hz */
{
960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0}, /* 60 Hz */
{
1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0, 0}, /* 70 Hz */
{
1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0}, /* 60 Hz */
{
1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0}, /* 60 Hz */
{
1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0}, /* 60 Hz */
{
1600, 1200, /*? */ 0, 272, 48, 32, 5, 152, 5, 0, 0}, /* 60 Hz */
#endif
};
/* Initialization/Query functions */
static int FB_VideoInit(_THIS, SDL_PixelFormat * vformat);
static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags);
static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface * current, int width,
int height, int bpp, Uint32 flags);
#ifdef VGA16_FBCON_SUPPORT
static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface * current, int width,
int height, int bpp, Uint32 flags);
#endif
static int FB_SetColors(_THIS, int firstcolor, int ncolors,
SDL_Color * colors);
static void FB_VideoQuit(_THIS);
/* Hardware surface functions */
static int FB_InitHWSurfaces(_THIS, SDL_Surface * screen, char *base,
int size);
static void FB_FreeHWSurfaces(_THIS);
static int FB_AllocHWSurface(_THIS, SDL_Surface * surface);
static int FB_LockHWSurface(_THIS, SDL_Surface * surface);
static void FB_UnlockHWSurface(_THIS, SDL_Surface * surface);
static void FB_FreeHWSurface(_THIS, SDL_Surface * surface);
static void FB_WaitVBL(_THIS);
static void FB_WaitIdle(_THIS);
static int FB_FlipHWSurface(_THIS, SDL_Surface * surface);
/* Internal palette functions */
static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo,
struct fb_var_screeninfo *vinfo);
static void FB_RestorePalette(_THIS);
static int
SDL_getpagesize(void)
{
#ifdef HAVE_GETPAGESIZE
return getpagesize();
#elif defined(PAGE_SIZE)
return PAGE_SIZE;
#else
#error Can not determine system page size.
/* this is what it USED to be in Linux... */
return 4096;
#endif
}
/* Small wrapper for mmap() so we can play nicely with no-mmu hosts
* (non-mmu hosts disallow the MAP_SHARED flag) */
static void *
do_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
void *ret;
ret = mmap(start, length, prot, flags, fd, offset);
if (ret == (char *) -1 && (flags & MAP_SHARED)) {
ret = mmap(start, length, prot,
(flags & ~MAP_SHARED) | MAP_PRIVATE, fd, offset);
}
return ret;
}
/* FB driver bootstrap functions */
static int
FB_Available(void)
{
int console = -1;
/* Added check for /fb/0 (devfs) */
/* but - use environment variable first... if it fails, still check defaults */
int idx = 0;
const char *SDL_fbdevs[4] = { NULL, "/dev/fb0", "/dev/fb/0", NULL };
SDL_fbdevs[0] = SDL_getenv("SDL_FBDEV");
if (!SDL_fbdevs[0])
idx++;
for (; SDL_fbdevs[idx]; idx++) {
console = open(SDL_fbdevs[idx], O_RDWR, 0);
if (console >= 0) {
close(console);
break;
}
}
return (console >= 0);
}
static void
FB_DeleteDevice(SDL_VideoDevice * device)
{
SDL_free(device->hidden);
SDL_free(device);
}
static SDL_VideoDevice *
FB_CreateDevice(int devindex)
{
SDL_VideoDevice *this;
/* Initialize all variables that we clean on shutdown */
this = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice));
if (this) {
SDL_memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateVideoData *)
SDL_malloc((sizeof *this->hidden));
}
if ((this == NULL) || (this->hidden == NULL)) {
SDL_OutOfMemory();
if (this) {
SDL_free(this);
}
return (0);
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
wait_vbl = FB_WaitVBL;
wait_idle = FB_WaitIdle;
mouse_fd = -1;
keyboard_fd = -1;
/* Set the function pointers */
this->VideoInit = FB_VideoInit;
this->ListModes = FB_ListModes;
this->SetVideoMode = FB_SetVideoMode;
this->SetColors = FB_SetColors;
this->UpdateRects = NULL;
this->VideoQuit = FB_VideoQuit;
this->AllocHWSurface = FB_AllocHWSurface;
this->CheckHWBlit = NULL;
this->FillHWRect = NULL;
this->SetHWColorKey = NULL;
this->SetHWAlpha = NULL;
this->LockHWSurface = FB_LockHWSurface;
this->UnlockHWSurface = FB_UnlockHWSurface;
this->FlipHWSurface = FB_FlipHWSurface;
this->FreeHWSurface = FB_FreeHWSurface;
this->SetCaption = NULL;
this->SetIcon = NULL;
this->IconifyWindow = NULL;
this->GrabInput = NULL;
this->GetWMInfo = NULL;
this->InitOSKeymap = FB_InitOSKeymap;
this->PumpEvents = FB_PumpEvents;
this->free = FB_DeleteDevice;
return this;
}
VideoBootStrap FBCON_bootstrap = {
"fbcon", "Linux Framebuffer Console",
FB_Available, FB_CreateDevice
};
#define FB_MODES_DB "/etc/fb.modes"
static int
read_fbmodes_line(FILE * f, char *line, int length)
{
int blank;
char *c;
int i;
blank = 0;
/* find a relevant line */
do {
if (!fgets(line, length, f))
return 0;
c = line;
while (((*c == '\t') || (*c == ' ')) && (*c != 0))
c++;
if ((*c == '\n') || (*c == '#') || (*c == 0))
blank = 1;
else
blank = 0;
} while (blank);
/* remove whitespace at the begining of the string */
i = 0;
do {
line[i] = c[i];
i++;
} while (c[i] != 0);
return 1;
}
static int
read_fbmodes_mode(FILE * f, struct fb_var_screeninfo *vinfo)
{
char line[1024];
char option[256];
/* Find a "geometry" */
do {
if (read_fbmodes_line(f, line, sizeof(line)) == 0)
return 0;
if (SDL_strncmp(line, "geometry", 8) == 0)
break;
} while (1);
SDL_sscanf(line, "geometry %d %d %d %d %d", &vinfo->xres, &vinfo->yres,
&vinfo->xres_virtual, &vinfo->yres_virtual,
&vinfo->bits_per_pixel);
if (read_fbmodes_line(f, line, sizeof(line)) == 0)
return 0;
SDL_sscanf(line, "timings %d %d %d %d %d %d %d", &vinfo->pixclock,
&vinfo->left_margin, &vinfo->right_margin,
&vinfo->upper_margin, &vinfo->lower_margin, &vinfo->hsync_len,
&vinfo->vsync_len);
vinfo->sync = 0;
vinfo->vmode = FB_VMODE_NONINTERLACED;
/* Parse misc options */
do {
if (read_fbmodes_line(f, line, sizeof(line)) == 0)
return 0;
if (SDL_strncmp(line, "hsync", 5) == 0) {
SDL_sscanf(line, "hsync %s", option);
if (SDL_strncmp(option, "high", 4) == 0)
vinfo->sync |= FB_SYNC_HOR_HIGH_ACT;
} else if (SDL_strncmp(line, "vsync", 5) == 0) {
SDL_sscanf(line, "vsync %s", option);
if (SDL_strncmp(option, "high", 4) == 0)
vinfo->sync |= FB_SYNC_VERT_HIGH_ACT;
} else if (SDL_strncmp(line, "csync", 5) == 0) {
SDL_sscanf(line, "csync %s", option);
if (SDL_strncmp(option, "high", 4) == 0)
vinfo->sync |= FB_SYNC_COMP_HIGH_ACT;
} else if (SDL_strncmp(line, "extsync", 5) == 0) {
SDL_sscanf(line, "extsync %s", option);
if (SDL_strncmp(option, "true", 4) == 0)
vinfo->sync |= FB_SYNC_EXT;
} else if (SDL_strncmp(line, "laced", 5) == 0) {
SDL_sscanf(line, "laced %s", option);
if (SDL_strncmp(option, "true", 4) == 0)
vinfo->vmode |= FB_VMODE_INTERLACED;
} else if (SDL_strncmp(line, "double", 6) == 0) {
SDL_sscanf(line, "double %s", option);
if (SDL_strncmp(option, "true", 4) == 0)
vinfo->vmode |= FB_VMODE_DOUBLE;
}
} while (SDL_strncmp(line, "endmode", 7) != 0);
return 1;
}
static int
FB_CheckMode(_THIS, struct fb_var_screeninfo *vinfo,
int index, unsigned int *w, unsigned int *h)
{
int mode_okay;
mode_okay = 0;
vinfo->bits_per_pixel = (index + 1) * 8;
vinfo->xres = *w;
vinfo->xres_virtual = *w;
vinfo->yres = *h;
vinfo->yres_virtual = *h;
vinfo->activate = FB_ACTIVATE_TEST;
if (ioctl(console_fd, FBIOPUT_VSCREENINFO, vinfo) == 0) {
#ifdef FBCON_DEBUG
fprintf(stderr,
"Checked mode %dx%d at %d bpp, got mode %dx%d at %d bpp\n",
*w, *h, (index + 1) * 8, vinfo->xres, vinfo->yres,
vinfo->bits_per_pixel);
#endif
if ((((vinfo->bits_per_pixel + 7) / 8) - 1) == index) {
*w = vinfo->xres;
*h = vinfo->yres;
mode_okay = 1;
}
}
return mode_okay;
}
static int
FB_AddMode(_THIS, int index, unsigned int w, unsigned int h,
int check_timings)
{
SDL_Rect *mode;
int i;
int next_mode;
/* Check to see if we already have this mode */
if (SDL_nummodes[index] > 0) {
mode = SDL_modelist[index][SDL_nummodes[index] - 1];
if ((mode->w == w) && (mode->h == h)) {
#ifdef FBCON_DEBUG
fprintf(stderr,
"We already have mode %dx%d at %d bytes per pixel\n",
w, h, index + 1);
#endif
return (0);
}
}
/* Only allow a mode if we have a valid timing for it */
if (check_timings) {
int found_timing = 0;
for (i = 0; i < (sizeof(vesa_timings) / sizeof(vesa_timings[0])); ++i) {
if ((w == vesa_timings[i].xres) &&
(h == vesa_timings[i].yres) && vesa_timings[i].pixclock) {
found_timing = 1;
break;
}
}
if (!found_timing) {
#ifdef FBCON_DEBUG
fprintf(stderr, "No valid timing line for mode %dx%d\n", w, h);
#endif
return (0);
}
}
/* Set up the new video mode rectangle */
mode = (SDL_Rect *) SDL_malloc(sizeof *mode);
if (mode == NULL) {
SDL_OutOfMemory();
return (-1);
}
mode->x = 0;
mode->y = 0;
mode->w = w;
mode->h = h;
#ifdef FBCON_DEBUG
fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h,
index + 1);
#endif
/* Allocate the new list of modes, and fill in the new mode */
next_mode = SDL_nummodes[index];
SDL_modelist[index] = (SDL_Rect **)
SDL_realloc(SDL_modelist[index],
(1 + next_mode + 1) * sizeof(SDL_Rect *));
if (SDL_modelist[index] == NULL) {
SDL_OutOfMemory();
SDL_nummodes[index] = 0;
SDL_free(mode);
return (-1);
}
SDL_modelist[index][next_mode] = mode;
SDL_modelist[index][next_mode + 1] = NULL;
SDL_nummodes[index]++;
return (0);
}
static int
cmpmodes(const void *va, const void *vb)
{
const SDL_Rect *a = *(const SDL_Rect **) va;
const SDL_Rect *b = *(const SDL_Rect **) vb;
if (a->h == b->h)
return b->w - a->w;
else
return b->h - a->h;
}
static void
FB_SortModes(_THIS)
{
int i;
for (i = 0; i < NUM_MODELISTS; ++i) {
if (SDL_nummodes[i] > 0) {
SDL_qsort(SDL_modelist[i], SDL_nummodes[i],
sizeof *SDL_modelist[i], cmpmodes);
}
}
}
static int
FB_VideoInit(_THIS, SDL_PixelFormat * vformat)
{
const int pagesize = SDL_getpagesize();
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
int i, j;
int current_index;
unsigned int current_w;
unsigned int current_h;
const char *SDL_fbdev;
FILE *modesdb;
/* Initialize the library */
SDL_fbdev = SDL_getenv("SDL_FBDEV");
if (SDL_fbdev == NULL) {
SDL_fbdev = "/dev/fb0";
}
console_fd = open(SDL_fbdev, O_RDWR, 0);
if (console_fd < 0) {
SDL_SetError("Unable to open %s", SDL_fbdev);
return (-1);
}
#if !SDL_THREADS_DISABLED
/* Create the hardware surface lock mutex */
hw_lock = SDL_CreateMutex();
if (hw_lock == NULL) {
SDL_SetError("Unable to create lock mutex");
FB_VideoQuit(this);
return (-1);
}
#endif
/* Get the type of video hardware */
if (ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
SDL_SetError("Couldn't get console hardware info");
FB_VideoQuit(this);
return (-1);
}
switch (finfo.type) {
case FB_TYPE_PACKED_PIXELS:
/* Supported, no worries.. */
break;
#ifdef VGA16_FBCON_SUPPORT
case FB_TYPE_VGA_PLANES:
/* VGA16 is supported, but that's it */
if (finfo.type_aux == FB_AUX_VGA_PLANES_VGA4) {
if (ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1) < 0) {
SDL_SetError("No I/O port permissions");
FB_VideoQuit(this);
return (-1);
}
this->SetVideoMode = FB_SetVGA16Mode;
break;
}
/* Fall through to unsupported case */
#endif /* VGA16_FBCON_SUPPORT */
default:
SDL_SetError("Unsupported console hardware");
FB_VideoQuit(this);
return (-1);
}
switch (finfo.visual) {
case FB_VISUAL_TRUECOLOR:
case FB_VISUAL_PSEUDOCOLOR:
case FB_VISUAL_STATIC_PSEUDOCOLOR:
case FB_VISUAL_DIRECTCOLOR:
break;
default:
SDL_SetError("Unsupported console hardware");
FB_VideoQuit(this);
return (-1);
}
/* Check if the user wants to disable hardware acceleration */
{
const char *fb_accel;
fb_accel = SDL_getenv("SDL_FBACCEL");
if (fb_accel) {
finfo.accel = SDL_atoi(fb_accel);
}
}
/* Memory map the device, compensating for buggy PPC mmap() */
mapped_offset = (((long) finfo.smem_start) -
(((long) finfo.smem_start) & ~(pagesize - 1)));
mapped_memlen = finfo.smem_len + mapped_offset;
mapped_mem = do_mmap(NULL, mapped_memlen,
PROT_READ | PROT_WRITE, MAP_SHARED, console_fd, 0);
if (mapped_mem == (char *) -1) {
SDL_SetError("Unable to memory map the video hardware");
mapped_mem = NULL;
FB_VideoQuit(this);
return (-1);
}
/* Determine the current screen depth */
if (ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
SDL_SetError("Couldn't get console pixel format");
FB_VideoQuit(this);
return (-1);
}
vformat->BitsPerPixel = vinfo.bits_per_pixel;
if (vformat->BitsPerPixel < 8) {
/* Assuming VGA16, we handle this via a shadow framebuffer */
vformat->BitsPerPixel = 8;
}
for (i = 0; i < vinfo.red.length; ++i) {
vformat->Rmask <<= 1;
vformat->Rmask |= (0x00000001 << vinfo.red.offset);
}
for (i = 0; i < vinfo.green.length; ++i) {
vformat->Gmask <<= 1;
vformat->Gmask |= (0x00000001 << vinfo.green.offset);
}
for (i = 0; i < vinfo.blue.length; ++i) {
vformat->Bmask <<= 1;
vformat->Bmask |= (0x00000001 << vinfo.blue.offset);
}
saved_vinfo = vinfo;
/* Save hardware palette, if needed */
FB_SavePalette(this, &finfo, &vinfo);
/* If the I/O registers are available, memory map them so we
can take advantage of any supported hardware acceleration.
*/
vinfo.accel_flags = 0; /* Temporarily reserve registers */
ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo);
if (finfo.accel && finfo.mmio_len) {
mapped_iolen = finfo.mmio_len;
mapped_io = do_mmap(NULL, mapped_iolen, PROT_READ | PROT_WRITE,
MAP_SHARED, console_fd, mapped_memlen);
if (mapped_io == (char *) -1) {
/* Hmm, failed to memory map I/O registers */
mapped_io = NULL;
}
}
/* Query for the list of available video modes */
current_w = vinfo.xres;
current_h = vinfo.yres;
current_index = ((vinfo.bits_per_pixel + 7) / 8) - 1;
modesdb = fopen(FB_MODES_DB, "r");
for (i = 0; i < NUM_MODELISTS; ++i) {
SDL_nummodes[i] = 0;
SDL_modelist[i] = NULL;
}
if (SDL_getenv("SDL_FB_BROKEN_MODES") != NULL) {
FB_AddMode(this, current_index, current_w, current_h, 0);
} else if (modesdb) {
while (read_fbmodes_mode(modesdb, &vinfo)) {
for (i = 0; i < NUM_MODELISTS; ++i) {
unsigned int w, h;
/* See if we are querying for the current mode */
w = vinfo.xres;
h = vinfo.yres;
if (i == current_index) {
if ((current_w > w) || (current_h > h)) {
/* Only check once */
FB_AddMode(this, i, current_w, current_h, 0);
current_index = -1;
}
}
if (FB_CheckMode(this, &vinfo, i, &w, &h)) {
FB_AddMode(this, i, w, h, 0);
}
}
}
fclose(modesdb);
FB_SortModes(this);
} else {
for (i = 0; i < NUM_MODELISTS; ++i) {
for (j = 0; j < (sizeof(checkres) / sizeof(checkres[0])); ++j) {
unsigned int w, h;
/* See if we are querying for the current mode */
w = checkres[j].w;
h = checkres[j].h;
if (i == current_index) {
if ((current_w > w) || (current_h > h)) {
/* Only check once */
FB_AddMode(this, i, current_w, current_h, 0);
current_index = -1;
}
}
if (FB_CheckMode(this, &vinfo, i, &w, &h)) {
FB_AddMode(this, i, w, h, 1);
}
}
}
}
/* Fill in our hardware acceleration capabilities */
this->info.current_w = current_w;
this->info.current_h = current_h;
this->info.wm_available = 0;
this->info.hw_available = 1;
this->info.video_mem = finfo.smem_len / 1024;
if (mapped_io) {
switch (finfo.accel) {
case FB_ACCEL_MATROX_MGA2064W:
case FB_ACCEL_MATROX_MGA1064SG:
case FB_ACCEL_MATROX_MGA2164W:
case FB_ACCEL_MATROX_MGA2164W_AGP:
case FB_ACCEL_MATROX_MGAG100:
/*case FB_ACCEL_MATROX_MGAG200: G200 acceleration broken! */
case FB_ACCEL_MATROX_MGAG400:
#ifdef FBACCEL_DEBUG
printf("Matrox hardware accelerator!\n");
#endif
FB_MatroxAccel(this, finfo.accel);
break;
case FB_ACCEL_3DFX_BANSHEE:
#ifdef FBACCEL_DEBUG
printf("3DFX hardware accelerator!\n");
#endif
FB_3DfxAccel(this, finfo.accel);
break;
case FB_ACCEL_NV3:
case FB_ACCEL_NV4:
#ifdef FBACCEL_DEBUG
printf("NVidia hardware accelerator!\n");
#endif
FB_RivaAccel(this, finfo.accel);
break;
default:
#ifdef FBACCEL_DEBUG
printf("Unknown hardware accelerator.\n");
#endif
break;
}
}
/* Enable mouse and keyboard support */
if (FB_OpenKeyboard(this) < 0) {
FB_VideoQuit(this);
return (-1);
}
if (FB_OpenMouse(this) < 0) {
const char *sdl_nomouse;
sdl_nomouse = SDL_getenv("SDL_NOMOUSE");
if (!sdl_nomouse) {
SDL_SetError("Unable to open mouse");
FB_VideoQuit(this);
return (-1);
}
}
/* We're done! */
return (0);
}
static SDL_Rect **
FB_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
{
return (SDL_modelist[((format->BitsPerPixel + 7) / 8) - 1]);
}
/* Various screen update functions available */
static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect * rects);
#ifdef VGA16_FBCON_SUPPORT
static void FB_VGA16Update(_THIS, int numrects, SDL_Rect * rects);
#endif
#ifdef FBCON_DEBUG
static void
print_vinfo(struct fb_var_screeninfo *vinfo)
{
fprintf(stderr, "Printing vinfo:\n");
fprintf(stderr, "\txres: %d\n", vinfo->xres);
fprintf(stderr, "\tyres: %d\n", vinfo->yres);
fprintf(stderr, "\txres_virtual: %d\n", vinfo->xres_virtual);
fprintf(stderr, "\tyres_virtual: %d\n", vinfo->yres_virtual);
fprintf(stderr, "\txoffset: %d\n", vinfo->xoffset);
fprintf(stderr, "\tyoffset: %d\n", vinfo->yoffset);
fprintf(stderr, "\tbits_per_pixel: %d\n", vinfo->bits_per_pixel);
fprintf(stderr, "\tgrayscale: %d\n", vinfo->grayscale);
fprintf(stderr, "\tnonstd: %d\n", vinfo->nonstd);
fprintf(stderr, "\tactivate: %d\n", vinfo->activate);
fprintf(stderr, "\theight: %d\n", vinfo->height);
fprintf(stderr, "\twidth: %d\n", vinfo->width);
fprintf(stderr, "\taccel_flags: %d\n", vinfo->accel_flags);
fprintf(stderr, "\tpixclock: %d\n", vinfo->pixclock);
fprintf(stderr, "\tleft_margin: %d\n", vinfo->left_margin);
fprintf(stderr, "\tright_margin: %d\n", vinfo->right_margin);
fprintf(stderr, "\tupper_margin: %d\n", vinfo->upper_margin);
fprintf(stderr, "\tlower_margin: %d\n", vinfo->lower_margin);
fprintf(stderr, "\thsync_len: %d\n", vinfo->hsync_len);
fprintf(stderr, "\tvsync_len: %d\n", vinfo->vsync_len);
fprintf(stderr, "\tsync: %d\n", vinfo->sync);
fprintf(stderr, "\tvmode: %d\n", vinfo->vmode);
fprintf(stderr, "\tred: %d/%d\n", vinfo->red.length, vinfo->red.offset);
fprintf(stderr, "\tgreen: %d/%d\n", vinfo->green.length,
vinfo->green.offset);
fprintf(stderr, "\tblue: %d/%d\n", vinfo->blue.length,
vinfo->blue.offset);
fprintf(stderr, "\talpha: %d/%d\n", vinfo->transp.length,
vinfo->transp.offset);
}
static void
print_finfo(struct fb_fix_screeninfo *finfo)
{
fprintf(stderr, "Printing finfo:\n");
fprintf(stderr, "\tsmem_start = %p\n", (char *) finfo->smem_start);
fprintf(stderr, "\tsmem_len = %d\n", finfo->smem_len);
fprintf(stderr, "\ttype = %d\n", finfo->type);
fprintf(stderr, "\ttype_aux = %d\n", finfo->type_aux);
fprintf(stderr, "\tvisual = %d\n", finfo->visual);
fprintf(stderr, "\txpanstep = %d\n", finfo->xpanstep);
fprintf(stderr, "\typanstep = %d\n", finfo->ypanstep);
fprintf(stderr, "\tywrapstep = %d\n", finfo->ywrapstep);
fprintf(stderr, "\tline_length = %d\n", finfo->line_length);
fprintf(stderr, "\tmmio_start = %p\n", (char *) finfo->mmio_start);
fprintf(stderr, "\tmmio_len = %d\n", finfo->mmio_len);
fprintf(stderr, "\taccel = %d\n", finfo->accel);
}
#endif
static int
choose_fbmodes_mode(struct fb_var_screeninfo *vinfo)
{
int matched;
FILE *modesdb;
struct fb_var_screeninfo cinfo;
matched = 0;
modesdb = fopen(FB_MODES_DB, "r");
if (modesdb) {
/* Parse the mode definition file */
while (read_fbmodes_mode(modesdb, &cinfo)) {
if ((vinfo->xres == cinfo.xres && vinfo->yres == cinfo.yres)
&& (!matched
|| (vinfo->bits_per_pixel == cinfo.bits_per_pixel))) {
vinfo->pixclock = cinfo.pixclock;
vinfo->left_margin = cinfo.left_margin;
vinfo->right_margin = cinfo.right_margin;
vinfo->upper_margin = cinfo.upper_margin;
vinfo->lower_margin = cinfo.lower_margin;
vinfo->hsync_len = cinfo.hsync_len;
vinfo->vsync_len = cinfo.vsync_len;
if (matched) {
break;
}
matched = 1;
}
}
fclose(modesdb);
}
return (matched);
}
static int
choose_vesa_mode(struct fb_var_screeninfo *vinfo)
{
int matched;
int i;
/* Check for VESA timings */
matched = 0;
for (i = 0; i < (sizeof(vesa_timings) / sizeof(vesa_timings[0])); ++i) {
if ((vinfo->xres == vesa_timings[i].xres) &&
(vinfo->yres == vesa_timings[i].yres)) {
#ifdef FBCON_DEBUG
fprintf(stderr, "Using VESA timings for %dx%d\n",
vinfo->xres, vinfo->yres);
#endif
if (vesa_timings[i].pixclock) {
vinfo->pixclock = vesa_timings[i].pixclock;
}
vinfo->left_margin = vesa_timings[i].left;
vinfo->right_margin = vesa_timings[i].right;
vinfo->upper_margin = vesa_timings[i].upper;
vinfo->lower_margin = vesa_timings[i].lower;
vinfo->hsync_len = vesa_timings[i].hslen;
vinfo->vsync_len = vesa_timings[i].vslen;
vinfo->sync = vesa_timings[i].sync;
vinfo->vmode = vesa_timings[i].vmode;
matched = 1;
break;
}
}
return (matched);
}
#ifdef VGA16_FBCON_SUPPORT
static SDL_Surface *
FB_SetVGA16Mode(_THIS, SDL_Surface * current,
int width, int height, int bpp, Uint32 flags)
{
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
/* Set the terminal into graphics mode */
if (FB_EnterGraphicsMode(this) < 0) {
return (NULL);
}
/* Restore the original palette */
FB_RestorePalette(this);
/* Set the video mode and get the final screen format */
if (ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
SDL_SetError("Couldn't get console screen info");
return (NULL);
}
cache_vinfo = vinfo;
#ifdef FBCON_DEBUG
fprintf(stderr, "Printing actual vinfo:\n");
print_vinfo(&vinfo);
#endif
if (!SDL_ReallocFormat(current, bpp, 0, 0, 0, 0)) {
return (NULL);
}
current->format->palette->ncolors = 16;
/* Get the fixed information about the console hardware.
This is necessary since finfo.line_length changes.
*/
if (ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
SDL_SetError("Couldn't get console hardware info");
return (NULL);
}
#ifdef FBCON_DEBUG
fprintf(stderr, "Printing actual finfo:\n");
print_finfo(&finfo);
#endif
/* Save hardware palette, if needed */
FB_SavePalette(this, &finfo, &vinfo);
/* Set up the new mode framebuffer */
current->flags = SDL_FULLSCREEN;
current->w = vinfo.xres;
current->h = vinfo.yres;
current->pitch = current->w;
current->pixels = SDL_malloc(current->h * current->pitch);
/* Set the update rectangle function */
this->UpdateRects = FB_VGA16Update;
/* We're done */
return (current);
}
#endif /* VGA16_FBCON_SUPPORT */
static SDL_Surface *
FB_SetVideoMode(_THIS, SDL_Surface * current,
int width, int height, int bpp, Uint32 flags)
{
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
int i;
Uint32 Rmask;
Uint32 Gmask;
Uint32 Bmask;
char *surfaces_mem;
int surfaces_len;
/* Set the terminal into graphics mode */
if (FB_EnterGraphicsMode(this) < 0) {
return (NULL);
}
/* Restore the original palette */
FB_RestorePalette(this);
/* Set the video mode and get the final screen format */
if (ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
SDL_SetError("Couldn't get console screen info");
return (NULL);
}
#ifdef FBCON_DEBUG
fprintf(stderr, "Printing original vinfo:\n");
print_vinfo(&vinfo);
#endif
if ((vinfo.xres != width) || (vinfo.yres != height) ||
(vinfo.bits_per_pixel != bpp) || (flags & SDL_DOUBLEBUF)) {
vinfo.activate = FB_ACTIVATE_NOW;
vinfo.accel_flags = 0;
vinfo.bits_per_pixel = bpp;
vinfo.xres = width;
vinfo.xres_virtual = width;
vinfo.yres = height;
if (flags & SDL_DOUBLEBUF) {
vinfo.yres_virtual = height * 2;
} else {
vinfo.yres_virtual = height;
}
vinfo.xoffset = 0;
vinfo.yoffset = 0;
vinfo.red.length = vinfo.red.offset = 0;
vinfo.green.length = vinfo.green.offset = 0;
vinfo.blue.length = vinfo.blue.offset = 0;
vinfo.transp.length = vinfo.transp.offset = 0;
if (!choose_fbmodes_mode(&vinfo)) {
choose_vesa_mode(&vinfo);
}
#ifdef FBCON_DEBUG
fprintf(stderr, "Printing wanted vinfo:\n");
print_vinfo(&vinfo);
#endif
if (ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
vinfo.yres_virtual = height;
if (ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
SDL_SetError("Couldn't set console screen info");
return (NULL);
}
}
} else {
int maxheight;
/* Figure out how much video memory is available */
if (flags & SDL_DOUBLEBUF) {
maxheight = height * 2;
} else {
maxheight = height;
}
if (vinfo.yres_virtual > maxheight) {
vinfo.yres_virtual = maxheight;
}
}
cache_vinfo = vinfo;
#ifdef FBCON_DEBUG
fprintf(stderr, "Printing actual vinfo:\n");
print_vinfo(&vinfo);
#endif
Rmask = 0;
for (i = 0; i < vinfo.red.length; ++i) {
Rmask <<= 1;
Rmask |= (0x00000001 << vinfo.red.offset);
}
Gmask = 0;
for (i = 0; i < vinfo.green.length; ++i) {
Gmask <<= 1;
Gmask |= (0x00000001 << vinfo.green.offset);
}
Bmask = 0;
for (i = 0; i < vinfo.blue.length; ++i) {
Bmask <<= 1;
Bmask |= (0x00000001 << vinfo.blue.offset);
}
if (!SDL_ReallocFormat(current, vinfo.bits_per_pixel,
Rmask, Gmask, Bmask, 0)) {
return (NULL);
}
/* Get the fixed information about the console hardware.
This is necessary since finfo.line_length changes.
*/
if (ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
SDL_SetError("Couldn't get console hardware info");
return (NULL);
}
/* Save hardware palette, if needed */
FB_SavePalette(this, &finfo, &vinfo);
/* Set up the new mode framebuffer */
current->flags = (SDL_FULLSCREEN | SDL_HWSURFACE);
current->w = vinfo.xres;
current->h = vinfo.yres;
current->pitch = finfo.line_length;
current->pixels = mapped_mem + mapped_offset;
/* Set up the information for hardware surfaces */
surfaces_mem = (char *) current->pixels +
vinfo.yres_virtual * current->pitch;
surfaces_len = (mapped_memlen - (surfaces_mem - mapped_mem));
FB_FreeHWSurfaces(this);
FB_InitHWSurfaces(this, current, surfaces_mem, surfaces_len);
/* Let the application know we have a hardware palette */
switch (finfo.visual) {
case FB_VISUAL_PSEUDOCOLOR:
current->flags |= SDL_HWPALETTE;
break;
default:
break;
}
/* Update for double-buffering, if we can */
if (flags & SDL_DOUBLEBUF) {
if (vinfo.yres_virtual == (height * 2)) {
current->flags |= SDL_DOUBLEBUF;
flip_page = 0;
flip_address[0] = (char *) current->pixels;
flip_address[1] = (char *) current->pixels +
current->h * current->pitch;
this->screen = current;
FB_FlipHWSurface(this, current);
this->screen = NULL;
}
}
/* Set the update rectangle function */
this->UpdateRects = FB_DirectUpdate;
/* We're done */
return (current);
}
#ifdef FBCON_DEBUG
void
FB_DumpHWSurfaces(_THIS)
{
vidmem_bucket *bucket;
printf("Memory left: %d (%d total)\n", surfaces_memleft,
surfaces_memtotal);
printf("\n");
printf(" Base Size\n");
for (bucket = &surfaces; bucket; bucket = bucket->next) {
printf("Bucket: %p, %d (%s)\n", bucket->base, bucket->size,
bucket->used ? "used" : "free");
if (bucket->prev) {
if (bucket->base != bucket->prev->base + bucket->prev->size) {
printf("Warning, corrupt bucket list! (prev)\n");
}
} else {
if (bucket != &surfaces) {
printf("Warning, corrupt bucket list! (!prev)\n");
}
}
if (bucket->next) {
if (bucket->next->base != bucket->base + bucket->size) {
printf("Warning, corrupt bucket list! (next)\n");
}
}
}
printf("\n");
}
#endif
static int
FB_InitHWSurfaces(_THIS, SDL_Surface * screen, char *base, int size)
{
vidmem_bucket *bucket;
surfaces_memtotal = size;
surfaces_memleft = size;
if (surfaces_memleft > 0) {
bucket = (vidmem_bucket *) SDL_malloc(sizeof(*bucket));
if (bucket == NULL) {
SDL_OutOfMemory();
return (-1);
}
bucket->prev = &surfaces;
bucket->used = 0;
bucket->dirty = 0;
bucket->base = base;
bucket->size = size;
bucket->next = NULL;
} else {
bucket = NULL;
}
surfaces.prev = NULL;
surfaces.used = 1;
surfaces.dirty = 0;
surfaces.base = screen->pixels;
surfaces.size = (unsigned int) ((long) base - (long) surfaces.base);
surfaces.next = bucket;
screen->hwdata = (struct private_hwdata *) &surfaces;
return (0);
}
static void
FB_FreeHWSurfaces(_THIS)
{
vidmem_bucket *bucket, *freeable;
bucket = surfaces.next;
while (bucket) {
freeable = bucket;
bucket = bucket->next;
SDL_free(freeable);
}
surfaces.next = NULL;
}
static int
FB_AllocHWSurface(_THIS, SDL_Surface * surface)
{
vidmem_bucket *bucket;
int size;
int extra;
/* Temporarily, we only allow surfaces the same width as display.
Some blitters require the pitch between two hardware surfaces
to be the same. Others have interesting alignment restrictions.
Until someone who knows these details looks at the code...
*/
if (surface->pitch > SDL_VideoSurface->pitch) {
SDL_SetError("Surface requested wider than screen");
return (-1);
}
surface->pitch = SDL_VideoSurface->pitch;
size = surface->h * surface->pitch;
#ifdef FBCON_DEBUG
fprintf(stderr, "Allocating bucket of %d bytes\n", size);
#endif
/* Quick check for available mem */
if (size > surfaces_memleft) {
SDL_SetError("Not enough video memory");
return (-1);
}
/* Search for an empty bucket big enough */
for (bucket = &surfaces; bucket; bucket = bucket->next) {
if (!bucket->used && (size <= bucket->size)) {
break;
}
}
if (bucket == NULL) {
SDL_SetError("Video memory too fragmented");
return (-1);
}
/* Create a new bucket for left-over memory */
extra = (bucket->size - size);
if (extra) {
vidmem_bucket *newbucket;
#ifdef FBCON_DEBUG
fprintf(stderr, "Adding new free bucket of %d bytes\n", extra);
#endif
newbucket = (vidmem_bucket *) SDL_malloc(sizeof(*newbucket));
if (newbucket == NULL) {
SDL_OutOfMemory();
return (-1);
}
newbucket->prev = bucket;
newbucket->used = 0;
newbucket->base = bucket->base + size;
newbucket->size = extra;
newbucket->next = bucket->next;
if (bucket->next) {
bucket->next->prev = newbucket;
}
bucket->next = newbucket;
}
/* Set the current bucket values and return it! */
bucket->used = 1;
bucket->size = size;
bucket->dirty = 0;
#ifdef FBCON_DEBUG
fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base);
#endif
surfaces_memleft -= size;
surface->flags |= SDL_HWSURFACE;
surface->pixels = bucket->base;
surface->hwdata = (struct private_hwdata *) bucket;
return (0);
}
static void
FB_FreeHWSurface(_THIS, SDL_Surface * surface)
{
vidmem_bucket *bucket, *freeable;
/* Look for the bucket in the current list */
for (bucket = &surfaces; bucket; bucket = bucket->next) {
if (bucket == (vidmem_bucket *) surface->hwdata) {
break;
}
}
if (bucket && bucket->used) {
/* Add the memory back to the total */
#ifdef DGA_DEBUG
printf("Freeing bucket of %d bytes\n", bucket->size);
#endif
surfaces_memleft += bucket->size;
/* Can we merge the space with surrounding buckets? */
bucket->used = 0;
if (bucket->next && !bucket->next->used) {
#ifdef DGA_DEBUG
printf("Merging with next bucket, for %d total bytes\n",
bucket->size + bucket->next->size);
#endif
freeable = bucket->next;
bucket->size += bucket->next->size;
bucket->next = bucket->next->next;
if (bucket->next) {
bucket->next->prev = bucket;
}
SDL_free(freeable);
}
if (bucket->prev && !bucket->prev->used) {
#ifdef DGA_DEBUG
printf("Merging with previous bucket, for %d total bytes\n",
bucket->prev->size + bucket->size);
#endif
freeable = bucket;
bucket->prev->size += bucket->size;
bucket->prev->next = bucket->next;
if (bucket->next) {
bucket->next->prev = bucket->prev;
}
SDL_free(freeable);
}
}
surface->pixels = NULL;
surface->hwdata = NULL;
}
static int
FB_LockHWSurface(_THIS, SDL_Surface * surface)
{
if (switched_away) {
return -2; /* no hardware access */
}
if (surface == this->screen) {
SDL_mutexP(hw_lock);
if (FB_IsSurfaceBusy(surface)) {
FB_WaitBusySurfaces(this);
}
} else {
if (FB_IsSurfaceBusy(surface)) {
FB_WaitBusySurfaces(this);
}
}
return (0);
}
static void
FB_UnlockHWSurface(_THIS, SDL_Surface * surface)
{
if (surface == this->screen) {
SDL_mutexV(hw_lock);
}
}
static void
FB_WaitVBL(_THIS)
{
#ifdef FBIOWAITRETRACE /* Heheh, this didn't make it into the main kernel */
ioctl(console_fd, FBIOWAITRETRACE, 0);
#endif
return;
}
static void
FB_WaitIdle(_THIS)
{
return;
}
static int
FB_FlipHWSurface(_THIS, SDL_Surface * surface)
{
if (switched_away) {
return -2; /* no hardware access */
}
/* Wait for vertical retrace and then flip display */
cache_vinfo.yoffset = flip_page * surface->h;
if (FB_IsSurfaceBusy(this->screen)) {
FB_WaitBusySurfaces(this);
}
wait_vbl(this);
if (ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0) {
SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed");
return (-1);
}
flip_page = !flip_page;
surface->pixels = flip_address[flip_page];
return (0);
}
static void
FB_DirectUpdate(_THIS, int numrects, SDL_Rect * rects)
{
/* The application is already updating the visible video memory */
return;
}
#ifdef VGA16_FBCON_SUPPORT
/* Code adapted with thanks from the XFree86 VGA16 driver! :) */
#define writeGr(index, value) \
outb(index, 0x3CE); \
outb(value, 0x3CF);
#define writeSeq(index, value) \
outb(index, 0x3C4); \
outb(value, 0x3C5);
static void
FB_VGA16Update(_THIS, int numrects, SDL_Rect * rects)
{
SDL_Surface *screen;
int width, height, FBPitch, left, i, j, SRCPitch, phase;
register Uint32 m;
Uint8 s1, s2, s3, s4;
Uint32 *src, *srcPtr;
Uint8 *dst, *dstPtr;
if (switched_away) {
return; /* no hardware access */
}
screen = this->screen;
FBPitch = screen->w >> 3;
SRCPitch = screen->pitch >> 2;
writeGr(0x03, 0x00);
writeGr(0x05, 0x00);
writeGr(0x01, 0x00);
writeGr(0x08, 0xFF);
while (numrects--) {
left = rects->x & ~7;
width = (rects->w + 7) >> 3;
height = rects->h;
src = (Uint32 *) screen->pixels + (rects->y * SRCPitch) + (left >> 2);
dst = (Uint8 *) mapped_mem + (rects->y * FBPitch) + (left >> 3);
if ((phase = (long) dst & 3L)) {
phase = 4 - phase;
if (phase > width)
phase = width;
width -= phase;
}
while (height--) {
writeSeq(0x02, 1 << 0);
dstPtr = dst;
srcPtr = src;
i = width;
j = phase;
while (j--) {
m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101)
<< 4);
*dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
srcPtr += 2;
}
while (i >= 4) {
m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101)
<< 4);
s1 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
m = (srcPtr[3] & 0x01010101) | ((srcPtr[2] & 0x01010101)
<< 4);
s2 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
m = (srcPtr[5] & 0x01010101) | ((srcPtr[4] & 0x01010101)
<< 4);
s3 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
m = (srcPtr[7] & 0x01010101) | ((srcPtr[6] & 0x01010101)
<< 4);
s4 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
*((Uint32 *) dstPtr) =
s1 | (s2 << 8) | (s3 << 16) | (s4 << 24);
srcPtr += 8;
dstPtr += 4;
i -= 4;
}
while (i--) {
m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101)
<< 4);
*dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
srcPtr += 2;
}
writeSeq(0x02, 1 << 1);
dstPtr = dst;
srcPtr = src;
i = width;
j = phase;
while (j--) {
m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202)
<< 4);
*dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
srcPtr += 2;
}
while (i >= 4) {
m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202)
<< 4);
s1 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
m = (srcPtr[3] & 0x02020202) | ((srcPtr[2] & 0x02020202)
<< 4);
s2 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
m = (srcPtr[5] & 0x02020202) | ((srcPtr[4] & 0x02020202)
<< 4);
s3 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
m = (srcPtr[7] & 0x02020202) | ((srcPtr[6] & 0x02020202)
<< 4);
s4 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
*((Uint32 *) dstPtr) =
s1 | (s2 << 8) | (s3 << 16) | (s4 << 24);
srcPtr += 8;
dstPtr += 4;
i -= 4;
}
while (i--) {
m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202)
<< 4);
*dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
srcPtr += 2;
}
writeSeq(0x02, 1 << 2);
dstPtr = dst;
srcPtr = src;
i = width;
j = phase;
while (j--) {
m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404)
<< 4);
*dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
srcPtr += 2;
}
while (i >= 4) {
m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404)
<< 4);
s1 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
m = (srcPtr[3] & 0x04040404) | ((srcPtr[2] & 0x04040404)
<< 4);
s2 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
m = (srcPtr[5] & 0x04040404) | ((srcPtr[4] & 0x04040404)
<< 4);
s3 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
m = (srcPtr[7] & 0x04040404) | ((srcPtr[6] & 0x04040404)
<< 4);
s4 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
*((Uint32 *) dstPtr) =
s1 | (s2 << 8) | (s3 << 16) | (s4 << 24);
srcPtr += 8;
dstPtr += 4;
i -= 4;
}
while (i--) {
m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404)
<< 4);
*dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
srcPtr += 2;
}
writeSeq(0x02, 1 << 3);
dstPtr = dst;
srcPtr = src;
i = width;
j = phase;
while (j--) {
m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808)
<< 4);
*dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m;
srcPtr += 2;
}
while (i >= 4) {
m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808)
<< 4);
s1 = (m >> 27) | (m >> 18) | (m >> 9) | m;
m = (srcPtr[3] & 0x08080808) | ((srcPtr[2] & 0x08080808)
<< 4);
s2 = (m >> 27) | (m >> 18) | (m >> 9) | m;
m = (srcPtr[5] & 0x08080808) | ((srcPtr[4] & 0x08080808)
<< 4);
s3 = (m >> 27) | (m >> 18) | (m >> 9) | m;
m = (srcPtr[7] & 0x08080808) | ((srcPtr[6] & 0x08080808)
<< 4);
s4 = (m >> 27) | (m >> 18) | (m >> 9) | m;
*((Uint32 *) dstPtr) =
s1 | (s2 << 8) | (s3 << 16) | (s4 << 24);
srcPtr += 8;
dstPtr += 4;
i -= 4;
}
while (i--) {
m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808)
<< 4);
*dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m;
srcPtr += 2;
}
dst += FBPitch;
src += SRCPitch;
}
rects++;
}
}
#endif /* VGA16_FBCON_SUPPORT */
void
FB_SavePaletteTo(_THIS, int palette_len, __u16 * area)
{
struct fb_cmap cmap;
cmap.start = 0;
cmap.len = palette_len;
cmap.red = &area[0 * palette_len];
cmap.green = &area[1 * palette_len];
cmap.blue = &area[2 * palette_len];
cmap.transp = NULL;
ioctl(console_fd, FBIOGETCMAP, &cmap);
}
void
FB_RestorePaletteFrom(_THIS, int palette_len, __u16 * area)
{
struct fb_cmap cmap;
cmap.start = 0;
cmap.len = palette_len;
cmap.red = &area[0 * palette_len];
cmap.green = &area[1 * palette_len];
cmap.blue = &area[2 * palette_len];
cmap.transp = NULL;
ioctl(console_fd, FBIOPUTCMAP, &cmap);
}
static void
FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo,
struct fb_var_screeninfo *vinfo)
{
int i;
/* Save hardware palette, if needed */
if (finfo->visual == FB_VISUAL_PSEUDOCOLOR) {
saved_cmaplen = 1 << vinfo->bits_per_pixel;
saved_cmap =
(__u16 *) SDL_malloc(3 * saved_cmaplen * sizeof(*saved_cmap));
if (saved_cmap != NULL) {
FB_SavePaletteTo(this, saved_cmaplen, saved_cmap);
}
}
/* Added support for FB_VISUAL_DIRECTCOLOR.
With this mode pixel information is passed through the palette...
Neat fading and gamma correction effects can be had by simply
fooling around with the palette instead of changing the pixel
values themselves... Very neat!
Adam Meyerowitz 1/19/2000
ameyerow@optonline.com
*/
if (finfo->visual == FB_VISUAL_DIRECTCOLOR) {
__u16 new_entries[3 * 256];
/* Save the colormap */
saved_cmaplen = 256;
saved_cmap =
(__u16 *) SDL_malloc(3 * saved_cmaplen * sizeof(*saved_cmap));
if (saved_cmap != NULL) {
FB_SavePaletteTo(this, saved_cmaplen, saved_cmap);
}
/* Allocate new identity colormap */
for (i = 0; i < 256; ++i) {
new_entries[(0 * 256) + i] =
new_entries[(1 * 256) + i] =
new_entries[(2 * 256) + i] = (i << 8) | i;
}
FB_RestorePaletteFrom(this, 256, new_entries);
}
}
static void
FB_RestorePalette(_THIS)
{
/* Restore the original palette */
if (saved_cmap) {
FB_RestorePaletteFrom(this, saved_cmaplen, saved_cmap);
SDL_free(saved_cmap);
saved_cmap = NULL;
}
}
static int
FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
{
int i;
__u16 r[256];
__u16 g[256];
__u16 b[256];
struct fb_cmap cmap;
/* Set up the colormap */
for (i = 0; i < ncolors; i++) {
r[i] = colors[i].r << 8;
g[i] = colors[i].g << 8;
b[i] = colors[i].b << 8;
}
cmap.start = firstcolor;
cmap.len = ncolors;
cmap.red = r;
cmap.green = g;
cmap.blue = b;
cmap.transp = NULL;
if ((ioctl(console_fd, FBIOPUTCMAP, &cmap) < 0) ||
!(this->screen->flags & SDL_HWPALETTE)) {
colors = this->screen->format->palette->colors;
ncolors = this->screen->format->palette->ncolors;
cmap.start = 0;
cmap.len = ncolors;
SDL_memset(r, 0, sizeof(r));
SDL_memset(g, 0, sizeof(g));
SDL_memset(b, 0, sizeof(b));
if (ioctl(console_fd, FBIOGETCMAP, &cmap) == 0) {
for (i = ncolors - 1; i >= 0; --i) {
colors[i].r = (r[i] >> 8);
colors[i].g = (g[i] >> 8);
colors[i].b = (b[i] >> 8);
}
}
return (0);
}
return (1);
}
/* Note: If we are terminated, this could be called in the middle of
another SDL video routine -- notably UpdateRects.
*/
static void
FB_VideoQuit(_THIS)
{
int i, j;
if (this->screen) {
/* Clear screen and tell SDL not to free the pixels */
if (this->screen->pixels && FB_InGraphicsMode(this)) {
#if defined(__powerpc__) || defined(__ia64__) /* SIGBUS when using SDL_memset() ?? */
Uint8 *rowp = (Uint8 *) this->screen->pixels;
int left = this->screen->pitch * this->screen->h;
while (left--) {
*rowp++ = 0;
}
#else
SDL_memset(this->screen->pixels, 0,
this->screen->h * this->screen->pitch);
#endif
}
/* This test fails when using the VGA16 shadow memory */
if (((char *) this->screen->pixels >= mapped_mem) &&
((char *) this->screen->pixels < (mapped_mem + mapped_memlen))) {
this->screen->pixels = NULL;
}
}
/* Clear the lock mutex */
if (hw_lock) {
SDL_DestroyMutex(hw_lock);
hw_lock = NULL;
}
/* Clean up defined video modes */
for (i = 0; i < NUM_MODELISTS; ++i) {
if (SDL_modelist[i] != NULL) {
for (j = 0; SDL_modelist[i][j]; ++j) {
SDL_free(SDL_modelist[i][j]);
}
SDL_free(SDL_modelist[i]);
SDL_modelist[i] = NULL;
}
}
/* Clean up the memory bucket list */
FB_FreeHWSurfaces(this);
/* Close console and input file descriptors */
if (console_fd > 0) {
/* Unmap the video framebuffer and I/O registers */
if (mapped_mem) {
munmap(mapped_mem, mapped_memlen);
mapped_mem = NULL;
}
if (mapped_io) {
munmap(mapped_io, mapped_iolen);
mapped_io = NULL;
}
/* Restore the original video mode and palette */
if (FB_InGraphicsMode(this)) {
FB_RestorePalette(this);
ioctl(console_fd, FBIOPUT_VSCREENINFO, &saved_vinfo);
}
/* We're all done with the framebuffer */
close(console_fd);
console_fd = -1;
}
FB_CloseMouse(this);
FB_CloseKeyboard(this);
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#ifndef _SDL_fbvideo_h
#define _SDL_fbvideo_h
#include <sys/types.h>
#include <termios.h>
#include <linux/fb.h>
#include "SDL_mouse.h"
#include "SDL_mutex.h"
#include "../SDL_sysvideo.h"
#if SDL_INPUT_TSLIB
#include "tslib.h"
#endif
/* Hidden "this" pointer for the video functions */
#define _THIS SDL_VideoDevice *this
/* This is the structure we use to keep track of video memory */
typedef struct vidmem_bucket
{
struct vidmem_bucket *prev;
int used;
int dirty;
char *base;
unsigned int size;
struct vidmem_bucket *next;
} vidmem_bucket;
/* Private display data */
struct SDL_PrivateVideoData
{
int console_fd;
struct fb_var_screeninfo cache_vinfo;
struct fb_var_screeninfo saved_vinfo;
int saved_cmaplen;
__u16 *saved_cmap;
int current_vt;
int saved_vt;
int keyboard_fd;
int saved_kbd_mode;
struct termios saved_kbd_termios;
int mouse_fd;
#if SDL_INPUT_TSLIB
struct tsdev *ts_dev;
#endif
char *mapped_mem;
int mapped_memlen;
int mapped_offset;
char *mapped_io;
long mapped_iolen;
int flip_page;
char *flip_address[2];
#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */
int SDL_nummodes[NUM_MODELISTS];
SDL_Rect **SDL_modelist[NUM_MODELISTS];
vidmem_bucket surfaces;
int surfaces_memtotal;
int surfaces_memleft;
SDL_mutex *hw_lock;
int switched_away;
struct fb_var_screeninfo screen_vinfo;
Uint32 screen_arealen;
Uint8 *screen_contents;
__u16 screen_palette[3 * 256];
void (*wait_vbl) (_THIS);
void (*wait_idle) (_THIS);
};
/* Old variable names */
#define console_fd (this->hidden->console_fd)
#define current_vt (this->hidden->current_vt)
#define saved_vt (this->hidden->saved_vt)
#define keyboard_fd (this->hidden->keyboard_fd)
#define saved_kbd_mode (this->hidden->saved_kbd_mode)
#define saved_kbd_termios (this->hidden->saved_kbd_termios)
#define mouse_fd (this->hidden->mouse_fd)
#if SDL_INPUT_TSLIB
#define ts_dev (this->hidden->ts_dev)
#endif
#define cache_vinfo (this->hidden->cache_vinfo)
#define saved_vinfo (this->hidden->saved_vinfo)
#define saved_cmaplen (this->hidden->saved_cmaplen)
#define saved_cmap (this->hidden->saved_cmap)
#define mapped_mem (this->hidden->mapped_mem)
#define mapped_memlen (this->hidden->mapped_memlen)
#define mapped_offset (this->hidden->mapped_offset)
#define mapped_io (this->hidden->mapped_io)
#define mapped_iolen (this->hidden->mapped_iolen)
#define flip_page (this->hidden->flip_page)
#define flip_address (this->hidden->flip_address)
#define SDL_nummodes (this->hidden->SDL_nummodes)
#define SDL_modelist (this->hidden->SDL_modelist)
#define surfaces (this->hidden->surfaces)
#define surfaces_memtotal (this->hidden->surfaces_memtotal)
#define surfaces_memleft (this->hidden->surfaces_memleft)
#define hw_lock (this->hidden->hw_lock)
#define switched_away (this->hidden->switched_away)
#define screen_vinfo (this->hidden->screen_vinfo)
#define screen_arealen (this->hidden->screen_arealen)
#define screen_contents (this->hidden->screen_contents)
#define screen_palette (this->hidden->screen_palette)
#define wait_vbl (this->hidden->wait_vbl)
#define wait_idle (this->hidden->wait_idle)
/* Accelerator types that are supported by the driver, but are not
necessarily in the kernel headers on the system we compile on.
*/
#ifndef FB_ACCEL_MATROX_MGAG400
#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */
#endif
#ifndef FB_ACCEL_3DFX_BANSHEE
#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */
#endif
/* These functions are defined in SDL_fbvideo.c */
extern void FB_SavePaletteTo(_THIS, int palette_len, __u16 * area);
extern void FB_RestorePaletteFrom(_THIS, int palette_len, __u16 * area);
/* These are utility functions for working with video surfaces */
static __inline__ void
FB_AddBusySurface(SDL_Surface * surface)
{
((vidmem_bucket *) surface->hwdata)->dirty = 1;
}
static __inline__ int
FB_IsSurfaceBusy(SDL_Surface * surface)
{
return ((vidmem_bucket *) surface->hwdata)->dirty;
}
static __inline__ void
FB_WaitBusySurfaces(_THIS)
{
vidmem_bucket *bucket;
/* Wait for graphic operations to complete */
wait_idle(this);
/* Clear all surface dirty bits */
for (bucket = &surfaces; bucket; bucket = bucket->next) {
bucket->dirty = 0;
}
}
static __inline__ void
FB_dst_to_xy(_THIS, SDL_Surface * dst, int *x, int *y)
{
*x = (long) ((char *) dst->pixels - mapped_mem) % this->screen->pitch;
*y = (long) ((char *) dst->pixels - mapped_mem) / this->screen->pitch;
if (dst == this->screen) {
*x += this->offset_x;
*y += this->offset_y;
}
}
#endif /* _SDL_fbvideo_h */
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* MGA register definitions */
#include "matrox_regs.h"
/* MGA control macros */
#define mga_in8(reg) *(volatile Uint8 *)(mapped_io + (reg))
#define mga_in32(reg) *(volatile Uint32 *)(mapped_io + (reg))
#define mga_out8(reg,v) *(volatile Uint8 *)(mapped_io + (reg)) = v;
#define mga_out32(reg,v) *(volatile Uint32 *)(mapped_io + (reg)) = v;
/* Wait for fifo space */
#define mga_wait(space) \
{ \
while ( mga_in8(MGAREG_FIFOSTATUS) < space ) \
; \
}
/* Wait for idle accelerator */
#define mga_waitidle() \
{ \
while ( mga_in32(MGAREG_STATUS) & 0x10000 ) \
; \
}
/* vi: set ts=4 sw=4 expandtab: */
/*
* MGA Millennium (MGA2064W) functions
* MGA Mystique (MGA1064SG) functions
*
* Copyright 1996 The XFree86 Project, Inc.
*
* Authors
* Dirk Hohndel
* hohndel@XFree86.Org
* David Dawes
* dawes@XFree86.Org
* Contributors:
* Guy DESBIEF, Aix-en-provence, France
* g.desbief@aix.pacwan.net
* MGA1064SG Mystique register file
*/
#ifndef _MGA_REG_H_
#define _MGA_REG_H_
#define MGAREG_DWGCTL 0x1c00
#define MGAREG_MACCESS 0x1c04
/* the following is a mystique only register */
#define MGAREG_MCTLWTST 0x1c08
#define MGAREG_ZORG 0x1c0c
#define MGAREG_PAT0 0x1c10
#define MGAREG_PAT1 0x1c14
#define MGAREG_PLNWT 0x1c1c
#define MGAREG_BCOL 0x1c20
#define MGAREG_FCOL 0x1c24
#define MGAREG_SRC0 0x1c30
#define MGAREG_SRC1 0x1c34
#define MGAREG_SRC2 0x1c38
#define MGAREG_SRC3 0x1c3c
#define MGAREG_XYSTRT 0x1c40
#define MGAREG_XYEND 0x1c44
#define MGAREG_SHIFT 0x1c50
/* the following is a mystique only register */
#define MGAREG_DMAPAD 0x1c54
#define MGAREG_SGN 0x1c58
#define MGAREG_LEN 0x1c5c
#define MGAREG_AR0 0x1c60
#define MGAREG_AR1 0x1c64
#define MGAREG_AR2 0x1c68
#define MGAREG_AR3 0x1c6c
#define MGAREG_AR4 0x1c70
#define MGAREG_AR5 0x1c74
#define MGAREG_AR6 0x1c78
#define MGAREG_CXBNDRY 0x1c80
#define MGAREG_FXBNDRY 0x1c84
#define MGAREG_YDSTLEN 0x1c88
#define MGAREG_PITCH 0x1c8c
#define MGAREG_YDST 0x1c90
#define MGAREG_YDSTORG 0x1c94
#define MGAREG_YTOP 0x1c98
#define MGAREG_YBOT 0x1c9c
#define MGAREG_CXLEFT 0x1ca0
#define MGAREG_CXRIGHT 0x1ca4
#define MGAREG_FXLEFT 0x1ca8
#define MGAREG_FXRIGHT 0x1cac
#define MGAREG_XDST 0x1cb0
#define MGAREG_DR0 0x1cc0
#define MGAREG_DR1 0x1cc4
#define MGAREG_DR2 0x1cc8
#define MGAREG_DR3 0x1ccc
#define MGAREG_DR4 0x1cd0
#define MGAREG_DR5 0x1cd4
#define MGAREG_DR6 0x1cd8
#define MGAREG_DR7 0x1cdc
#define MGAREG_DR8 0x1ce0
#define MGAREG_DR9 0x1ce4
#define MGAREG_DR10 0x1ce8
#define MGAREG_DR11 0x1cec
#define MGAREG_DR12 0x1cf0
#define MGAREG_DR13 0x1cf4
#define MGAREG_DR14 0x1cf8
#define MGAREG_DR15 0x1cfc
#define MGAREG_SRCORG 0x2cb4
#define MGAREG_DSTORG 0x2cb8
/* add or or this to one of the previous "power registers" to start
the drawing engine */
#define MGAREG_EXEC 0x0100
#define MGAREG_FIFOSTATUS 0x1e10
#define MGAREG_STATUS 0x1e14
#define MGAREG_ICLEAR 0x1e18
#define MGAREG_IEN 0x1e1c
#define MGAREG_VCOUNT 0x1e20
#define MGAREG_Reset 0x1e40
#define MGAREG_OPMODE 0x1e54
/* OPMODE register additives */
#define MGAOPM_DMA_GENERAL (0x00 << 2)
#define MGAOPM_DMA_BLIT (0x01 << 2)
#define MGAOPM_DMA_VECTOR (0x10 << 2)
/* DWGCTL register additives */
/* Lines */
#define MGADWG_LINE_OPEN 0x00
#define MGADWG_AUTOLINE_OPEN 0x01
#define MGADWG_LINE_CLOSE 0x02
#define MGADWG_AUTOLINE_CLOSE 0x03
/* Trapezoids */
#define MGADWG_TRAP 0x04
#define MGADWG_TEXTURE_TRAP 0x05
/* BitBlts */
#define MGADWG_BITBLT 0x08
#define MGADWG_FBITBLT 0x0c
#define MGADWG_ILOAD 0x09
#define MGADWG_ILOAD_SCALE 0x0d
#define MGADWG_ILOAD_FILTER 0x0f
#define MGADWG_IDUMP 0x0a
/* atype access to WRAM */
#define MGADWG_RPL ( 0x00 << 4 )
#define MGADWG_RSTR ( 0x01 << 4 )
#define MGADWG_ZI ( 0x03 << 4 )
#define MGADWG_BLK ( 0x04 << 4 )
#define MGADWG_I ( 0x07 << 4 )
/* specifies whether bit blits are linear or xy */
#define MGADWG_LINEAR ( 0x01 << 7 )
/* z drawing mode. use MGADWG_NOZCMP for always */
#define MGADWG_NOZCMP ( 0x00 << 8 )
#define MGADWG_ZE ( 0x02 << 8 )
#define MGADWG_ZNE ( 0x03 << 8 )
#define MGADWG_ZLT ( 0x04 << 8 )
#define MGADWG_ZLTE ( 0x05 << 8 )
#define MGADWG_GT ( 0x06 << 8 )
#define MGADWG_GTE ( 0x07 << 8 )
/* use this to force colour expansion circuitry to do its stuff */
#define MGADWG_SOLID ( 0x01 << 11 )
/* ar register at zero */
#define MGADWG_ARZERO ( 0x01 << 12 )
#define MGADWG_SGNZERO ( 0x01 << 13 )
#define MGADWG_SHIFTZERO ( 0x01 << 14 )
/* See table on 4-43 for bop ALU operations */
/* See table on 4-44 for translucidity masks */
#define MGADWG_BMONOLEF ( 0x00 << 25 )
#define MGADWG_BMONOWF ( 0x04 << 25 )
#define MGADWG_BPLAN ( 0x01 << 25 )
/* note that if bfcol is specified and you're doing a bitblt, it causes
a fbitblt to be performed, so check that you obey the fbitblt rules */
#define MGADWG_BFCOL ( 0x02 << 25 )
#define MGADWG_BUYUV ( 0x0e << 25 )
#define MGADWG_BU32BGR ( 0x03 << 25 )
#define MGADWG_BU32RGB ( 0x07 << 25 )
#define MGADWG_BU24BGR ( 0x0b << 25 )
#define MGADWG_BU24RGB ( 0x0f << 25 )
#define MGADWG_REPLACE 0x000C0000 /* From Linux kernel sources */
#define MGADWG_PATTERN ( 0x01 << 29 )
#define MGADWG_TRANSC ( 0x01 << 30 )
#define MGADWG_NOCLIP ( 0x01 << 31 )
#define MGAREG_MISC_WRITE 0x3c2
#define MGAREG_MISC_READ 0x3cc
#define MGAREG_MISC_IOADSEL (0x1 << 0)
#define MGAREG_MISC_RAMMAPEN (0x1 << 1)
#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2)
#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2)
#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2)
#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2)
#define MGAREG_MISC_VIDEO_DIS (0x1 << 4)
#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5)
/* MMIO VGA registers */
#define MGAREG_CRTC_INDEX 0x1fd4
#define MGAREG_CRTC_DATA 0x1fd5
#define MGAREG_CRTCEXT_INDEX 0x1fde
#define MGAREG_CRTCEXT_DATA 0x1fdf
/* MGA bits for registers PCI_OPTION_REG */
#define MGA1064_OPT_SYS_CLK_PCI ( 0x00 << 0 )
#define MGA1064_OPT_SYS_CLK_PLL ( 0x01 << 0 )
#define MGA1064_OPT_SYS_CLK_EXT ( 0x02 << 0 )
#define MGA1064_OPT_SYS_CLK_MSK ( 0x03 << 0 )
#define MGA1064_OPT_SYS_CLK_DIS ( 0x01 << 2 )
#define MGA1064_OPT_G_CLK_DIV_1 ( 0x01 << 3 )
#define MGA1064_OPT_M_CLK_DIV_1 ( 0x01 << 4 )
#define MGA1064_OPT_SYS_PLL_PDN ( 0x01 << 5 )
#define MGA1064_OPT_VGA_ION ( 0x01 << 8 )
/* MGA registers in PCI config space */
#define PCI_MGA_INDEX 0x44
#define PCI_MGA_DATA 0x48
#define PCI_MGA_OPTION2 0x50
#define PCI_MGA_OPTION3 0x54
#define RAMDAC_OFFSET 0x3c00
/* TVP3026 direct registers */
#define TVP3026_INDEX 0x00
#define TVP3026_WADR_PAL 0x00
#define TVP3026_COL_PAL 0x01
#define TVP3026_PIX_RD_MSK 0x02
#define TVP3026_RADR_PAL 0x03
#define TVP3026_CUR_COL_ADDR 0x04
#define TVP3026_CUR_COL_DATA 0x05
#define TVP3026_DATA 0x0a
#define TVP3026_CUR_RAM 0x0b
#define TVP3026_CUR_XLOW 0x0c
#define TVP3026_CUR_XHI 0x0d
#define TVP3026_CUR_YLOW 0x0e
#define TVP3026_CUR_YHI 0x0f
/* TVP3026 indirect registers */
#define TVP3026_SILICON_REV 0x01
#define TVP3026_CURSOR_CTL 0x06
#define TVP3026_LATCH_CTL 0x0f
#define TVP3026_TRUE_COLOR_CTL 0x18
#define TVP3026_MUX_CTL 0x19
#define TVP3026_CLK_SEL 0x1a
#define TVP3026_PAL_PAGE 0x1c
#define TVP3026_GEN_CTL 0x1d
#define TVP3026_MISC_CTL 0x1e
#define TVP3026_GEN_IO_CTL 0x2a
#define TVP3026_GEN_IO_DATA 0x2b
#define TVP3026_PLL_ADDR 0x2c
#define TVP3026_PIX_CLK_DATA 0x2d
#define TVP3026_MEM_CLK_DATA 0x2e
#define TVP3026_LOAD_CLK_DATA 0x2f
#define TVP3026_KEY_RED_LOW 0x32
#define TVP3026_KEY_RED_HI 0x33
#define TVP3026_KEY_GREEN_LOW 0x34
#define TVP3026_KEY_GREEN_HI 0x35
#define TVP3026_KEY_BLUE_LOW 0x36
#define TVP3026_KEY_BLUE_HI 0x37
#define TVP3026_KEY_CTL 0x38
#define TVP3026_MCLK_CTL 0x39
#define TVP3026_SENSE_TEST 0x3a
#define TVP3026_TEST_DATA 0x3b
#define TVP3026_CRC_LSB 0x3c
#define TVP3026_CRC_MSB 0x3d
#define TVP3026_CRC_CTL 0x3e
#define TVP3026_ID 0x3f
#define TVP3026_RESET 0xff
/* MGA1064 DAC Register file */
/* MGA1064 direct registers */
#define MGA1064_INDEX 0x00
#define MGA1064_WADR_PAL 0x00
#define MGA1064_COL_PAL 0x01
#define MGA1064_PIX_RD_MSK 0x02
#define MGA1064_RADR_PAL 0x03
#define MGA1064_DATA 0x0a
#define MGA1064_CUR_XLOW 0x0c
#define MGA1064_CUR_XHI 0x0d
#define MGA1064_CUR_YLOW 0x0e
#define MGA1064_CUR_YHI 0x0f
/* MGA1064 indirect registers */
#define MGA1064_CURSOR_BASE_ADR_LOW 0x04
#define MGA1064_CURSOR_BASE_ADR_HI 0x05
#define MGA1064_CURSOR_CTL 0x06
#define MGA1064_CURSOR_COL0_RED 0x08
#define MGA1064_CURSOR_COL0_GREEN 0x09
#define MGA1064_CURSOR_COL0_BLUE 0x0a
#define MGA1064_CURSOR_COL1_RED 0x0c
#define MGA1064_CURSOR_COL1_GREEN 0x0d
#define MGA1064_CURSOR_COL1_BLUE 0x0e
#define MGA1064_CURSOR_COL2_RED 0x010
#define MGA1064_CURSOR_COL2_GREEN 0x011
#define MGA1064_CURSOR_COL2_BLUE 0x012
#define MGA1064_VREF_CTL 0x018
#define MGA1064_MUL_CTL 0x19
#define MGA1064_MUL_CTL_8bits 0x0
#define MGA1064_MUL_CTL_15bits 0x01
#define MGA1064_MUL_CTL_16bits 0x02
#define MGA1064_MUL_CTL_24bits 0x03
#define MGA1064_MUL_CTL_32bits 0x04
#define MGA1064_MUL_CTL_2G8V16bits 0x05
#define MGA1064_MUL_CTL_G16V16bits 0x06
#define MGA1064_MUL_CTL_32_24bits 0x07
#define MGAGDAC_XVREFCTRL 0x18
#define MGA1064_PIX_CLK_CTL 0x1a
#define MGA1064_PIX_CLK_CTL_CLK_DIS ( 0x01 << 2 )
#define MGA1064_PIX_CLK_CTL_CLK_POW_DOWN ( 0x01 << 3 )
#define MGA1064_PIX_CLK_CTL_SEL_PCI ( 0x00 << 0 )
#define MGA1064_PIX_CLK_CTL_SEL_PLL ( 0x01 << 0 )
#define MGA1064_PIX_CLK_CTL_SEL_EXT ( 0x02 << 0 )
#define MGA1064_PIX_CLK_CTL_SEL_MSK ( 0x03 << 0 )
#define MGA1064_GEN_CTL 0x1d
#define MGA1064_MISC_CTL 0x1e
#define MGA1064_MISC_CTL_DAC_POW_DN ( 0x01 << 0 )
#define MGA1064_MISC_CTL_VGA ( 0x01 << 1 )
#define MGA1064_MISC_CTL_DIS_CON ( 0x03 << 1 )
#define MGA1064_MISC_CTL_MAFC ( 0x02 << 1 )
#define MGA1064_MISC_CTL_VGA8 ( 0x01 << 3 )
#define MGA1064_MISC_CTL_DAC_RAM_CS ( 0x01 << 4 )
#define MGA1064_GEN_IO_CTL 0x2a
#define MGA1064_GEN_IO_DATA 0x2b
#define MGA1064_SYS_PLL_M 0x2c
#define MGA1064_SYS_PLL_N 0x2d
#define MGA1064_SYS_PLL_P 0x2e
#define MGA1064_SYS_PLL_STAT 0x2f
#define MGA1064_ZOOM_CTL 0x38
#define MGA1064_SENSE_TST 0x3a
#define MGA1064_CRC_LSB 0x3c
#define MGA1064_CRC_MSB 0x3d
#define MGA1064_CRC_CTL 0x3e
#define MGA1064_COL_KEY_MSK_LSB 0x40
#define MGA1064_COL_KEY_MSK_MSB 0x41
#define MGA1064_COL_KEY_LSB 0x42
#define MGA1064_COL_KEY_MSB 0x43
#define MGA1064_PIX_PLLA_M 0x44
#define MGA1064_PIX_PLLA_N 0x45
#define MGA1064_PIX_PLLA_P 0x46
#define MGA1064_PIX_PLLB_M 0x48
#define MGA1064_PIX_PLLB_N 0x49
#define MGA1064_PIX_PLLB_P 0x4a
#define MGA1064_PIX_PLLC_M 0x4c
#define MGA1064_PIX_PLLC_N 0x4d
#define MGA1064_PIX_PLLC_P 0x4e
#define MGA1064_PIX_PLL_STAT 0x4f
#endif
/* vi: set ts=4 sw=4 expandtab: */
/***************************************************************************\
|* *|
|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
|* *|
|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
|* international laws. Users and possessors of this source code are *|
|* hereby granted a nonexclusive, royalty-free copyright license to *|
|* use this code in individual and commercial software. *|
|* *|
|* Any use of this source code must include, in the user documenta- *|
|* tion and internal comments to the code, notices to the end user *|
|* as follows: *|
|* *|
|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
|* *|
|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
|* *|
|* U.S. Government End Users. This source code is a "commercial *|
|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
|* consisting of "commercial computer software" and "commercial *|
|* computer software documentation," as such terms are used in *|
|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
|* all U.S. Government End Users acquire the source code with only *|
|* those rights set forth herein. *|
|* *|
\***************************************************************************/
#ifndef __RIVA_HW_H__
#define __RIVA_HW_H__
#define RIVA_SW_VERSION 0x00010003
/*
* Typedefs to force certain sized values.
*/
typedef Uint8 U008;
typedef Uint16 U016;
typedef Uint32 U032;
/*
* HW access macros.
*/
#define NV_WR08(p,i,d) (((U008 *)(p))[i]=(d))
#define NV_RD08(p,i) (((U008 *)(p))[i])
#define NV_WR16(p,i,d) (((U016 *)(p))[(i)/2]=(d))
#define NV_RD16(p,i) (((U016 *)(p))[(i)/2])
#define NV_WR32(p,i,d) (((U032 *)(p))[(i)/4]=(d))
#define NV_RD32(p,i) (((U032 *)(p))[(i)/4])
#define VGA_WR08(p,i,d) NV_WR08(p,i,d)
#define VGA_RD08(p,i) NV_RD08(p,i)
/*
* Define supported architectures.
*/
#define NV_ARCH_03 0x03
#define NV_ARCH_04 0x04
#define NV_ARCH_10 0x10
/***************************************************************************\
* *
* FIFO registers. *
* *
\***************************************************************************/
/*
* Raster OPeration. Windows style ROP3.
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop;
U032 reserved01[0x0BB];
U032 Rop3;
} RivaRop;
/*
* 8X8 Monochrome pattern.
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop;
U032 reserved01[0x0BD];
U032 Shape;
U032 reserved03[0x001];
U032 Color0;
U032 Color1;
U032 Monochrome[2];
} RivaPattern;
/*
* Scissor clip rectangle.
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop;
U032 reserved01[0x0BB];
U032 TopLeft;
U032 WidthHeight;
} RivaClip;
/*
* 2D filled rectangle.
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop[1];
U032 reserved01[0x0BC];
U032 Color;
U032 reserved03[0x03E];
U032 TopLeft;
U032 WidthHeight;
} RivaRectangle;
/*
* 2D screen-screen BLT.
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop;
U032 reserved01[0x0BB];
U032 TopLeftSrc;
U032 TopLeftDst;
U032 WidthHeight;
} RivaScreenBlt;
/*
* 2D pixel BLT.
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop[1];
U032 reserved01[0x0BC];
U032 TopLeft;
U032 WidthHeight;
U032 WidthHeightIn;
U032 reserved02[0x03C];
U032 Pixels;
} RivaPixmap;
/*
* Filled rectangle combined with monochrome expand. Useful for glyphs.
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop;
U032 reserved01[0x0BB];
U032 reserved03[(0x040) - 1];
U032 Color1A;
struct
{
U032 TopLeft;
U032 WidthHeight;
} UnclippedRectangle[64];
U032 reserved04[(0x080) - 3];
struct
{
U032 TopLeft;
U032 BottomRight;
} ClipB;
U032 Color1B;
struct
{
U032 TopLeft;
U032 BottomRight;
} ClippedRectangle[64];
U032 reserved05[(0x080) - 5];
struct
{
U032 TopLeft;
U032 BottomRight;
} ClipC;
U032 Color1C;
U032 WidthHeightC;
U032 PointC;
U032 MonochromeData1C;
U032 reserved06[(0x080) + 121];
struct
{
U032 TopLeft;
U032 BottomRight;
} ClipD;
U032 Color1D;
U032 WidthHeightInD;
U032 WidthHeightOutD;
U032 PointD;
U032 MonochromeData1D;
U032 reserved07[(0x080) + 120];
struct
{
U032 TopLeft;
U032 BottomRight;
} ClipE;
U032 Color0E;
U032 Color1E;
U032 WidthHeightInE;
U032 WidthHeightOutE;
U032 PointE;
U032 MonochromeData01E;
} RivaBitmap;
/*
* 3D textured, Z buffered triangle.
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop;
U032 reserved01[0x0BC];
U032 TextureOffset;
U032 TextureFormat;
U032 TextureFilter;
U032 FogColor;
/* This is a problem on LynxOS */
#ifdef Control
#undef Control
#endif
U032 Control;
U032 AlphaTest;
U032 reserved02[0x339];
U032 FogAndIndex;
U032 Color;
float ScreenX;
float ScreenY;
float ScreenZ;
float EyeM;
float TextureS;
float TextureT;
} RivaTexturedTriangle03;
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop;
U032 reserved01[0x0BB];
U032 ColorKey;
U032 TextureOffset;
U032 TextureFormat;
U032 TextureFilter;
U032 Blend;
/* This is a problem on LynxOS */
#ifdef Control
#undef Control
#endif
U032 Control;
U032 FogColor;
U032 reserved02[0x39];
struct
{
float ScreenX;
float ScreenY;
float ScreenZ;
float EyeM;
U032 Color;
U032 Specular;
float TextureS;
float TextureT;
} Vertex[16];
U032 DrawTriangle3D;
} RivaTexturedTriangle05;
/*
* 2D line.
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop[1];
U032 reserved01[0x0BC];
U032 Color; /* source color 0304-0307 */
U032 Reserved02[0x03e];
struct
{ /* start aliased methods in array 0400- */
U032 point0; /* y_x S16_S16 in pixels 0- 3 */
U032 point1; /* y_x S16_S16 in pixels 4- 7 */
} Lin[16]; /* end of aliased methods in array -047f */
struct
{ /* start aliased methods in array 0480- */
U032 point0X; /* in pixels, 0 at left 0- 3 */
U032 point0Y; /* in pixels, 0 at top 4- 7 */
U032 point1X; /* in pixels, 0 at left 8- b */
U032 point1Y; /* in pixels, 0 at top c- f */
} Lin32[8]; /* end of aliased methods in array -04ff */
U032 PolyLin[32]; /* y_x S16_S16 in pixels 0500-057f */
struct
{ /* start aliased methods in array 0580- */
U032 x; /* in pixels, 0 at left 0- 3 */
U032 y; /* in pixels, 0 at top 4- 7 */
} PolyLin32[16]; /* end of aliased methods in array -05ff */
struct
{ /* start aliased methods in array 0600- */
U032 color; /* source color 0- 3 */
U032 point; /* y_x S16_S16 in pixels 4- 7 */
} ColorPolyLin[16]; /* end of aliased methods in array -067f */
} RivaLine;
/*
* 2D/3D surfaces
*/
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop;
U032 reserved01[0x0BE];
U032 Offset;
} RivaSurface;
typedef volatile struct
{
U032 reserved00[4];
U016 FifoFree;
U016 Nop;
U032 reserved01[0x0BD];
U032 Pitch;
U032 RenderBufferOffset;
U032 ZBufferOffset;
} RivaSurface3D;
/***************************************************************************\
* *
* Virtualized RIVA H/W interface. *
* *
\***************************************************************************/
struct _riva_hw_inst;
struct _riva_hw_state;
/*
* Virtialized chip interface. Makes RIVA 128 and TNT look alike.
*/
typedef struct _riva_hw_inst
{
/*
* Chip specific settings.
*/
U032 Architecture;
U032 Version;
U032 CrystalFreqKHz;
U032 RamAmountKBytes;
U032 MaxVClockFreqKHz;
U032 RamBandwidthKBytesPerSec;
U032 EnableIRQ;
U032 IO;
U032 VBlankBit;
U032 FifoFreeCount;
U032 FifoEmptyCount;
/*
* Non-FIFO registers.
*/
volatile U032 *PCRTC;
volatile U032 *PRAMDAC;
volatile U032 *PFB;
volatile U032 *PFIFO;
volatile U032 *PGRAPH;
volatile U032 *PEXTDEV;
volatile U032 *PTIMER;
volatile U032 *PMC;
volatile U032 *PRAMIN;
volatile U032 *FIFO;
volatile U032 *CURSOR;
volatile U032 *CURSORPOS;
volatile U032 *VBLANKENABLE;
volatile U032 *VBLANK;
volatile U008 *PCIO;
volatile U008 *PVIO;
volatile U008 *PDIO;
/*
* Common chip functions.
*/
int (*Busy) (struct _riva_hw_inst *);
void (*CalcStateExt) (struct _riva_hw_inst *, struct _riva_hw_state *,
int, int, int, int, int, int, int, int, int, int,
int, int, int);
void (*LoadStateExt) (struct _riva_hw_inst *, struct _riva_hw_state *);
void (*UnloadStateExt) (struct _riva_hw_inst *, struct _riva_hw_state *);
void (*SetStartAddress) (struct _riva_hw_inst *, U032);
void (*SetSurfaces2D) (struct _riva_hw_inst *, U032, U032);
void (*SetSurfaces3D) (struct _riva_hw_inst *, U032, U032);
int (*ShowHideCursor) (struct _riva_hw_inst *, int);
void (*LockUnlock) (struct _riva_hw_inst *, int);
/*
* Current extended mode settings.
*/
struct _riva_hw_state *CurrentState;
/*
* FIFO registers.
*/
RivaRop *Rop;
RivaPattern *Patt;
RivaClip *Clip;
RivaPixmap *Pixmap;
RivaScreenBlt *Blt;
RivaBitmap *Bitmap;
RivaLine *Line;
RivaTexturedTriangle03 *Tri03;
RivaTexturedTriangle05 *Tri05;
} RIVA_HW_INST;
/*
* Extended mode state information.
*/
typedef struct _riva_hw_state
{
U032 bpp;
U032 width;
U032 height;
U032 repaint0;
U032 repaint1;
U032 screen;
U032 pixel;
U032 horiz;
U032 arbitration0;
U032 arbitration1;
U032 vpll;
U032 pllsel;
U032 general;
U032 config;
U032 cursor0;
U032 cursor1;
U032 cursor2;
U032 offset0;
U032 offset1;
U032 offset2;
U032 offset3;
U032 pitch0;
U032 pitch1;
U032 pitch2;
U032 pitch3;
} RIVA_HW_STATE;
/*
* FIFO Free Count. Should attempt to yield processor if RIVA is busy.
*/
#define RIVA_FIFO_FREE(hwptr,cnt) \
{ \
while (FifoFreeCount < (cnt)) \
FifoFreeCount = hwptr->FifoFree >> 2; \
FifoFreeCount -= (cnt); \
}
#endif /* __RIVA_HW_H__ */
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#ifndef _RIVA_REGS_H
#define _RIVA_REGS_H
/* This information comes from the XFree86 NVidia hardware driver */
/* mapped_io register offsets */
#define PGRAPH_OFFSET 0x00400000
#define FIFO_OFFSET 0x00800000
#define ROP_OFFSET FIFO_OFFSET+0x00000000
#define CLIP_OFFSET FIFO_OFFSET+0x00002000
#define PATT_OFFSET FIFO_OFFSET+0x00004000
#define PIXMAP_OFFSET FIFO_OFFSET+0x00006000
#define BLT_OFFSET FIFO_OFFSET+0x00008000
#define BITMAP_OFFSET FIFO_OFFSET+0x0000A000
#define LINE_OFFSET FIFO_OFFSET+0x0000C000
#define TRI03_OFFSET FIFO_OFFSET+0x0000E000
#define PCIO_OFFSET 0x00601000
#endif /* _RIVA_REGS_H */
/* vi: set ts=4 sw=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment