xserver

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

generic.c (12175B)


      1 /*
      2  *                   XFree86 int10 module
      3  *   execute BIOS int 10h calls in x86 real mode environment
      4  *                 Copyright 1999 Egbert Eich
      5  */
      6 #ifdef HAVE_XORG_CONFIG_H
      7 #include <xorg-config.h>
      8 #endif
      9 
     10 #include <string.h>
     11 #include <unistd.h>
     12 
     13 #include "xf86.h"
     14 #include "xf86_OSproc.h"
     15 #include "compiler.h"
     16 #define _INT10_PRIVATE
     17 #include "xf86int10.h"
     18 #include "int10Defines.h"
     19 #include "Pci.h"
     20 
     21 #define ALLOC_ENTRIES(x) ((V_RAM / x) - 1)
     22 
     23 #include <string.h>             /* needed for memmove */
     24 
     25 static __inline__ uint32_t
     26 ldl_u(uint32_t * p)
     27 {
     28     uint32_t ret;
     29 
     30     memmove(&ret, p, sizeof(*p));
     31     return ret;
     32 }
     33 
     34 static __inline__ uint16_t
     35 ldw_u(uint16_t * p)
     36 {
     37     uint16_t ret;
     38 
     39     memmove(&ret, p, sizeof(*p));
     40     return ret;
     41 }
     42 
     43 static __inline__ void
     44 stl_u(uint32_t val, uint32_t * p)
     45 {
     46     uint32_t tmp = val;
     47 
     48     memmove(p, &tmp, sizeof(*p));
     49 }
     50 
     51 static __inline__ void
     52 stw_u(uint16_t val, uint16_t * p)
     53 {
     54     uint16_t tmp = val;
     55 
     56     memmove(p, &tmp, sizeof(*p));
     57 }
     58 
     59 static uint8_t read_b(xf86Int10InfoPtr pInt, int addr);
     60 static uint16_t read_w(xf86Int10InfoPtr pInt, int addr);
     61 static uint32_t read_l(xf86Int10InfoPtr pInt, int addr);
     62 static void write_b(xf86Int10InfoPtr pInt, int addr, uint8_t val);
     63 static void write_w(xf86Int10InfoPtr pInt, int addr, uint16_t val);
     64 static void write_l(xf86Int10InfoPtr pInt, int addr, uint32_t val);
     65 
     66 /*
     67  * the emulator cannot pass a pointer to the current xf86Int10InfoRec
     68  * to the memory access functions therefore store it here.
     69  */
     70 
     71 typedef struct {
     72     int shift;
     73     int entries;
     74     void *base;
     75     void *vRam;
     76     int highMemory;
     77     void *sysMem;
     78     char *alloc;
     79 } genericInt10Priv;
     80 
     81 #define INTPriv(x) ((genericInt10Priv*)x->private)
     82 
     83 int10MemRec genericMem = {
     84     read_b,
     85     read_w,
     86     read_l,
     87     write_b,
     88     write_w,
     89     write_l
     90 };
     91 
     92 static void MapVRam(xf86Int10InfoPtr pInt);
     93 static void UnmapVRam(xf86Int10InfoPtr pInt);
     94 
     95 #ifdef _PC
     96 #define GET_HIGH_BASE(x) (((V_BIOS + (x) + getpagesize() - 1)/getpagesize()) \
     97                               * getpagesize())
     98 #endif
     99 
    100 static void *sysMem = NULL;
    101 
    102 static Bool
    103 readIntVec(struct pci_device *dev, unsigned char *buf, int len)
    104 {
    105     void *map;
    106 
    107     if (pci_device_map_legacy(dev, 0, len, 0, &map))
    108         return FALSE;
    109 
    110     memcpy(buf, map, len);
    111     pci_device_unmap_legacy(dev, map, len);
    112 
    113     return TRUE;
    114 }
    115 
    116 xf86Int10InfoPtr
    117 xf86ExtendedInitInt10(int entityIndex, int Flags)
    118 {
    119     xf86Int10InfoPtr pInt;
    120     void *base = 0;
    121     void *vbiosMem = 0;
    122     void *options = NULL;
    123     legacyVGARec vga;
    124     ScrnInfoPtr pScrn;
    125 
    126     pScrn = xf86FindScreenForEntity(entityIndex);
    127 
    128     options = xf86HandleInt10Options(pScrn, entityIndex);
    129 
    130     if (int10skip(options)) {
    131         free(options);
    132         return NULL;
    133     }
    134 
    135     pInt = (xf86Int10InfoPtr) xnfcalloc(1, sizeof(xf86Int10InfoRec));
    136     pInt->entityIndex = entityIndex;
    137     if (!xf86Int10ExecSetup(pInt))
    138         goto error0;
    139     pInt->mem = &genericMem;
    140     pInt->private = (void *) xnfcalloc(1, sizeof(genericInt10Priv));
    141     INTPriv(pInt)->alloc = (void *) xnfcalloc(1, ALLOC_ENTRIES(getpagesize()));
    142     pInt->pScrn = pScrn;
    143     base = INTPriv(pInt)->base = xnfalloc(SYS_BIOS);
    144 
    145     /* FIXME: Shouldn't this be a failure case?  Leaving dev as NULL seems like
    146      * FIXME: an error
    147      */
    148     pInt->dev = xf86GetPciInfoForEntity(entityIndex);
    149 
    150     /*
    151      * we need to map video RAM MMIO as some chipsets map mmio
    152      * registers into this range.
    153      */
    154     MapVRam(pInt);
    155 #ifdef _PC
    156     if (!sysMem)
    157         pci_device_map_legacy(pInt->dev, V_BIOS, BIOS_SIZE + SYS_BIOS - V_BIOS,
    158                               PCI_DEV_MAP_FLAG_WRITABLE, &sysMem);
    159     INTPriv(pInt)->sysMem = sysMem;
    160 
    161     if (!readIntVec(pInt->dev, base, LOW_PAGE_SIZE)) {
    162         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read int vect\n");
    163         goto error1;
    164     }
    165 
    166     /*
    167      * Retrieve everything between V_BIOS and SYS_BIOS as some system BIOSes
    168      * have executable code there.
    169      */
    170     memset((char *) base + V_BIOS, 0, SYS_BIOS - V_BIOS);
    171     INTPriv(pInt)->highMemory = V_BIOS;
    172 
    173     if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) {
    174         if (!xf86int10GetBiosSegment(pInt, (unsigned char *) sysMem - V_BIOS))
    175             goto error1;
    176 
    177         set_return_trap(pInt);
    178 
    179         pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
    180         if (!(pInt->Flags & SET_BIOS_SCRATCH))
    181             pInt->Flags &= ~RESTORE_BIOS_SCRATCH;
    182         xf86Int10SaveRestoreBIOSVars(pInt, TRUE);
    183 
    184     }
    185     else {
    186         const BusType location_type = xf86int10GetBiosLocationType(pInt);
    187         int bios_location = V_BIOS;
    188 
    189         reset_int_vect(pInt);
    190         set_return_trap(pInt);
    191 
    192         switch (location_type) {
    193         case BUS_PCI:{
    194             int err;
    195             struct pci_device *rom_device =
    196                 xf86GetPciInfoForEntity(pInt->entityIndex);
    197 
    198             vbiosMem = (unsigned char *) base + bios_location;
    199             err = pci_device_read_rom(rom_device, vbiosMem);
    200             if (err) {
    201                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read V_BIOS (3) %s\n",
    202                            strerror(err));
    203                 goto error1;
    204             }
    205             INTPriv(pInt)->highMemory = GET_HIGH_BASE(rom_device->rom_size);
    206             break;
    207         }
    208         default:
    209             goto error1;
    210         }
    211         pInt->BIOSseg = V_BIOS >> 4;
    212         pInt->num = 0xe6;
    213         LockLegacyVGA(pInt, &vga);
    214         xf86ExecX86int10(pInt);
    215         UnlockLegacyVGA(pInt, &vga);
    216     }
    217 #else
    218     if (!sysMem) {
    219         sysMem = xnfalloc(BIOS_SIZE);
    220         setup_system_bios(sysMem);
    221     }
    222     INTPriv(pInt)->sysMem = sysMem;
    223     setup_int_vect(pInt);
    224     set_return_trap(pInt);
    225 
    226     /* Retrieve the entire legacy video BIOS segment.  This can be up to
    227      * 128KiB.
    228      */
    229     vbiosMem = (char *) base + V_BIOS;
    230     memset(vbiosMem, 0, 2 * V_BIOS_SIZE);
    231     if (pci_device_read_rom(pInt->dev, vbiosMem) != 0
    232         || pInt->dev->rom_size < V_BIOS_SIZE) {
    233         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
    234                    "Unable to retrieve all of segment 0x0C0000.\n");
    235     }
    236 
    237     /*
    238      * If this adapter is the primary, use its post-init BIOS (if we can find
    239      * it).
    240      */
    241     {
    242         int bios_location = V_BIOS;
    243         Bool done = FALSE;
    244 
    245         vbiosMem = (unsigned char *) base + bios_location;
    246 
    247         if (xf86IsEntityPrimary(entityIndex)) {
    248             if (int10_check_bios(pScrn->scrnIndex, bios_location >> 4, vbiosMem))
    249                 done = TRUE;
    250             else
    251                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    252                            "No legacy BIOS found -- trying PCI\n");
    253         }
    254         if (!done) {
    255             int err;
    256             struct pci_device *rom_device =
    257                 xf86GetPciInfoForEntity(pInt->entityIndex);
    258 
    259             err = pci_device_read_rom(rom_device, vbiosMem);
    260             if (err) {
    261                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read V_BIOS (5) %s\n",
    262                            strerror(err));
    263                 goto error1;
    264             }
    265         }
    266     }
    267 
    268     pInt->BIOSseg = V_BIOS >> 4;
    269     pInt->num = 0xe6;
    270     LockLegacyVGA(pInt, &vga);
    271     xf86ExecX86int10(pInt);
    272     UnlockLegacyVGA(pInt, &vga);
    273 #endif
    274     free(options);
    275     return pInt;
    276 
    277  error1:
    278     free(base);
    279     UnmapVRam(pInt);
    280     free(INTPriv(pInt)->alloc);
    281     free(pInt->private);
    282  error0:
    283     free(pInt);
    284     free(options);
    285 
    286     return NULL;
    287 }
    288 
    289 static void
    290 MapVRam(xf86Int10InfoPtr pInt)
    291 {
    292     int pagesize = getpagesize();
    293     int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize;
    294 
    295     pci_device_map_legacy(pInt->dev, V_RAM, size, PCI_DEV_MAP_FLAG_WRITABLE,
    296                           &(INTPriv(pInt)->vRam));
    297     pInt->io = pci_legacy_open_io(pInt->dev, 0, 64 * 1024);
    298 }
    299 
    300 static void
    301 UnmapVRam(xf86Int10InfoPtr pInt)
    302 {
    303     int pagesize = getpagesize();
    304     int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize;
    305 
    306     pci_device_unmap_legacy(pInt->dev, INTPriv(pInt)->vRam, size);
    307     pci_device_close_io(pInt->dev, pInt->io);
    308     pInt->io = NULL;
    309 }
    310 
    311 Bool
    312 MapCurrentInt10(xf86Int10InfoPtr pInt)
    313 {
    314     /* nothing to do here */
    315     return TRUE;
    316 }
    317 
    318 void
    319 xf86FreeInt10(xf86Int10InfoPtr pInt)
    320 {
    321     if (!pInt)
    322         return;
    323 #if defined (_PC)
    324     xf86Int10SaveRestoreBIOSVars(pInt, FALSE);
    325 #endif
    326     if (Int10Current == pInt)
    327         Int10Current = NULL;
    328     free(INTPriv(pInt)->base);
    329     UnmapVRam(pInt);
    330     free(INTPriv(pInt)->alloc);
    331     free(pInt->private);
    332     free(pInt);
    333 }
    334 
    335 void *
    336 xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off)
    337 {
    338     int pagesize = getpagesize();
    339     int num_pages = ALLOC_ENTRIES(pagesize);
    340     int i, j;
    341 
    342     for (i = 0; i < (num_pages - num); i++) {
    343         if (INTPriv(pInt)->alloc[i] == 0) {
    344             for (j = i; j < (num + i); j++)
    345                 if (INTPriv(pInt)->alloc[j] != 0)
    346                     break;
    347             if (j == (num + i))
    348                 break;
    349             i += num;
    350         }
    351     }
    352     if (i == (num_pages - num))
    353         return NULL;
    354 
    355     for (j = i; j < (i + num); j++)
    356         INTPriv(pInt)->alloc[j] = 1;
    357 
    358     *off = (i + 1) * pagesize;
    359 
    360     return (char *) INTPriv(pInt)->base + *off;
    361 }
    362 
    363 void
    364 xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num)
    365 {
    366     int pagesize = getpagesize();
    367     int first =
    368         (((char *) pbase - (char *) INTPriv(pInt)->base) / pagesize) - 1;
    369     int i;
    370 
    371     for (i = first; i < (first + num); i++)
    372         INTPriv(pInt)->alloc[i] = 0;
    373 }
    374 
    375 #define OFF(addr) ((addr) & 0xffff)
    376 #if defined _PC
    377 #define HIGH_OFFSET (INTPriv(pInt)->highMemory)
    378 #define HIGH_BASE   V_BIOS
    379 #else
    380 #define HIGH_OFFSET SYS_BIOS
    381 #define HIGH_BASE   SYS_BIOS
    382 #endif
    383 #define SYS(addr) ((addr) >= HIGH_OFFSET)
    384 #define V_ADDR(addr) \
    385 	  (SYS(addr) ? ((char*)INTPriv(pInt)->sysMem) + (addr - HIGH_BASE) \
    386 	   : (((char*)(INTPriv(pInt)->base) + addr)))
    387 #define VRAM_ADDR(addr) (addr - V_RAM)
    388 #define VRAM_BASE (INTPriv(pInt)->vRam)
    389 
    390 #define VRAM(addr) ((addr >= V_RAM) && (addr < (V_RAM + VRAM_SIZE)))
    391 #define V_ADDR_RB(addr) \
    392 	((VRAM(addr)) ? MMIO_IN8((uint8_t*)VRAM_BASE,VRAM_ADDR(addr)) \
    393 	   : *(uint8_t*) V_ADDR(addr))
    394 #define V_ADDR_RW(addr) \
    395 	((VRAM(addr)) ? MMIO_IN16((uint16_t*)VRAM_BASE,VRAM_ADDR(addr)) \
    396 	   : ldw_u((void *)V_ADDR(addr)))
    397 #define V_ADDR_RL(addr) \
    398 	((VRAM(addr)) ? MMIO_IN32((uint32_t*)VRAM_BASE,VRAM_ADDR(addr)) \
    399 	   : ldl_u((void *)V_ADDR(addr)))
    400 
    401 #define V_ADDR_WB(addr,val) \
    402 	if(VRAM(addr)) \
    403 	    MMIO_OUT8((uint8_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
    404 	else \
    405 	    *(uint8_t*) V_ADDR(addr) = val;
    406 #define V_ADDR_WW(addr,val) \
    407 	if(VRAM(addr)) \
    408 	    MMIO_OUT16((uint16_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
    409 	else \
    410 	    stw_u((val),(void *)(V_ADDR(addr)));
    411 
    412 #define V_ADDR_WL(addr,val) \
    413 	if (VRAM(addr)) \
    414 	    MMIO_OUT32((uint32_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
    415 	else \
    416 	    stl_u(val,(void *)(V_ADDR(addr)));
    417 
    418 static uint8_t
    419 read_b(xf86Int10InfoPtr pInt, int addr)
    420 {
    421     return V_ADDR_RB(addr);
    422 }
    423 
    424 static uint16_t
    425 read_w(xf86Int10InfoPtr pInt, int addr)
    426 {
    427 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
    428     if (OFF(addr + 1) > 0)
    429         return V_ADDR_RW(addr);
    430 #endif
    431     return V_ADDR_RB(addr) | (V_ADDR_RB(addr + 1) << 8);
    432 }
    433 
    434 static uint32_t
    435 read_l(xf86Int10InfoPtr pInt, int addr)
    436 {
    437 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
    438     if (OFF(addr + 3) > 2)
    439         return V_ADDR_RL(addr);
    440 #endif
    441     return V_ADDR_RB(addr) |
    442         (V_ADDR_RB(addr + 1) << 8) |
    443         (V_ADDR_RB(addr + 2) << 16) | (V_ADDR_RB(addr + 3) << 24);
    444 }
    445 
    446 static void
    447 write_b(xf86Int10InfoPtr pInt, int addr, uint8_t val)
    448 {
    449     V_ADDR_WB(addr, val);
    450 }
    451 
    452 static void
    453 write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val)
    454 {
    455 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
    456     if (OFF(addr + 1) > 0) {
    457         V_ADDR_WW(addr, val);
    458     }
    459 #endif
    460     V_ADDR_WB(addr, val);
    461     V_ADDR_WB(addr + 1, val >> 8);
    462 }
    463 
    464 static void
    465 write_l(xf86Int10InfoPtr pInt, int addr, uint32_t val)
    466 {
    467 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
    468     if (OFF(addr + 3) > 2) {
    469         V_ADDR_WL(addr, val);
    470     }
    471 #endif
    472     V_ADDR_WB(addr, val);
    473     V_ADDR_WB(addr + 1, val >> 8);
    474     V_ADDR_WB(addr + 2, val >> 16);
    475     V_ADDR_WB(addr + 3, val >> 24);
    476 }
    477 
    478 void *
    479 xf86int10Addr(xf86Int10InfoPtr pInt, uint32_t addr)
    480 {
    481     return V_ADDR(addr);
    482 }