xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

linux.c (16143B)


      1 /*
      2  * linux specific part of the int10 module
      3  * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2008 Egbert Eich
      4  */
      5 #ifdef HAVE_XORG_CONFIG_H
      6 #include <xorg-config.h>
      7 #endif
      8 
      9 #include "xf86.h"
     10 #include "xf86_OSproc.h"
     11 #include "xf86Pci.h"
     12 #include "compiler.h"
     13 #define _INT10_PRIVATE
     14 #include "xf86int10.h"
     15 #ifdef __sparc__
     16 #define DEV_MEM "/dev/fb"
     17 #else
     18 #define DEV_MEM "/dev/mem"
     19 #endif
     20 #define ALLOC_ENTRIES(x) ((V_RAM / x) - 1)
     21 #define SHMERRORPTR (void *)(-1)
     22 
     23 #include <fcntl.h>
     24 #include <errno.h>
     25 #include <sys/mman.h>
     26 #include <sys/ipc.h>
     27 #include <sys/shm.h>
     28 #include <unistd.h>
     29 #include <string.h>
     30 
     31 static int counter = 0;
     32 static unsigned long int10Generation = 0;
     33 
     34 static CARD8 read_b(xf86Int10InfoPtr pInt, int addr);
     35 static CARD16 read_w(xf86Int10InfoPtr pInt, int addr);
     36 static CARD32 read_l(xf86Int10InfoPtr pInt, int addr);
     37 static void write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val);
     38 static void write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val);
     39 static void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val);
     40 
     41 int10MemRec linuxMem = {
     42     read_b,
     43     read_w,
     44     read_l,
     45     write_b,
     46     write_w,
     47     write_l
     48 };
     49 
     50 typedef struct {
     51     int lowMem;
     52     int highMem;
     53     char *base;
     54     char *base_high;
     55     char *alloc;
     56 } linuxInt10Priv;
     57 
     58 #if defined DoSubModules
     59 
     60 typedef enum {
     61     INT10_NOT_LOADED,
     62     INT10_LOADED_VM86,
     63     INT10_LOADED_X86EMU,
     64     INT10_LOAD_FAILED
     65 } Int10LinuxSubModuleState;
     66 
     67 static Int10LinuxSubModuleState loadedSubModule = INT10_NOT_LOADED;
     68 
     69 static Int10LinuxSubModuleState int10LinuxLoadSubModule(ScrnInfoPtr pScrn);
     70 
     71 #endif                          /* DoSubModules */
     72 
     73 static Bool
     74 readLegacy(struct pci_device *dev, unsigned char *buf, int base, int len)
     75 {
     76     void *map;
     77 
     78     if (pci_device_map_legacy(dev, base, len, 0, &map))
     79         return FALSE;
     80 
     81     memcpy(buf, map, len);
     82     pci_device_unmap_legacy(dev, man, len);
     83 
     84     return TRUE;
     85 }
     86 
     87 xf86Int10InfoPtr
     88 xf86ExtendedInitInt10(int entityIndex, int Flags)
     89 {
     90     xf86Int10InfoPtr pInt = NULL;
     91     int screen;
     92     int fd;
     93     static void *vidMem = NULL;
     94     static void *sysMem = NULL;
     95     void *vMem = NULL;
     96     void *options = NULL;
     97     int low_mem;
     98     int high_mem = -1;
     99     char *base = SHMERRORPTR;
    100     char *base_high = SHMERRORPTR;
    101     int pagesize;
    102     memType cs;
    103     legacyVGARec vga;
    104     Bool videoBiosMapped = FALSE;
    105     ScrnInfoPtr pScrn;
    106     if (int10Generation != serverGeneration) {
    107         counter = 0;
    108         int10Generation = serverGeneration;
    109     }
    110 
    111     pScrn = xf86FindScreenForEntity(entityIndex);
    112     screen = pScrn->scrnIndex;
    113 
    114     options = xf86HandleInt10Options(pScrn, entityIndex);
    115 
    116     if (int10skip(options)) {
    117         free(options);
    118         return NULL;
    119     }
    120 
    121 #if defined DoSubModules
    122     if (loadedSubModule == INT10_NOT_LOADED)
    123         loadedSubModule = int10LinuxLoadSubModule(pScrn);
    124 
    125     if (loadedSubModule == INT10_LOAD_FAILED)
    126         return NULL;
    127 #endif
    128 
    129     if ((!vidMem) || (!sysMem)) {
    130         if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
    131             if (!sysMem) {
    132                 DebugF("Mapping sys bios area\n");
    133                 if ((sysMem = mmap((void *) (SYS_BIOS), BIOS_SIZE,
    134                                    PROT_READ | PROT_EXEC,
    135                                    MAP_SHARED | MAP_FIXED, fd, SYS_BIOS))
    136                     == MAP_FAILED) {
    137                     xf86DrvMsg(screen, X_ERROR, "Cannot map SYS BIOS\n");
    138                     close(fd);
    139                     goto error0;
    140                 }
    141             }
    142             if (!vidMem) {
    143                 DebugF("Mapping VRAM area\n");
    144                 if ((vidMem = mmap((void *) (V_RAM), VRAM_SIZE,
    145                                    PROT_READ | PROT_WRITE | PROT_EXEC,
    146                                    MAP_SHARED | MAP_FIXED, fd, V_RAM))
    147                     == MAP_FAILED) {
    148                     xf86DrvMsg(screen, X_ERROR, "Cannot map V_RAM\n");
    149                     close(fd);
    150                     goto error0;
    151                 }
    152             }
    153             close(fd);
    154         }
    155         else {
    156             xf86DrvMsg(screen, X_ERROR, "Cannot open %s\n", DEV_MEM);
    157             goto error0;
    158         }
    159     }
    160 
    161     pInt = (xf86Int10InfoPtr) xnfcalloc(1, sizeof(xf86Int10InfoRec));
    162     pInt->pScrn = pScrn;
    163     pInt->entityIndex = entityIndex;
    164     pInt->dev = xf86GetPciInfoForEntity(entityIndex);
    165 
    166     if (!xf86Int10ExecSetup(pInt))
    167         goto error0;
    168     pInt->mem = &linuxMem;
    169     pagesize = getpagesize();
    170     pInt->private = (void *) xnfcalloc(1, sizeof(linuxInt10Priv));
    171     ((linuxInt10Priv *) pInt->private)->alloc =
    172         (void *) xnfcalloc(1, ALLOC_ENTRIES(pagesize));
    173 
    174     if (!xf86IsEntityPrimary(entityIndex)) {
    175         DebugF("Mapping high memory area\n");
    176         if ((high_mem = shmget(counter++, HIGH_MEM_SIZE,
    177                                IPC_CREAT | SHM_R | SHM_W)) == -1) {
    178             if (errno == ENOSYS)
    179                 xf86DrvMsg(screen, X_ERROR, "shmget error\n Please reconfigure"
    180                            " your kernel to include System V IPC support\n");
    181             else
    182                 xf86DrvMsg(screen, X_ERROR,
    183                            "shmget(highmem) error: %s\n", strerror(errno));
    184             goto error1;
    185         }
    186     }
    187     else {
    188         DebugF("Mapping Video BIOS\n");
    189         videoBiosMapped = TRUE;
    190         if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
    191             if ((vMem = mmap((void *) (V_BIOS), SYS_BIOS - V_BIOS,
    192                              PROT_READ | PROT_WRITE | PROT_EXEC,
    193                              MAP_SHARED | MAP_FIXED, fd, V_BIOS))
    194                 == MAP_FAILED) {
    195                 xf86DrvMsg(screen, X_ERROR, "Cannot map V_BIOS\n");
    196                 close(fd);
    197                 goto error1;
    198             }
    199             close(fd);
    200         }
    201         else
    202             goto error1;
    203     }
    204     ((linuxInt10Priv *) pInt->private)->highMem = high_mem;
    205 
    206     DebugF("Mapping 640kB area\n");
    207     if ((low_mem = shmget(counter++, V_RAM, IPC_CREAT | SHM_R | SHM_W)) == -1) {
    208         xf86DrvMsg(screen, X_ERROR,
    209                    "shmget(lowmem) error: %s\n", strerror(errno));
    210         goto error2;
    211     }
    212 
    213     ((linuxInt10Priv *) pInt->private)->lowMem = low_mem;
    214     base = shmat(low_mem, 0, 0);
    215     if (base == SHMERRORPTR) {
    216         xf86DrvMsg(screen, X_ERROR,
    217                    "shmat(low_mem) error: %s\n", strerror(errno));
    218         goto error3;
    219     }
    220     ((linuxInt10Priv *) pInt->private)->base = base;
    221     if (high_mem > -1) {
    222         base_high = shmat(high_mem, 0, 0);
    223         if (base_high == SHMERRORPTR) {
    224             xf86DrvMsg(screen, X_ERROR,
    225                        "shmat(high_mem) error: %s\n", strerror(errno));
    226             goto error3;
    227         }
    228         ((linuxInt10Priv *) pInt->private)->base_high = base_high;
    229     }
    230     else
    231         ((linuxInt10Priv *) pInt->private)->base_high = NULL;
    232 
    233     if (!MapCurrentInt10(pInt))
    234         goto error3;
    235 
    236     Int10Current = pInt;
    237 
    238     DebugF("Mapping int area\n");
    239     /* note: yes, we really are writing the 0 page here */
    240     if (!readLegacy(pInt->dev, (unsigned char *) 0, 0, LOW_PAGE_SIZE)) {
    241         xf86DrvMsg(screen, X_ERROR, "Cannot read int vect\n");
    242         goto error3;
    243     }
    244     DebugF("done\n");
    245     /*
    246      * Read in everything between V_BIOS and SYS_BIOS as some system BIOSes
    247      * have executable code there.  Note that xf86ReadBIOS() can only bring in
    248      * 64K bytes at a time.
    249      */
    250     if (!videoBiosMapped) {
    251         memset((void *) V_BIOS, 0, SYS_BIOS - V_BIOS);
    252         DebugF("Reading BIOS\n");
    253         for (cs = V_BIOS; cs < SYS_BIOS; cs += V_BIOS_SIZE)
    254             if (!readLegacy(pInt->dev, (void *)cs, cs, V_BIOS_SIZE))
    255                 xf86DrvMsg(screen, X_WARNING,
    256                            "Unable to retrieve all of segment 0x%06lX.\n",
    257                            (long) cs);
    258         DebugF("done\n");
    259     }
    260 
    261     if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) {
    262         if (!xf86int10GetBiosSegment(pInt, NULL))
    263             goto error3;
    264 
    265         set_return_trap(pInt);
    266 #ifdef _PC
    267         pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
    268         if (!(pInt->Flags & SET_BIOS_SCRATCH))
    269             pInt->Flags &= ~RESTORE_BIOS_SCRATCH;
    270         xf86Int10SaveRestoreBIOSVars(pInt, TRUE);
    271 #endif
    272     }
    273     else {
    274         const BusType location_type = xf86int10GetBiosLocationType(pInt);
    275 
    276         switch (location_type) {
    277         case BUS_PCI:{
    278             int err;
    279             struct pci_device *rom_device =
    280                 xf86GetPciInfoForEntity(pInt->entityIndex);
    281 
    282             pci_device_enable(rom_device);
    283             err = pci_device_read_rom(rom_device, (unsigned char *) (V_BIOS));
    284             if (err) {
    285                 xf86DrvMsg(screen, X_ERROR, "Cannot read V_BIOS (%s)\n",
    286                            strerror(err));
    287                 goto error3;
    288             }
    289 
    290             pInt->BIOSseg = V_BIOS >> 4;
    291             break;
    292         }
    293         default:
    294             goto error3;
    295         }
    296 
    297         pInt->num = 0xe6;
    298         reset_int_vect(pInt);
    299         set_return_trap(pInt);
    300         LockLegacyVGA(pInt, &vga);
    301         xf86ExecX86int10(pInt);
    302         UnlockLegacyVGA(pInt, &vga);
    303     }
    304 #ifdef DEBUG
    305     dprint(0xc0000, 0x20);
    306 #endif
    307 
    308     free(options);
    309     return pInt;
    310 
    311  error3:
    312     if (base_high)
    313         shmdt(base_high);
    314     shmdt(base);
    315     shmdt(0);
    316     if (base_high)
    317         shmdt((char *) HIGH_MEM);
    318     shmctl(low_mem, IPC_RMID, NULL);
    319     Int10Current = NULL;
    320  error2:
    321     if (high_mem > -1)
    322         shmctl(high_mem, IPC_RMID, NULL);
    323  error1:
    324     if (vMem)
    325         munmap(vMem, SYS_BIOS - V_BIOS);
    326     free(((linuxInt10Priv *) pInt->private)->alloc);
    327     free(pInt->private);
    328  error0:
    329     free(options);
    330     free(pInt);
    331     return NULL;
    332 }
    333 
    334 Bool
    335 MapCurrentInt10(xf86Int10InfoPtr pInt)
    336 {
    337     void *addr;
    338     int fd = -1;
    339 
    340     if (Int10Current) {
    341         shmdt(0);
    342         if (((linuxInt10Priv *) Int10Current->private)->highMem >= 0)
    343             shmdt((char *) HIGH_MEM);
    344         else
    345             munmap((void *) V_BIOS, (SYS_BIOS - V_BIOS));
    346     }
    347     addr =
    348         shmat(((linuxInt10Priv *) pInt->private)->lowMem, (char *) 1, SHM_RND);
    349     if (addr == SHMERRORPTR) {
    350         xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "Cannot shmat() low memory\n");
    351         xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR,
    352                    "shmat(low_mem) error: %s\n", strerror(errno));
    353         return FALSE;
    354     }
    355     if (mprotect((void *) 0, V_RAM, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
    356         xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR,
    357                    "Cannot set EXEC bit on low memory: %s\n", strerror(errno));
    358 
    359     if (((linuxInt10Priv *) pInt->private)->highMem >= 0) {
    360         addr = shmat(((linuxInt10Priv *) pInt->private)->highMem,
    361                      (char *) HIGH_MEM, 0);
    362         if (addr == SHMERRORPTR) {
    363             xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR,
    364                        "Cannot shmat() high memory\n");
    365             xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR,
    366                        "shmget error: %s\n", strerror(errno));
    367             return FALSE;
    368         }
    369         if (mprotect((void *) HIGH_MEM, HIGH_MEM_SIZE,
    370                      PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
    371             xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR,
    372                        "Cannot set EXEC bit on high memory: %s\n",
    373                        strerror(errno));
    374     }
    375     else {
    376         if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) {
    377             if (mmap((void *) (V_BIOS), SYS_BIOS - V_BIOS,
    378                      PROT_READ | PROT_WRITE | PROT_EXEC,
    379                      MAP_SHARED | MAP_FIXED, fd, V_BIOS)
    380                 == MAP_FAILED) {
    381                 xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "Cannot map V_BIOS\n");
    382                 close(fd);
    383                 return FALSE;
    384             }
    385         }
    386         else {
    387             xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "Cannot open %s\n", DEV_MEM);
    388             return FALSE;
    389         }
    390         close(fd);
    391     }
    392 
    393     return TRUE;
    394 }
    395 
    396 void
    397 xf86FreeInt10(xf86Int10InfoPtr pInt)
    398 {
    399     if (!pInt)
    400         return;
    401 
    402 #ifdef _PC
    403     xf86Int10SaveRestoreBIOSVars(pInt, FALSE);
    404 #endif
    405     if (Int10Current == pInt) {
    406         shmdt(0);
    407         if (((linuxInt10Priv *) pInt->private)->highMem >= 0)
    408             shmdt((char *) HIGH_MEM);
    409         else
    410             munmap((void *) V_BIOS, (SYS_BIOS - V_BIOS));
    411         Int10Current = NULL;
    412     }
    413 
    414     if (((linuxInt10Priv *) pInt->private)->base_high)
    415         shmdt(((linuxInt10Priv *) pInt->private)->base_high);
    416     shmdt(((linuxInt10Priv *) pInt->private)->base);
    417     shmctl(((linuxInt10Priv *) pInt->private)->lowMem, IPC_RMID, NULL);
    418     if (((linuxInt10Priv *) pInt->private)->highMem >= 0)
    419         shmctl(((linuxInt10Priv *) pInt->private)->highMem, IPC_RMID, NULL);
    420     free(((linuxInt10Priv *) pInt->private)->alloc);
    421     free(pInt->private);
    422     free(pInt);
    423 }
    424 
    425 void *
    426 xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off)
    427 {
    428     int pagesize = getpagesize();
    429     int num_pages = ALLOC_ENTRIES(pagesize);
    430     int i, j;
    431 
    432     for (i = 0; i < (num_pages - num); i++) {
    433         if (((linuxInt10Priv *) pInt->private)->alloc[i] == 0) {
    434             for (j = i; j < (num + i); j++)
    435                 if ((((linuxInt10Priv *) pInt->private)->alloc[j] != 0))
    436                     break;
    437             if (j == (num + i))
    438                 break;
    439             else
    440                 i = i + num;
    441         }
    442     }
    443     if (i == (num_pages - num))
    444         return NULL;
    445 
    446     for (j = i; j < (i + num); j++)
    447         ((linuxInt10Priv *) pInt->private)->alloc[j] = 1;
    448 
    449     *off = (i + 1) * pagesize;
    450 
    451     return ((linuxInt10Priv *) pInt->private)->base + ((i + 1) * pagesize);
    452 }
    453 
    454 void
    455 xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num)
    456 {
    457     int pagesize = getpagesize();
    458     int first = (((unsigned long) pbase
    459                   - (unsigned long) ((linuxInt10Priv *) pInt->private)->base)
    460                  / pagesize) - 1;
    461     int i;
    462 
    463     for (i = first; i < (first + num); i++)
    464         ((linuxInt10Priv *) pInt->private)->alloc[i] = 0;
    465 }
    466 
    467 static CARD8
    468 read_b(xf86Int10InfoPtr pInt, int addr)
    469 {
    470     return *((CARD8 *) (memType) addr);
    471 }
    472 
    473 static CARD16
    474 read_w(xf86Int10InfoPtr pInt, int addr)
    475 {
    476     return *((CARD16 *) (memType) addr);
    477 }
    478 
    479 static CARD32
    480 read_l(xf86Int10InfoPtr pInt, int addr)
    481 {
    482     return *((CARD32 *) (memType) addr);
    483 }
    484 
    485 static void
    486 write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val)
    487 {
    488     *((CARD8 *) (memType) addr) = val;
    489 }
    490 
    491 static void
    492 write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val)
    493 {
    494     *((CARD16 *) (memType) addr) = val;
    495 }
    496 
    497 static
    498     void
    499 write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val)
    500 {
    501     *((CARD32 *) (memType) addr) = val;
    502 }
    503 
    504 void *
    505 xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr)
    506 {
    507     if (addr < V_RAM)
    508         return ((linuxInt10Priv *) pInt->private)->base + addr;
    509     else if (addr < V_BIOS)
    510         return (void *) (memType) addr;
    511     else if (addr < SYS_BIOS) {
    512         if (((linuxInt10Priv *) pInt->private)->base_high)
    513             return (void *) (((linuxInt10Priv *) pInt->private)->base_high
    514                               - V_BIOS + addr);
    515         else
    516             return (void *) (memType) addr;
    517     }
    518     else
    519         return (void *) (memType) addr;
    520 }
    521 
    522 #if defined DoSubModules
    523 
    524 static Bool
    525 vm86_tst(void)
    526 {
    527     int __res;
    528 
    529 #ifdef __PIC__
    530     /* When compiling with -fPIC, we can't use asm constraint "b" because
    531        %ebx is already taken by gcc. */
    532     __asm__ __volatile__("pushl %%ebx\n\t"
    533                          "movl %2,%%ebx\n\t"
    534                          "movl %1,%%eax\n\t"
    535                          "int $0x80\n\t" "popl %%ebx":"=a"(__res)
    536                          :"n"((int) 113), "r"(NULL));
    537 #else
    538     __asm__ __volatile__("int $0x80\n\t":"=a"(__res):"a"((int) 113),
    539                          "b"((struct vm86_struct *) NULL));
    540 #endif
    541 
    542     if (__res < 0 && __res == -ENOSYS)
    543         return FALSE;
    544 
    545     return TRUE;
    546 }
    547 
    548 static Int10LinuxSubModuleState
    549 int10LinuxLoadSubModule(ScrnInfoPtr pScrn)
    550 {
    551     if (vm86_tst()) {
    552         if (xf86LoadSubModule(pScrn, "vm86"))
    553             return INT10_LOADED_VM86;
    554     }
    555     if (xf86LoadSubModule(pScrn, "x86emu"))
    556         return INT10_LOADED_X86EMU;
    557 
    558     return INT10_LOAD_FAILED;
    559 }
    560 
    561 #endif                          /* DoSubModules */