aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xfree86/os-support/linux/int10
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xfree86/os-support/linux/int10')
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/int10/linux.c1085
1 files changed, 541 insertions, 544 deletions
diff --git a/xorg-server/hw/xfree86/os-support/linux/int10/linux.c b/xorg-server/hw/xfree86/os-support/linux/int10/linux.c
index e3c8a984d..564447ff6 100644
--- a/xorg-server/hw/xfree86/os-support/linux/int10/linux.c
+++ b/xorg-server/hw/xfree86/os-support/linux/int10/linux.c
@@ -1,544 +1,541 @@
-/*
- * linux specific part of the int10 module
- * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2008 Egbert Eich
- */
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86_OSproc.h"
-#include "xf86Pci.h"
-#include "compiler.h"
-#define _INT10_PRIVATE
-#include "xf86int10.h"
-#ifdef __sparc__
-#define DEV_MEM "/dev/fb"
-#else
-#define DEV_MEM "/dev/mem"
-#endif
-#define ALLOC_ENTRIES(x) ((V_RAM / x) - 1)
-#define SHMERRORPTR (pointer)(-1)
-
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <unistd.h>
-#include <string.h>
-
-static int counter = 0;
-static unsigned long int10Generation = 0;
-
-static CARD8 read_b(xf86Int10InfoPtr pInt, int addr);
-static CARD16 read_w(xf86Int10InfoPtr pInt, int addr);
-static CARD32 read_l(xf86Int10InfoPtr pInt, int addr);
-static void write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val);
-static void write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val);
-static void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val);
-
-int10MemRec linuxMem = {
- read_b,
- read_w,
- read_l,
- write_b,
- write_w,
- write_l
-};
-
-typedef struct {
- int lowMem;
- int highMem;
- char* base;
- char* base_high;
- int screen;
- char* alloc;
-} linuxInt10Priv;
-
-#if defined DoSubModules
-
-typedef enum {
- INT10_NOT_LOADED,
- INT10_LOADED_VM86,
- INT10_LOADED_X86EMU,
- INT10_LOAD_FAILED
-} Int10LinuxSubModuleState;
-
-static Int10LinuxSubModuleState loadedSubModule = INT10_NOT_LOADED;
-
-static Int10LinuxSubModuleState int10LinuxLoadSubModule(ScrnInfoPtr pScrn);
-
-#endif /* DoSubModules */
-
-xf86Int10InfoPtr
-xf86ExtendedInitInt10(int entityIndex, int Flags)
-{
- xf86Int10InfoPtr pInt = NULL;
- int screen;
- int fd;
- static void* vidMem = NULL;
- static void* sysMem = NULL;
- void* vMem = NULL;
- void *options = NULL;
- int low_mem;
- int high_mem = -1;
- char *base = SHMERRORPTR;
- char *base_high = SHMERRORPTR;
- int pagesize;
- memType cs;
- legacyVGARec vga;
- Bool videoBiosMapped = FALSE;
-
- if (int10Generation != serverGeneration) {
- counter = 0;
- int10Generation = serverGeneration;
- }
-
- screen = (xf86FindScreenForEntity(entityIndex))->scrnIndex;
-
- options = xf86HandleInt10Options(xf86Screens[screen],entityIndex);
-
- if (int10skip(options)) {
- free(options);
- return NULL;
- }
-
-#if defined DoSubModules
- if (loadedSubModule == INT10_NOT_LOADED)
- loadedSubModule = int10LinuxLoadSubModule(xf86Screens[screen]);
-
- if (loadedSubModule == INT10_LOAD_FAILED)
- return NULL;
-#endif
-
- if ((!vidMem) || (!sysMem)) {
- if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
- if (!sysMem) {
- DebugF("Mapping sys bios area\n");
- if ((sysMem = mmap((void *)(SYS_BIOS), BIOS_SIZE,
- PROT_READ | PROT_EXEC,
- MAP_SHARED | MAP_FIXED, fd, SYS_BIOS))
- == MAP_FAILED) {
- xf86DrvMsg(screen, X_ERROR, "Cannot map SYS BIOS\n");
- close(fd);
- goto error0;
- }
- }
- if (!vidMem) {
- DebugF("Mapping VRAM area\n");
- if ((vidMem = mmap((void *)(V_RAM), VRAM_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_SHARED | MAP_FIXED, fd, V_RAM))
- == MAP_FAILED) {
- xf86DrvMsg(screen, X_ERROR, "Cannot map V_RAM\n");
- close(fd);
- goto error0;
- }
- }
- close(fd);
- } else {
- xf86DrvMsg(screen, X_ERROR, "Cannot open %s\n", DEV_MEM);
- goto error0;
- }
- }
-
- pInt = (xf86Int10InfoPtr)xnfcalloc(1, sizeof(xf86Int10InfoRec));
- pInt->scrnIndex = screen;
- pInt->entityIndex = entityIndex;
- pInt->dev = xf86GetPciInfoForEntity(entityIndex);
-
- if (!xf86Int10ExecSetup(pInt))
- goto error0;
- pInt->mem = &linuxMem;
- pagesize = getpagesize();
- pInt->private = (pointer)xnfcalloc(1, sizeof(linuxInt10Priv));
- ((linuxInt10Priv*)pInt->private)->screen = screen;
- ((linuxInt10Priv*)pInt->private)->alloc =
- (pointer)xnfcalloc(1, ALLOC_ENTRIES(pagesize));
-
- if (!xf86IsEntityPrimary(entityIndex)) {
- DebugF("Mapping high memory area\n");
- if ((high_mem = shmget(counter++, HIGH_MEM_SIZE,
- IPC_CREAT | SHM_R | SHM_W)) == -1) {
- if (errno == ENOSYS)
- xf86DrvMsg(screen, X_ERROR, "shmget error\n Please reconfigure"
- " your kernel to include System V IPC support\n");
- else
- xf86DrvMsg(screen, X_ERROR,
- "shmget(highmem) error: %s\n",strerror(errno));
- goto error1;
- }
- } else {
- DebugF("Mapping Video BIOS\n");
- videoBiosMapped = TRUE;
- if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
- if ((vMem = mmap((void *)(V_BIOS), SYS_BIOS - V_BIOS,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_SHARED | MAP_FIXED, fd, V_BIOS))
- == MAP_FAILED) {
- xf86DrvMsg(screen, X_ERROR, "Cannot map V_BIOS\n");
- close(fd);
- goto error1;
- }
- close (fd);
- } else
- goto error1;
- }
- ((linuxInt10Priv*)pInt->private)->highMem = high_mem;
-
- DebugF("Mapping 640kB area\n");
- if ((low_mem = shmget(counter++, V_RAM,
- IPC_CREAT | SHM_R | SHM_W)) == -1) {
- xf86DrvMsg(screen, X_ERROR,
- "shmget(lowmem) error: %s\n",strerror(errno));
- goto error2;
- }
-
- ((linuxInt10Priv*)pInt->private)->lowMem = low_mem;
- base = shmat(low_mem, 0, 0);
- if (base == SHMERRORPTR) {
- xf86DrvMsg(screen, X_ERROR,
- "shmat(low_mem) error: %s\n",strerror(errno));
- goto error3;
- }
- ((linuxInt10Priv *)pInt->private)->base = base;
- if (high_mem > -1) {
- base_high = shmat(high_mem, 0, 0);
- if (base_high == SHMERRORPTR) {
- xf86DrvMsg(screen, X_ERROR,
- "shmat(high_mem) error: %s\n",strerror(errno));
- goto error3;
- }
- ((linuxInt10Priv*)pInt->private)->base_high = base_high;
- } else
- ((linuxInt10Priv*)pInt->private)->base_high = NULL;
-
- if (!MapCurrentInt10(pInt))
- goto error3;
-
- Int10Current = pInt;
-
- DebugF("Mapping int area\n");
- if (xf86ReadBIOS(0, 0, (unsigned char *)0, LOW_PAGE_SIZE) < 0) {
- xf86DrvMsg(screen, X_ERROR, "Cannot read int vect\n");
- goto error3;
- }
- DebugF("done\n");
- /*
- * Read in everything between V_BIOS and SYS_BIOS as some system BIOSes
- * have executable code there. Note that xf86ReadBIOS() can only bring in
- * 64K bytes at a time.
- */
- if (!videoBiosMapped) {
- memset((pointer)V_BIOS, 0, SYS_BIOS - V_BIOS);
- DebugF("Reading BIOS\n");
- for (cs = V_BIOS; cs < SYS_BIOS; cs += V_BIOS_SIZE)
- if (xf86ReadBIOS(cs, 0, (pointer)cs, V_BIOS_SIZE) < V_BIOS_SIZE)
- xf86DrvMsg(screen, X_WARNING,
- "Unable to retrieve all of segment 0x%06lX.\n",
- (long)cs);
- DebugF("done\n");
- }
-
- if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) {
- if (!xf86int10GetBiosSegment(pInt, NULL))
- goto error3;
-
- set_return_trap(pInt);
-#ifdef _PC
- pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
- if (! (pInt->Flags & SET_BIOS_SCRATCH))
- pInt->Flags &= ~RESTORE_BIOS_SCRATCH;
- xf86Int10SaveRestoreBIOSVars(pInt, TRUE);
-#endif
- } else {
- const BusType location_type = xf86int10GetBiosLocationType(pInt);
-
- switch (location_type) {
- case BUS_PCI: {
- int err;
- struct pci_device *rom_device =
- xf86GetPciInfoForEntity(pInt->entityIndex);
-
-#if HAVE_PCI_DEVICE_ENABLE
- pci_device_enable(rom_device);
-#endif
-
- err = pci_device_read_rom(rom_device, (unsigned char *)(V_BIOS));
- if (err) {
- xf86DrvMsg(screen,X_ERROR,"Cannot read V_BIOS (%s)\n",
- strerror(err));
- goto error3;
- }
-
- pInt->BIOSseg = V_BIOS >> 4;
- break;
- }
- default:
- goto error3;
- }
-
- pInt->num = 0xe6;
- reset_int_vect(pInt);
- set_return_trap(pInt);
- LockLegacyVGA(pInt, &vga);
- xf86ExecX86int10(pInt);
- UnlockLegacyVGA(pInt, &vga);
- }
-#ifdef DEBUG
- dprint(0xc0000, 0x20);
-#endif
-
- free(options);
- return pInt;
-
-error3:
- if (base_high)
- shmdt(base_high);
- shmdt(base);
- shmdt(0);
- if (base_high)
- shmdt((char*)HIGH_MEM);
- shmctl(low_mem, IPC_RMID, NULL);
- Int10Current = NULL;
-error2:
- if (high_mem > -1)
- shmctl(high_mem, IPC_RMID,NULL);
-error1:
- if (vMem)
- munmap(vMem, SYS_BIOS - V_BIOS);
- free(((linuxInt10Priv*)pInt->private)->alloc);
- free(pInt->private);
-error0:
- free(options);
- free(pInt);
- return NULL;
-}
-
-Bool
-MapCurrentInt10(xf86Int10InfoPtr pInt)
-{
- pointer addr;
- int fd = -1;
-
- if (Int10Current) {
- shmdt(0);
- if (((linuxInt10Priv*)Int10Current->private)->highMem >= 0)
- shmdt((char*)HIGH_MEM);
- else
- munmap((pointer)V_BIOS, (SYS_BIOS - V_BIOS));
- }
- addr = shmat(((linuxInt10Priv*)pInt->private)->lowMem, (char*)1, SHM_RND);
- if (addr == SHMERRORPTR) {
- xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot shmat() low memory\n");
- xf86DrvMsg(pInt->scrnIndex, X_ERROR,
- "shmat(low_mem) error: %s\n",strerror(errno));
- return FALSE;
- }
- if (mprotect((void*)0, V_RAM, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
- xf86DrvMsg(pInt->scrnIndex, X_ERROR,
- "Cannot set EXEC bit on low memory: %s\n", strerror(errno));
-
- if (((linuxInt10Priv*)pInt->private)->highMem >= 0) {
- addr = shmat(((linuxInt10Priv*)pInt->private)->highMem,
- (char*)HIGH_MEM, 0);
- if (addr == SHMERRORPTR) {
- xf86DrvMsg(pInt->scrnIndex, X_ERROR,
- "Cannot shmat() high memory\n");
- xf86DrvMsg(pInt->scrnIndex, X_ERROR,
- "shmget error: %s\n",strerror(errno));
- return FALSE;
- }
- if (mprotect((void*)HIGH_MEM, HIGH_MEM_SIZE,
- PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
- xf86DrvMsg(pInt->scrnIndex, X_ERROR,
- "Cannot set EXEC bit on high memory: %s\n",
- strerror(errno));
- } else {
- if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
- if (mmap((void *)(V_BIOS), SYS_BIOS - V_BIOS,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_SHARED | MAP_FIXED, fd, V_BIOS)
- == MAP_FAILED) {
- xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot map V_BIOS\n");
- close (fd);
- return FALSE;
- }
- } else {
- xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot open %s\n",DEV_MEM);
- return FALSE;
- }
- close (fd);
- }
-
- return TRUE;
-}
-
-void
-xf86FreeInt10(xf86Int10InfoPtr pInt)
-{
- if (!pInt)
- return;
-
-#ifdef _PC
- xf86Int10SaveRestoreBIOSVars(pInt, FALSE);
-#endif
- if (Int10Current == pInt) {
- shmdt(0);
- if (((linuxInt10Priv*)pInt->private)->highMem >= 0)
- shmdt((char*)HIGH_MEM);
- else
- munmap((pointer)V_BIOS, (SYS_BIOS - V_BIOS));
- Int10Current = NULL;
- }
-
- if (((linuxInt10Priv*)pInt->private)->base_high)
- shmdt(((linuxInt10Priv*)pInt->private)->base_high);
- shmdt(((linuxInt10Priv*)pInt->private)->base);
- shmctl(((linuxInt10Priv*)pInt->private)->lowMem, IPC_RMID, NULL);
- if (((linuxInt10Priv*)pInt->private)->highMem >= 0)
- shmctl(((linuxInt10Priv*)pInt->private)->highMem, IPC_RMID, NULL);
- free(((linuxInt10Priv*)pInt->private)->alloc);
- free(pInt->private);
- free(pInt);
-}
-
-void *
-xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off)
-{
- int pagesize = getpagesize();
- int num_pages = ALLOC_ENTRIES(pagesize);
- int i, j;
-
- for (i = 0; i < (num_pages - num); i++) {
- if (((linuxInt10Priv*)pInt->private)->alloc[i] == 0) {
- for (j = i; j < (num + i); j++)
- if ((((linuxInt10Priv*)pInt->private)->alloc[j] != 0))
- break;
- if (j == (num + i))
- break;
- else
- i = i + num;
- }
- }
- if (i == (num_pages - num))
- return NULL;
-
- for (j = i; j < (i + num); j++)
- ((linuxInt10Priv*)pInt->private)->alloc[j] = 1;
-
- *off = (i + 1) * pagesize;
-
- return ((linuxInt10Priv*)pInt->private)->base + ((i + 1) * pagesize);
-}
-
-void
-xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num)
-{
- int pagesize = getpagesize();
- int first = (((unsigned long)pbase
- - (unsigned long)((linuxInt10Priv*)pInt->private)->base)
- / pagesize) - 1;
- int i;
-
- for (i = first; i < (first + num); i++)
- ((linuxInt10Priv*)pInt->private)->alloc[i] = 0;
-}
-
-static CARD8
-read_b(xf86Int10InfoPtr pInt, int addr)
-{
- return *((CARD8 *)(memType)addr);
-}
-
-static CARD16
-read_w(xf86Int10InfoPtr pInt, int addr)
-{
- return *((CARD16 *)(memType)addr);
-}
-
-static CARD32
-read_l(xf86Int10InfoPtr pInt, int addr)
-{
- return *((CARD32 *)(memType)addr);
-}
-
-static void
-write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val)
-{
- *((CARD8 *)(memType)addr) = val;
-}
-
-static void
-write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val)
-{
- *((CARD16 *)(memType)addr) = val;
-}
-
-static
-void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val)
-{
- *((CARD32 *)(memType) addr) = val;
-}
-
-pointer
-xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr)
-{
- if (addr < V_RAM)
- return ((linuxInt10Priv*)pInt->private)->base + addr;
- else if (addr < V_BIOS)
- return (pointer)(memType)addr;
- else if (addr < SYS_BIOS) {
- if (((linuxInt10Priv*)pInt->private)->base_high)
- return (pointer)(((linuxInt10Priv*)pInt->private)->base_high
- - V_BIOS + addr);
- else
- return (pointer) (memType)addr;
- } else
- return (pointer) (memType)addr;
-}
-
-#if defined DoSubModules
-
-static Bool
-vm86_tst(void)
-{
- int __res;
-
-#ifdef __PIC__
- /* When compiling with -fPIC, we can't use asm constraint "b" because
- %ebx is already taken by gcc. */
- __asm__ __volatile__("pushl %%ebx\n\t"
- "movl %2,%%ebx\n\t"
- "movl %1,%%eax\n\t"
- "int $0x80\n\t"
- "popl %%ebx"
- :"=a" (__res)
- :"n" ((int)113), "r" (NULL));
-#else
- __asm__ __volatile__("int $0x80\n\t"
- :"=a" (__res):"a" ((int)113),
- "b" ((struct vm86_struct *)NULL));
-#endif
-
- if (__res < 0 && __res == -ENOSYS)
- return FALSE;
-
- return TRUE;
-}
-
-static Int10LinuxSubModuleState
-int10LinuxLoadSubModule(ScrnInfoPtr pScrn)
-{
- if (vm86_tst()) {
- if (xf86LoadSubModule(pScrn,"vm86"))
- return INT10_LOADED_VM86;
- }
- if (xf86LoadSubModule(pScrn,"x86emu"))
- return INT10_LOADED_X86EMU;
-
- return INT10_LOAD_FAILED;
-}
-
-#endif /* DoSubModules */
+/*
+ * linux specific part of the int10 module
+ * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2008 Egbert Eich
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Pci.h"
+#include "compiler.h"
+#define _INT10_PRIVATE
+#include "xf86int10.h"
+#ifdef __sparc__
+#define DEV_MEM "/dev/fb"
+#else
+#define DEV_MEM "/dev/mem"
+#endif
+#define ALLOC_ENTRIES(x) ((V_RAM / x) - 1)
+#define SHMERRORPTR (pointer)(-1)
+
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <unistd.h>
+#include <string.h>
+
+static int counter = 0;
+static unsigned long int10Generation = 0;
+
+static CARD8 read_b(xf86Int10InfoPtr pInt, int addr);
+static CARD16 read_w(xf86Int10InfoPtr pInt, int addr);
+static CARD32 read_l(xf86Int10InfoPtr pInt, int addr);
+static void write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val);
+static void write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val);
+static void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val);
+
+int10MemRec linuxMem = {
+ read_b,
+ read_w,
+ read_l,
+ write_b,
+ write_w,
+ write_l
+};
+
+typedef struct {
+ int lowMem;
+ int highMem;
+ char* base;
+ char* base_high;
+ int screen;
+ char* alloc;
+} linuxInt10Priv;
+
+#if defined DoSubModules
+
+typedef enum {
+ INT10_NOT_LOADED,
+ INT10_LOADED_VM86,
+ INT10_LOADED_X86EMU,
+ INT10_LOAD_FAILED
+} Int10LinuxSubModuleState;
+
+static Int10LinuxSubModuleState loadedSubModule = INT10_NOT_LOADED;
+
+static Int10LinuxSubModuleState int10LinuxLoadSubModule(ScrnInfoPtr pScrn);
+
+#endif /* DoSubModules */
+
+xf86Int10InfoPtr
+xf86ExtendedInitInt10(int entityIndex, int Flags)
+{
+ xf86Int10InfoPtr pInt = NULL;
+ int screen;
+ int fd;
+ static void* vidMem = NULL;
+ static void* sysMem = NULL;
+ void* vMem = NULL;
+ void *options = NULL;
+ int low_mem;
+ int high_mem = -1;
+ char *base = SHMERRORPTR;
+ char *base_high = SHMERRORPTR;
+ int pagesize;
+ memType cs;
+ legacyVGARec vga;
+ Bool videoBiosMapped = FALSE;
+
+ if (int10Generation != serverGeneration) {
+ counter = 0;
+ int10Generation = serverGeneration;
+ }
+
+ screen = (xf86FindScreenForEntity(entityIndex))->scrnIndex;
+
+ options = xf86HandleInt10Options(xf86Screens[screen],entityIndex);
+
+ if (int10skip(options)) {
+ free(options);
+ return NULL;
+ }
+
+#if defined DoSubModules
+ if (loadedSubModule == INT10_NOT_LOADED)
+ loadedSubModule = int10LinuxLoadSubModule(xf86Screens[screen]);
+
+ if (loadedSubModule == INT10_LOAD_FAILED)
+ return NULL;
+#endif
+
+ if ((!vidMem) || (!sysMem)) {
+ if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
+ if (!sysMem) {
+ DebugF("Mapping sys bios area\n");
+ if ((sysMem = mmap((void *)(SYS_BIOS), BIOS_SIZE,
+ PROT_READ | PROT_EXEC,
+ MAP_SHARED | MAP_FIXED, fd, SYS_BIOS))
+ == MAP_FAILED) {
+ xf86DrvMsg(screen, X_ERROR, "Cannot map SYS BIOS\n");
+ close(fd);
+ goto error0;
+ }
+ }
+ if (!vidMem) {
+ DebugF("Mapping VRAM area\n");
+ if ((vidMem = mmap((void *)(V_RAM), VRAM_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_SHARED | MAP_FIXED, fd, V_RAM))
+ == MAP_FAILED) {
+ xf86DrvMsg(screen, X_ERROR, "Cannot map V_RAM\n");
+ close(fd);
+ goto error0;
+ }
+ }
+ close(fd);
+ } else {
+ xf86DrvMsg(screen, X_ERROR, "Cannot open %s\n", DEV_MEM);
+ goto error0;
+ }
+ }
+
+ pInt = (xf86Int10InfoPtr)xnfcalloc(1, sizeof(xf86Int10InfoRec));
+ pInt->scrnIndex = screen;
+ pInt->entityIndex = entityIndex;
+ pInt->dev = xf86GetPciInfoForEntity(entityIndex);
+
+ if (!xf86Int10ExecSetup(pInt))
+ goto error0;
+ pInt->mem = &linuxMem;
+ pagesize = getpagesize();
+ pInt->private = (pointer)xnfcalloc(1, sizeof(linuxInt10Priv));
+ ((linuxInt10Priv*)pInt->private)->screen = screen;
+ ((linuxInt10Priv*)pInt->private)->alloc =
+ (pointer)xnfcalloc(1, ALLOC_ENTRIES(pagesize));
+
+ if (!xf86IsEntityPrimary(entityIndex)) {
+ DebugF("Mapping high memory area\n");
+ if ((high_mem = shmget(counter++, HIGH_MEM_SIZE,
+ IPC_CREAT | SHM_R | SHM_W)) == -1) {
+ if (errno == ENOSYS)
+ xf86DrvMsg(screen, X_ERROR, "shmget error\n Please reconfigure"
+ " your kernel to include System V IPC support\n");
+ else
+ xf86DrvMsg(screen, X_ERROR,
+ "shmget(highmem) error: %s\n",strerror(errno));
+ goto error1;
+ }
+ } else {
+ DebugF("Mapping Video BIOS\n");
+ videoBiosMapped = TRUE;
+ if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
+ if ((vMem = mmap((void *)(V_BIOS), SYS_BIOS - V_BIOS,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_SHARED | MAP_FIXED, fd, V_BIOS))
+ == MAP_FAILED) {
+ xf86DrvMsg(screen, X_ERROR, "Cannot map V_BIOS\n");
+ close(fd);
+ goto error1;
+ }
+ close (fd);
+ } else
+ goto error1;
+ }
+ ((linuxInt10Priv*)pInt->private)->highMem = high_mem;
+
+ DebugF("Mapping 640kB area\n");
+ if ((low_mem = shmget(counter++, V_RAM,
+ IPC_CREAT | SHM_R | SHM_W)) == -1) {
+ xf86DrvMsg(screen, X_ERROR,
+ "shmget(lowmem) error: %s\n",strerror(errno));
+ goto error2;
+ }
+
+ ((linuxInt10Priv*)pInt->private)->lowMem = low_mem;
+ base = shmat(low_mem, 0, 0);
+ if (base == SHMERRORPTR) {
+ xf86DrvMsg(screen, X_ERROR,
+ "shmat(low_mem) error: %s\n",strerror(errno));
+ goto error3;
+ }
+ ((linuxInt10Priv *)pInt->private)->base = base;
+ if (high_mem > -1) {
+ base_high = shmat(high_mem, 0, 0);
+ if (base_high == SHMERRORPTR) {
+ xf86DrvMsg(screen, X_ERROR,
+ "shmat(high_mem) error: %s\n",strerror(errno));
+ goto error3;
+ }
+ ((linuxInt10Priv*)pInt->private)->base_high = base_high;
+ } else
+ ((linuxInt10Priv*)pInt->private)->base_high = NULL;
+
+ if (!MapCurrentInt10(pInt))
+ goto error3;
+
+ Int10Current = pInt;
+
+ DebugF("Mapping int area\n");
+ if (xf86ReadBIOS(0, 0, (unsigned char *)0, LOW_PAGE_SIZE) < 0) {
+ xf86DrvMsg(screen, X_ERROR, "Cannot read int vect\n");
+ goto error3;
+ }
+ DebugF("done\n");
+ /*
+ * Read in everything between V_BIOS and SYS_BIOS as some system BIOSes
+ * have executable code there. Note that xf86ReadBIOS() can only bring in
+ * 64K bytes at a time.
+ */
+ if (!videoBiosMapped) {
+ memset((pointer)V_BIOS, 0, SYS_BIOS - V_BIOS);
+ DebugF("Reading BIOS\n");
+ for (cs = V_BIOS; cs < SYS_BIOS; cs += V_BIOS_SIZE)
+ if (xf86ReadBIOS(cs, 0, (pointer)cs, V_BIOS_SIZE) < V_BIOS_SIZE)
+ xf86DrvMsg(screen, X_WARNING,
+ "Unable to retrieve all of segment 0x%06lX.\n",
+ (long)cs);
+ DebugF("done\n");
+ }
+
+ if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) {
+ if (!xf86int10GetBiosSegment(pInt, NULL))
+ goto error3;
+
+ set_return_trap(pInt);
+#ifdef _PC
+ pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
+ if (! (pInt->Flags & SET_BIOS_SCRATCH))
+ pInt->Flags &= ~RESTORE_BIOS_SCRATCH;
+ xf86Int10SaveRestoreBIOSVars(pInt, TRUE);
+#endif
+ } else {
+ const BusType location_type = xf86int10GetBiosLocationType(pInt);
+
+ switch (location_type) {
+ case BUS_PCI: {
+ int err;
+ struct pci_device *rom_device =
+ xf86GetPciInfoForEntity(pInt->entityIndex);
+
+ pci_device_enable(rom_device);
+ err = pci_device_read_rom(rom_device, (unsigned char *)(V_BIOS));
+ if (err) {
+ xf86DrvMsg(screen,X_ERROR,"Cannot read V_BIOS (%s)\n",
+ strerror(err));
+ goto error3;
+ }
+
+ pInt->BIOSseg = V_BIOS >> 4;
+ break;
+ }
+ default:
+ goto error3;
+ }
+
+ pInt->num = 0xe6;
+ reset_int_vect(pInt);
+ set_return_trap(pInt);
+ LockLegacyVGA(pInt, &vga);
+ xf86ExecX86int10(pInt);
+ UnlockLegacyVGA(pInt, &vga);
+ }
+#ifdef DEBUG
+ dprint(0xc0000, 0x20);
+#endif
+
+ free(options);
+ return pInt;
+
+error3:
+ if (base_high)
+ shmdt(base_high);
+ shmdt(base);
+ shmdt(0);
+ if (base_high)
+ shmdt((char*)HIGH_MEM);
+ shmctl(low_mem, IPC_RMID, NULL);
+ Int10Current = NULL;
+error2:
+ if (high_mem > -1)
+ shmctl(high_mem, IPC_RMID,NULL);
+error1:
+ if (vMem)
+ munmap(vMem, SYS_BIOS - V_BIOS);
+ free(((linuxInt10Priv*)pInt->private)->alloc);
+ free(pInt->private);
+error0:
+ free(options);
+ free(pInt);
+ return NULL;
+}
+
+Bool
+MapCurrentInt10(xf86Int10InfoPtr pInt)
+{
+ pointer addr;
+ int fd = -1;
+
+ if (Int10Current) {
+ shmdt(0);
+ if (((linuxInt10Priv*)Int10Current->private)->highMem >= 0)
+ shmdt((char*)HIGH_MEM);
+ else
+ munmap((pointer)V_BIOS, (SYS_BIOS - V_BIOS));
+ }
+ addr = shmat(((linuxInt10Priv*)pInt->private)->lowMem, (char*)1, SHM_RND);
+ if (addr == SHMERRORPTR) {
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot shmat() low memory\n");
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR,
+ "shmat(low_mem) error: %s\n",strerror(errno));
+ return FALSE;
+ }
+ if (mprotect((void*)0, V_RAM, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR,
+ "Cannot set EXEC bit on low memory: %s\n", strerror(errno));
+
+ if (((linuxInt10Priv*)pInt->private)->highMem >= 0) {
+ addr = shmat(((linuxInt10Priv*)pInt->private)->highMem,
+ (char*)HIGH_MEM, 0);
+ if (addr == SHMERRORPTR) {
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR,
+ "Cannot shmat() high memory\n");
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR,
+ "shmget error: %s\n",strerror(errno));
+ return FALSE;
+ }
+ if (mprotect((void*)HIGH_MEM, HIGH_MEM_SIZE,
+ PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR,
+ "Cannot set EXEC bit on high memory: %s\n",
+ strerror(errno));
+ } else {
+ if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
+ if (mmap((void *)(V_BIOS), SYS_BIOS - V_BIOS,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_SHARED | MAP_FIXED, fd, V_BIOS)
+ == MAP_FAILED) {
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot map V_BIOS\n");
+ close (fd);
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot open %s\n",DEV_MEM);
+ return FALSE;
+ }
+ close (fd);
+ }
+
+ return TRUE;
+}
+
+void
+xf86FreeInt10(xf86Int10InfoPtr pInt)
+{
+ if (!pInt)
+ return;
+
+#ifdef _PC
+ xf86Int10SaveRestoreBIOSVars(pInt, FALSE);
+#endif
+ if (Int10Current == pInt) {
+ shmdt(0);
+ if (((linuxInt10Priv*)pInt->private)->highMem >= 0)
+ shmdt((char*)HIGH_MEM);
+ else
+ munmap((pointer)V_BIOS, (SYS_BIOS - V_BIOS));
+ Int10Current = NULL;
+ }
+
+ if (((linuxInt10Priv*)pInt->private)->base_high)
+ shmdt(((linuxInt10Priv*)pInt->private)->base_high);
+ shmdt(((linuxInt10Priv*)pInt->private)->base);
+ shmctl(((linuxInt10Priv*)pInt->private)->lowMem, IPC_RMID, NULL);
+ if (((linuxInt10Priv*)pInt->private)->highMem >= 0)
+ shmctl(((linuxInt10Priv*)pInt->private)->highMem, IPC_RMID, NULL);
+ free(((linuxInt10Priv*)pInt->private)->alloc);
+ free(pInt->private);
+ free(pInt);
+}
+
+void *
+xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off)
+{
+ int pagesize = getpagesize();
+ int num_pages = ALLOC_ENTRIES(pagesize);
+ int i, j;
+
+ for (i = 0; i < (num_pages - num); i++) {
+ if (((linuxInt10Priv*)pInt->private)->alloc[i] == 0) {
+ for (j = i; j < (num + i); j++)
+ if ((((linuxInt10Priv*)pInt->private)->alloc[j] != 0))
+ break;
+ if (j == (num + i))
+ break;
+ else
+ i = i + num;
+ }
+ }
+ if (i == (num_pages - num))
+ return NULL;
+
+ for (j = i; j < (i + num); j++)
+ ((linuxInt10Priv*)pInt->private)->alloc[j] = 1;
+
+ *off = (i + 1) * pagesize;
+
+ return ((linuxInt10Priv*)pInt->private)->base + ((i + 1) * pagesize);
+}
+
+void
+xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num)
+{
+ int pagesize = getpagesize();
+ int first = (((unsigned long)pbase
+ - (unsigned long)((linuxInt10Priv*)pInt->private)->base)
+ / pagesize) - 1;
+ int i;
+
+ for (i = first; i < (first + num); i++)
+ ((linuxInt10Priv*)pInt->private)->alloc[i] = 0;
+}
+
+static CARD8
+read_b(xf86Int10InfoPtr pInt, int addr)
+{
+ return *((CARD8 *)(memType)addr);
+}
+
+static CARD16
+read_w(xf86Int10InfoPtr pInt, int addr)
+{
+ return *((CARD16 *)(memType)addr);
+}
+
+static CARD32
+read_l(xf86Int10InfoPtr pInt, int addr)
+{
+ return *((CARD32 *)(memType)addr);
+}
+
+static void
+write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val)
+{
+ *((CARD8 *)(memType)addr) = val;
+}
+
+static void
+write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val)
+{
+ *((CARD16 *)(memType)addr) = val;
+}
+
+static
+void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val)
+{
+ *((CARD32 *)(memType) addr) = val;
+}
+
+pointer
+xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr)
+{
+ if (addr < V_RAM)
+ return ((linuxInt10Priv*)pInt->private)->base + addr;
+ else if (addr < V_BIOS)
+ return (pointer)(memType)addr;
+ else if (addr < SYS_BIOS) {
+ if (((linuxInt10Priv*)pInt->private)->base_high)
+ return (pointer)(((linuxInt10Priv*)pInt->private)->base_high
+ - V_BIOS + addr);
+ else
+ return (pointer) (memType)addr;
+ } else
+ return (pointer) (memType)addr;
+}
+
+#if defined DoSubModules
+
+static Bool
+vm86_tst(void)
+{
+ int __res;
+
+#ifdef __PIC__
+ /* When compiling with -fPIC, we can't use asm constraint "b" because
+ %ebx is already taken by gcc. */
+ __asm__ __volatile__("pushl %%ebx\n\t"
+ "movl %2,%%ebx\n\t"
+ "movl %1,%%eax\n\t"
+ "int $0x80\n\t"
+ "popl %%ebx"
+ :"=a" (__res)
+ :"n" ((int)113), "r" (NULL));
+#else
+ __asm__ __volatile__("int $0x80\n\t"
+ :"=a" (__res):"a" ((int)113),
+ "b" ((struct vm86_struct *)NULL));
+#endif
+
+ if (__res < 0 && __res == -ENOSYS)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Int10LinuxSubModuleState
+int10LinuxLoadSubModule(ScrnInfoPtr pScrn)
+{
+ if (vm86_tst()) {
+ if (xf86LoadSubModule(pScrn,"vm86"))
+ return INT10_LOADED_VM86;
+ }
+ if (xf86LoadSubModule(pScrn,"x86emu"))
+ return INT10_LOADED_X86EMU;
+
+ return INT10_LOAD_FAILED;
+}
+
+#endif /* DoSubModules */