aboutsummaryrefslogtreecommitdiffstats
path: root/distrib/sdl-1.2.15/src/video/fbcon
diff options
context:
space:
mode:
Diffstat (limited to 'distrib/sdl-1.2.15/src/video/fbcon')
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/3dfx_mmio.h56
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/3dfx_regs.h83
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.c215
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.h29
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.c442
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.h55
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents.c1254
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents_c.h38
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbkeys.h139
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.c280
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.h29
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse.c33
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse_c.h26
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.c222
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.h36
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.c1982
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.h200
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/matrox_mmio.h51
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/matrox_regs.h376
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/riva_mmio.h449
-rw-r--r--distrib/sdl-1.2.15/src/video/fbcon/riva_regs.h43
21 files changed, 6038 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/3dfx_mmio.h b/distrib/sdl-1.2.15/src/video/fbcon/3dfx_mmio.h
new file mode 100644
index 0000000..b641454
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/3dfx_mmio.h
@@ -0,0 +1,56 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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 ); \
+}
+
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/3dfx_regs.h b/distrib/sdl-1.2.15/src/video/fbcon/3dfx_regs.h
new file mode 100644
index 0000000..e86f727
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/3dfx_regs.h
@@ -0,0 +1,83 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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 */
+
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.c
new file mode 100644
index 0000000..eb083b8
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.c
@@ -0,0 +1,215 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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;
+ Uint32 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 *)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, 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 src_base;
+ Uint32 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 *)src->pixels - mapped_mem);
+ bpp = src->format->BitsPerPixel;
+ src_format = src->pitch | ((bpp+((bpp==8) ? 0 : 8)) << 13);
+ dst_base = ((char *)dst->pixels - mapped_mem);
+ bpp = dst->format->BitsPerPixel;
+
+ 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;
+}
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.h
new file mode 100644
index 0000000..4a59de9
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.h
@@ -0,0 +1,29 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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);
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.c
new file mode 100644
index 0000000..63dff87
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.c
@@ -0,0 +1,442 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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;
+}
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.h
new file mode 100644
index 0000000..e7fde4f
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.h
@@ -0,0 +1,55 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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 */
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents.c
new file mode 100644
index 0000000..5e369a4
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents.c
@@ -0,0 +1,1254 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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 ) {
+ int matches = 0;
+ name[0] = '\0';
+ matches = fscanf(status, "Name: %s", name);
+ if ( (matches == 1) && (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];
+ if (read(fd, temp, sizeof(temp)) <= 0) {
+ break;
+ }
+ }
+
+ 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];
+ if (read(fd, temp, sizeof(temp)) <= 0) {
+ break;
+ }
+ }
+
+ /* 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:
+ break; /* carry on to read from device and discard it. */
+ 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;
+ }
+
+ if (mouse_drv == MOUSE_NONE) {
+ return; /* we're done; just draining the input queue. */
+ }
+
+ 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: /* shouldn't actually hit this. */
+ break; /* just throw everything away. */
+ 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);
+}
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents_c.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents_c.h
new file mode 100644
index 0000000..fe8b09c
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents_c.h
@@ -0,0 +1,38 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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);
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbkeys.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbkeys.h
new file mode 100644
index 0000000..2b01b6b
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbkeys.h
@@ -0,0 +1,139 @@
+
+/* 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
+
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.c
new file mode 100644
index 0000000..04b90b0
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.c
@@ -0,0 +1,280 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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
+}
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.h
new file mode 100644
index 0000000..f7d41b0
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.h
@@ -0,0 +1,29 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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);
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse.c
new file mode 100644
index 0000000..d65f27e
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse.c
@@ -0,0 +1,33 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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;
+};
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse_c.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse_c.h
new file mode 100644
index 0000000..fbb031d
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse_c.h
@@ -0,0 +1,26 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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 */
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.c
new file mode 100644
index 0000000..eb4b71f
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.c
@@ -0,0 +1,222 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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
+}
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.h
new file mode 100644
index 0000000..c78682e
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.h
@@ -0,0 +1,36 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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);
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.c
new file mode 100644
index 0000000..5e58809
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.c
@@ -0,0 +1,1982 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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
+};
+enum {
+ FBCON_ROTATE_NONE = 0,
+ FBCON_ROTATE_CCW = 90,
+ FBCON_ROTATE_UD = 180,
+ FBCON_ROTATE_CW = 270
+};
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+/* 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);
+
+/* Shadow buffer functions */
+static FB_bitBlit FB_blit16;
+static FB_bitBlit FB_blit16blocked;
+
+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.
+ return 4096; /* this is what it USED to be in Linux... */
+#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;
+ const char *rotation;
+ 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;
+ }
+ }
+
+ rotate = FBCON_ROTATE_NONE;
+ rotation = SDL_getenv("SDL_VIDEO_FBCON_ROTATION");
+ if (rotation != NULL) {
+ if (SDL_strlen(rotation) == 0) {
+ shadow_fb = 0;
+ rotate = FBCON_ROTATE_NONE;
+#ifdef FBCON_DEBUG
+ printf("Not rotating, no shadow\n");
+#endif
+ } else if (!SDL_strcmp(rotation, "NONE")) {
+ shadow_fb = 1;
+ rotate = FBCON_ROTATE_NONE;
+#ifdef FBCON_DEBUG
+ printf("Not rotating, but still using shadow\n");
+#endif
+ } else if (!SDL_strcmp(rotation, "CW")) {
+ shadow_fb = 1;
+ rotate = FBCON_ROTATE_CW;
+#ifdef FBCON_DEBUG
+ printf("Rotating screen clockwise\n");
+#endif
+ } else if (!SDL_strcmp(rotation, "CCW")) {
+ shadow_fb = 1;
+ rotate = FBCON_ROTATE_CCW;
+#ifdef FBCON_DEBUG
+ printf("Rotating screen counter clockwise\n");
+#endif
+ } else if (!SDL_strcmp(rotation, "UD")) {
+ shadow_fb = 1;
+ rotate = FBCON_ROTATE_UD;
+#ifdef FBCON_DEBUG
+ printf("Rotating screen upside down\n");
+#endif
+ } else {
+ SDL_SetError("\"%s\" is not a valid value for "
+ "SDL_VIDEO_FBCON_ROTATION", rotation);
+ return(-1);
+ }
+ }
+
+ if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) {
+ current_w = vinfo.yres;
+ current_h = vinfo.xres;
+ } else {
+ current_w = vinfo.xres;
+ current_h = vinfo.yres;
+ }
+
+ /* Query for the list of available video modes */
+ 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;
+
+ if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) {
+ w = vinfo.yres;
+ h = vinfo.xres;
+ } else {
+ w = vinfo.xres;
+ h = vinfo.yres;
+ }
+ /* See if we are querying for the current mode */
+ 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;
+
+ if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) {
+ w = checkres[j].h;
+ h = checkres[j].w;
+ } else {
+ w = checkres[j].w;
+ h = checkres[j].h;
+ }
+ /* See if we are querying for the current mode */
+ 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);
+ }
+ }
+ }
+ }
+
+ this->info.current_w = current_w;
+ this->info.current_h = current_h;
+ this->info.wm_available = 0;
+ this->info.hw_available = !shadow_fb;
+ this->info.video_mem = shadow_fb ? 0 : finfo.smem_len/1024;
+ /* Fill in our hardware acceleration capabilities */
+ 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;
+ }
+ }
+
+ if (shadow_fb) {
+ shadow_mem = (char *)SDL_malloc(mapped_memlen);
+ if (shadow_mem == NULL) {
+ SDL_SetError("No memory for shadow");
+ return (-1);
+ }
+ }
+
+ /* 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
+ /* Do not use double buffering with shadow buffer */
+ if (shadow_fb) {
+ flags &= ~SDL_DOUBLEBUF;
+ }
+
+ 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 ( !shadow_fb &&
+ 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);
+
+ if (shadow_fb) {
+ if (vinfo.bits_per_pixel == 16) {
+ blitFunc = (rotate == FBCON_ROTATE_NONE ||
+ rotate == FBCON_ROTATE_UD) ?
+ FB_blit16 : FB_blit16blocked;
+ } else {
+#ifdef FBCON_DEBUG
+ fprintf(stderr, "Init vinfo:\n");
+ print_vinfo(&vinfo);
+#endif
+ SDL_SetError("Using software buffer, but no blitter "
+ "function is available for %d bpp.",
+ vinfo.bits_per_pixel);
+ return(NULL);
+ }
+ }
+
+ /* Set up the new mode framebuffer */
+ current->flags &= SDL_FULLSCREEN;
+ if (shadow_fb) {
+ current->flags |= SDL_SWSURFACE;
+ } else {
+ current->flags |= SDL_HWSURFACE;
+ }
+ current->w = vinfo.xres;
+ current->h = vinfo.yres;
+ if (shadow_fb) {
+ current->pitch = current->w * ((vinfo.bits_per_pixel + 7) / 8);
+ current->pixels = shadow_mem;
+ physlinebytes = finfo.line_length;
+ } else {
+ 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 = (shadow_fb) ?
+ 0 : (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_blit16(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta,
+ Uint8 *byte_dst_pos, int dst_linebytes, int width, int height)
+{
+ int w;
+ Uint16 *src_pos = (Uint16 *)byte_src_pos;
+ Uint16 *dst_pos = (Uint16 *)byte_dst_pos;
+
+ while (height) {
+ Uint16 *src = src_pos;
+ Uint16 *dst = dst_pos;
+ for (w = width; w != 0; w--) {
+ *dst = *src;
+ src += src_right_delta;
+ dst++;
+ }
+ dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes);
+ src_pos += src_down_delta;
+ height--;
+ }
+}
+
+#define BLOCKSIZE_W 32
+#define BLOCKSIZE_H 32
+
+static void FB_blit16blocked(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta,
+ Uint8 *byte_dst_pos, int dst_linebytes, int width, int height)
+{
+ int w;
+ Uint16 *src_pos = (Uint16 *)byte_src_pos;
+ Uint16 *dst_pos = (Uint16 *)byte_dst_pos;
+
+ while (height > 0) {
+ Uint16 *src = src_pos;
+ Uint16 *dst = dst_pos;
+ for (w = width; w > 0; w -= BLOCKSIZE_W) {
+ FB_blit16((Uint8 *)src,
+ src_right_delta,
+ src_down_delta,
+ (Uint8 *)dst,
+ dst_linebytes,
+ min(w, BLOCKSIZE_W),
+ min(height, BLOCKSIZE_H));
+ src += src_right_delta * BLOCKSIZE_W;
+ dst += BLOCKSIZE_W;
+ }
+ dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes * BLOCKSIZE_H);
+ src_pos += src_down_delta * BLOCKSIZE_H;
+ height -= BLOCKSIZE_H;
+ }
+}
+
+static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
+{
+ int width = cache_vinfo.xres;
+ int height = cache_vinfo.yres;
+ int bytes_per_pixel = (cache_vinfo.bits_per_pixel + 7) / 8;
+ int i;
+
+ if (!shadow_fb) {
+ /* The application is already updating the visible video memory */
+ return;
+ }
+
+ if (cache_vinfo.bits_per_pixel != 16) {
+ SDL_SetError("Shadow copy only implemented for 16 bpp");
+ return;
+ }
+
+ for (i = 0; i < numrects; i++) {
+ int x1, y1, x2, y2;
+ int scr_x1, scr_y1, scr_x2, scr_y2;
+ int sha_x1, sha_y1;
+ int shadow_right_delta; /* Address change when moving right in dest */
+ int shadow_down_delta; /* Address change when moving down in dest */
+ char *src_start;
+ char *dst_start;
+
+ x1 = rects[i].x;
+ y1 = rects[i].y;
+ x2 = x1 + rects[i].w;
+ y2 = y1 + rects[i].h;
+
+ if (x1 < 0) {
+ x1 = 0;
+ } else if (x1 > width) {
+ x1 = width;
+ }
+ if (x2 < 0) {
+ x2 = 0;
+ } else if (x2 > width) {
+ x2 = width;
+ }
+ if (y1 < 0) {
+ y1 = 0;
+ } else if (y1 > height) {
+ y1 = height;
+ }
+ if (y2 < 0) {
+ y2 = 0;
+ } else if (y2 > height) {
+ y2 = height;
+ }
+ if (x2 <= x1 || y2 <= y1) {
+ continue;
+ }
+
+ switch (rotate) {
+ case FBCON_ROTATE_NONE:
+ sha_x1 = scr_x1 = x1;
+ sha_y1 = scr_y1 = y1;
+ scr_x2 = x2;
+ scr_y2 = y2;
+ shadow_right_delta = 1;
+ shadow_down_delta = width;
+ break;
+ case FBCON_ROTATE_CCW:
+ scr_x1 = y1;
+ scr_y1 = width - x2;
+ scr_x2 = y2;
+ scr_y2 = width - x1;
+ sha_x1 = x2 - 1;
+ sha_y1 = y1;
+ shadow_right_delta = width;
+ shadow_down_delta = -1;
+ break;
+ case FBCON_ROTATE_UD:
+ scr_x1 = width - x2;
+ scr_y1 = height - y2;
+ scr_x2 = width - x1;
+ scr_y2 = height - y1;
+ sha_x1 = x2 - 1;
+ sha_y1 = y2 - 1;
+ shadow_right_delta = -1;
+ shadow_down_delta = -width;
+ break;
+ case FBCON_ROTATE_CW:
+ scr_x1 = height - y2;
+ scr_y1 = x1;
+ scr_x2 = height - y1;
+ scr_y2 = x2;
+ sha_x1 = x1;
+ sha_y1 = y2 - 1;
+ shadow_right_delta = -width;
+ shadow_down_delta = 1;
+ break;
+ default:
+ SDL_SetError("Unknown rotation");
+ return;
+ }
+
+ src_start = shadow_mem +
+ (sha_y1 * width + sha_x1) * bytes_per_pixel;
+ dst_start = mapped_mem + mapped_offset + scr_y1 * physlinebytes +
+ scr_x1 * bytes_per_pixel;
+
+ blitFunc((Uint8 *) src_start,
+ shadow_right_delta,
+ shadow_down_delta,
+ (Uint8 *) dst_start,
+ physlinebytes,
+ scr_x2 - scr_x1,
+ scr_y2 - scr_y1);
+ }
+}
+
+#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 */
+
+ const char *dontClearPixels = SDL_getenv("SDL_FBCON_DONT_CLEAR");
+
+ /* If the framebuffer is not to be cleared, make sure that we won't
+ * display the previous frame when disabling double buffering. */
+ if ( dontClearPixels && flip_page == 0 ) {
+ SDL_memcpy(flip_address[0], flip_address[1], this->screen->pitch * this->screen->h);
+ }
+
+ if ( !dontClearPixels && 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);
+}
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.h
new file mode 100644
index 0000000..1443d2b
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.h
@@ -0,0 +1,200 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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
+
+typedef void FB_bitBlit(
+ Uint8 *src_pos,
+ int src_right_delta, /* pixels, not bytes */
+ int src_down_delta, /* pixels, not bytes */
+ Uint8 *dst_pos,
+ int dst_linebytes,
+ int width,
+ int height);
+
+/* 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;
+ char *shadow_mem;
+ int mapped_memlen;
+ int mapped_offset;
+ char *mapped_io;
+ long mapped_iolen;
+ int flip_page;
+ char *flip_address[2];
+ int rotate;
+ int shadow_fb; /* Tells whether a shadow is being used. */
+ FB_bitBlit *blitFunc;
+ int physlinebytes; /* Length of a line in bytes in physical fb */
+
+#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 shadow_mem (this->hidden->shadow_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 rotate (this->hidden->rotate)
+#define shadow_fb (this->hidden->shadow_fb)
+#define blitFunc (this->hidden->blitFunc)
+#define physlinebytes (this->hidden->physlinebytes)
+#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 */
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/matrox_mmio.h b/distrib/sdl-1.2.15/src/video/fbcon/matrox_mmio.h
new file mode 100644
index 0000000..a1cf203
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/matrox_mmio.h
@@ -0,0 +1,51 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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 ) \
+ ; \
+}
+
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/matrox_regs.h b/distrib/sdl-1.2.15/src/video/fbcon/matrox_regs.h
new file mode 100644
index 0000000..d570b0c
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/matrox_regs.h
@@ -0,0 +1,376 @@
+
+/*
+ * 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
+
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/riva_mmio.h b/distrib/sdl-1.2.15/src/video/fbcon/riva_mmio.h
new file mode 100644
index 0000000..e926167
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/riva_mmio.h
@@ -0,0 +1,449 @@
+/***************************************************************************\
+|* *|
+|* 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__ */
+
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/riva_regs.h b/distrib/sdl-1.2.15/src/video/fbcon/riva_regs.h
new file mode 100644
index 0000000..5324562
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/fbcon/riva_regs.h
@@ -0,0 +1,43 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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 */
+