562 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			562 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * 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 (void *)(-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;
 | |
|     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 */
 | |
| 
 | |
| static Bool
 | |
| readLegacy(struct pci_device *dev, unsigned char *buf, int base, int len)
 | |
| {
 | |
|     void *map;
 | |
| 
 | |
|     if (pci_device_map_legacy(dev, base, len, 0, &map))
 | |
|         return FALSE;
 | |
| 
 | |
|     memcpy(buf, map, len);
 | |
|     pci_device_unmap_legacy(dev, man, len);
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| 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;
 | |
|     ScrnInfoPtr pScrn;
 | |
|     if (int10Generation != serverGeneration) {
 | |
|         counter = 0;
 | |
|         int10Generation = serverGeneration;
 | |
|     }
 | |
| 
 | |
|     pScrn = xf86FindScreenForEntity(entityIndex);
 | |
|     screen = pScrn->scrnIndex;
 | |
| 
 | |
|     options = xf86HandleInt10Options(pScrn, entityIndex);
 | |
| 
 | |
|     if (int10skip(options)) {
 | |
|         free(options);
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
| #if defined DoSubModules
 | |
|     if (loadedSubModule == INT10_NOT_LOADED)
 | |
|         loadedSubModule = int10LinuxLoadSubModule(pScrn);
 | |
| 
 | |
|     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->pScrn = pScrn;
 | |
|     pInt->entityIndex = entityIndex;
 | |
|     pInt->dev = xf86GetPciInfoForEntity(entityIndex);
 | |
| 
 | |
|     if (!xf86Int10ExecSetup(pInt))
 | |
|         goto error0;
 | |
|     pInt->mem = &linuxMem;
 | |
|     pagesize = getpagesize();
 | |
|     pInt->private = (void *) xnfcalloc(1, sizeof(linuxInt10Priv));
 | |
|     ((linuxInt10Priv *) pInt->private)->alloc =
 | |
|         (void *) 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");
 | |
|     /* note: yes, we really are writing the 0 page here */
 | |
|     if (!readLegacy(pInt->dev, (unsigned char *) 0, 0, LOW_PAGE_SIZE)) {
 | |
|         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((void *) V_BIOS, 0, SYS_BIOS - V_BIOS);
 | |
|         DebugF("Reading BIOS\n");
 | |
|         for (cs = V_BIOS; cs < SYS_BIOS; cs += V_BIOS_SIZE)
 | |
|             if (!readLegacy(pInt->dev, (void *)cs, cs, 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)
 | |
| {
 | |
|     void *addr;
 | |
|     int fd = -1;
 | |
| 
 | |
|     if (Int10Current) {
 | |
|         shmdt(0);
 | |
|         if (((linuxInt10Priv *) Int10Current->private)->highMem >= 0)
 | |
|             shmdt((char *) HIGH_MEM);
 | |
|         else
 | |
|             munmap((void *) V_BIOS, (SYS_BIOS - V_BIOS));
 | |
|     }
 | |
|     addr =
 | |
|         shmat(((linuxInt10Priv *) pInt->private)->lowMem, (char *) 1, SHM_RND);
 | |
|     if (addr == SHMERRORPTR) {
 | |
|         xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "Cannot shmat() low memory\n");
 | |
|         xf86DrvMsg(pInt->pScrn->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->pScrn->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->pScrn->scrnIndex, X_ERROR,
 | |
|                        "Cannot shmat() high memory\n");
 | |
|             xf86DrvMsg(pInt->pScrn->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->pScrn->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->pScrn->scrnIndex, X_ERROR, "Cannot map V_BIOS\n");
 | |
|                 close(fd);
 | |
|                 return FALSE;
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             xf86DrvMsg(pInt->pScrn->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((void *) 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;
 | |
| }
 | |
| 
 | |
| void *
 | |
| xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr)
 | |
| {
 | |
|     if (addr < V_RAM)
 | |
|         return ((linuxInt10Priv *) pInt->private)->base + addr;
 | |
|     else if (addr < V_BIOS)
 | |
|         return (void *) (memType) addr;
 | |
|     else if (addr < SYS_BIOS) {
 | |
|         if (((linuxInt10Priv *) pInt->private)->base_high)
 | |
|             return (void *) (((linuxInt10Priv *) pInt->private)->base_high
 | |
|                               - V_BIOS + addr);
 | |
|         else
 | |
|             return (void *) (memType) addr;
 | |
|     }
 | |
|     else
 | |
|         return (void *) (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 */
 |