diff options
author | Tiago Vignatti <tiago.vignatti@nokia.com> | 2010-01-07 20:40:54 +0200 |
---|---|---|
committer | Tiago Vignatti <tiago.vignatti@nokia.com> | 2010-01-07 20:47:20 +0200 |
commit | d1497820e34ee7bcbc9bd5f628790d363b16ce5e (patch) | |
tree | f7ed6d8dce1cb66612192fc65a4cc90d4c855e3e | |
parent | 38b274187de0264a2e1310cfcd32cc52ec158e96 (diff) |
x86emu: import real-mode allocating functions from X
same idea as commit fda0acbc420efa876fc1ac9797305572f80a849f
Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com>
-rw-r--r-- | src/lrmi/backend-x86emu.c | 156 |
1 files changed, 155 insertions, 1 deletions
diff --git a/src/lrmi/backend-x86emu.c b/src/lrmi/backend-x86emu.c index 1c937d9..fa90df0 100644 --- a/src/lrmi/backend-x86emu.c +++ b/src/lrmi/backend-x86emu.c @@ -1,8 +1,10 @@ #include <stdarg.h> #include <stdio.h> #include <string.h> +#include <stdlib.h> #include <pciaccess.h> #include <inttypes.h> +#include <sys/mman.h> #include "libx86.h" #include "common.h" @@ -17,6 +19,7 @@ extern xf86Int10InfoPtr Int10Current; #define Bool int #define SHMERRORPTR (pointer)(-1) +#define ALLOC_ENTRIES(x) ((V_RAM / x) - 1) char *mmap_addr = SHMERRORPTR; static void *stack; @@ -37,6 +40,12 @@ typedef struct { } genericInt10Priv; #define INTPriv(x) ((genericInt10Priv*)x->private) +#define GET_HIGH_BASE(x) (((V_BIOS + (x) + getpagesize() - 1)/getpagesize()) \ + * getpagesize()) + +#define DEV_MEM "/dev/mem" +#include <sys/stat.h> +#include <fcntl.h> void printk(const char *fmt, ...) @@ -221,11 +230,50 @@ void x_outl(uint16_t port, uint32_t val); void x_outb(uint16_t port, uint8_t val); void x_outw(uint16_t port, uint16_t val); +/* Stolen from Xorg code */ +int +read_bios(unsigned long Base, unsigned long Offset, unsigned char *Buf, + int Len) +{ + int fd; + unsigned char *ptr; + int psize; + int mlen; + + if ((fd = open(DEV_MEM, O_RDONLY)) < 0) + { + fprintf(stderr, "xf86ReadBIOS: Failed to open %s\n", + DEV_MEM); + return(-1); + } + psize = getpagesize(); + Offset += Base & (psize - 1); + Base &= ~(psize - 1); + mlen = (Offset + Len + psize - 1) & ~(psize - 1); + ptr = (unsigned char *)mmap((caddr_t)0, mlen, PROT_READ, + MAP_SHARED, fd, (off_t)Base); + if (ptr == MAP_FAILED) + { + fprintf(stderr, "xf86ReadBIOS: %s mmap failed\n", + DEV_MEM); + close(fd); + return(-1); + } + (void)memcpy(Buf, (void *)(ptr + Offset), Len); + (void)munmap((caddr_t)ptr, mlen); + (void)close(fd); + return(Len); +} void LRMI_init(xf86Int10InfoPtr pInt) { - int i; + int i, err; + void* sysMem = NULL; + void* base = 0; + int fd; + + X86EMU_intrFuncs intFuncs[256]; X86EMU_pioFuncs pioFuncs = { (&x_inb), @@ -257,6 +305,63 @@ LRMI_init(xf86Int10InfoPtr pInt) pInt->mem = &genericMem; + if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) { + if (!sysMem) { + if ((sysMem = mmap((void *)0, BIOS_SIZE + SYS_BIOS - V_BIOS, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, fd, V_BIOS)) + == MAP_FAILED) { + fprintf(stderr, "Cannot map SYS BIOS\n"); + close(fd); + } + } + } + + pInt->private = (void *)calloc(1, sizeof(genericInt10Priv)); + INTPriv(pInt)->alloc = (void *)calloc(1, ALLOC_ENTRIES(getpagesize())); + base = INTPriv(pInt)->base = malloc(SYS_BIOS); + + /* + * we need to map video RAM MMIO as some chipsets map mmio + * registers into this range. + */ + INTPriv(pInt)->sysMem = sysMem; + + if (read_bios(0, 0, base, LOW_PAGE_SIZE) < 0) { + fprintf(stderr, "Cannot read int vect\n"); + goto error1; + } + + memset((char *)base + V_BIOS, 0, SYS_BIOS - V_BIOS); + INTPriv(pInt)->highMemory = V_BIOS; + + LRMI_set_exit_condition(pInt); + + /* + * Allocate a segment for the stack + */ + LRMI_alloc_real(pInt, 1, &pInt->stackseg); + + if (pci_device_is_boot_vga(pInt->dev)) + return; + + err = pci_device_read_rom(pInt->dev, (unsigned char *)base + V_BIOS); + if (err) { + fprintf(stderr,"Cannot read V_BIOS (3) %s\n", + strerror(err)); + goto error1; + } + INTPriv(pInt)->highMemory = GET_HIGH_BASE(pInt->dev->rom_size); + + pInt->BIOSseg = V_BIOS >> 4; + + return; + +error1: + free(base); + free(INTPriv(pInt)->alloc); + free(pInt->private); + return; #if 0 int i; @@ -282,6 +387,55 @@ LRMI_init(xf86Int10InfoPtr pInt) void LRMI_fini(xf86Int10InfoPtr pInt) { + if (!pInt) + return; + if (Int10Current == pInt) Int10Current = NULL; + + free(INTPriv(pInt)->base); + free(INTPriv(pInt)->alloc); + free(pInt->private); + free(pInt); +} + +void * +LRMI_alloc_real(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 (INTPriv(pInt)->alloc[i] == 0) { + for (j = i; j < (num + i); j++) + if (INTPriv(pInt)->alloc[j] != 0) + break; + if (j == (num + i)) + break; + i += num; + } + } + if (i == (num_pages - num)) + return NULL; + + for (j = i; j < (i + num); j++) + INTPriv(pInt)->alloc[j] = 1; + + *off = (i + 1) * pagesize; + + return (char *)INTPriv(pInt)->base + *off; +} + +void +LRMI_free_real(xf86Int10InfoPtr pInt, void *pbase, int num) +{ + int pagesize = getpagesize(); + int first = (((char *)pbase - (char *)INTPriv(pInt)->base) / pagesize) - +1; + int i; + + for (i = first; i < (first + num); i++) + INTPriv(pInt)->alloc[i] = 0; } + |