From c38dead3ea7e177728d90cd815cf4eead0c9f534 Mon Sep 17 00:00:00 2001 From: marha Date: Sat, 15 May 2010 16:28:11 +0000 Subject: xserver git update 15/5/2010 --- .../hw/xfree86/os-support/linux/int10/linux.c | 1088 ++++++------ xorg-server/hw/xfree86/os-support/linux/lnx_agp.c | 748 ++++----- .../hw/xfree86/os-support/linux/lnx_video.c | 1756 ++++++++++---------- 3 files changed, 1796 insertions(+), 1796 deletions(-) (limited to 'xorg-server/hw/xfree86/os-support/linux') 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 0cf3507c3..e3c8a984d 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,544 @@ -/* - * linux specific part of the int10 module - * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2008 Egbert Eich - */ -#ifdef HAVE_XORG_CONFIG_H -#include -#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 -#include -#include -#include -#include -#include -#include - -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)) { - xfree(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 - - xfree(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); - xfree(((linuxInt10Priv*)pInt->private)->alloc); - xfree(pInt->private); -error0: - xfree(options); - xfree(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); - xfree(((linuxInt10Priv*)pInt->private)->alloc); - xfree(pInt->private); - xfree(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 +#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 +#include +#include +#include +#include +#include +#include + +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 */ diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c b/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c index 61437406d..3fa897366 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c @@ -1,374 +1,374 @@ -/* - * Abstraction of the AGP GART interface. - * - * This version is for Linux and Free/Open/NetBSD. - * - * Copyright © 2000 VA Linux Systems, Inc. - * Copyright © 2001 The XFree86 Project, Inc. - */ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "xf86OSpriv.h" - -#if defined(linux) -#include -#include -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) -#include -#include -#endif - -#ifndef AGP_DEVICE -#define AGP_DEVICE "/dev/agpgart" -#endif -/* AGP page size is independent of the host page size. */ -#ifndef AGP_PAGE_SIZE -#define AGP_PAGE_SIZE 4096 -#endif -#define AGPGART_MAJOR_VERSION 0 -#define AGPGART_MINOR_VERSION 99 - -static int gartFd = -1; -static int acquiredScreen = -1; -static Bool initDone = FALSE; -/* - * Close /dev/agpgart. This frees all associated memory allocated during - * this server generation. - */ -Bool -xf86GARTCloseScreen(int screenNum) -{ - if(gartFd != -1) { - close(gartFd); - acquiredScreen = -1; - gartFd = -1; - initDone = FALSE; - } - return TRUE; -} - -/* - * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called. - */ -static Bool -GARTInit(int screenNum) -{ - struct _agp_info agpinf; - - if (initDone) - return (gartFd != -1); - - initDone = TRUE; - - if (gartFd == -1) - gartFd = open(AGP_DEVICE, O_RDWR, 0); - else - return FALSE; - - if (gartFd == -1) { - xf86DrvMsg(screenNum, X_ERROR, - "GARTInit: Unable to open " AGP_DEVICE " (%s)\n", - strerror(errno)); - return FALSE; - } - - xf86AcquireGART(-1); - /* Check the kernel driver version. */ - if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { - xf86DrvMsg(screenNum, X_ERROR, - "GARTInit: AGPIOC_INFO failed (%s)\n", strerror(errno)); - close(gartFd); - gartFd = -1; - return FALSE; - } - xf86ReleaseGART(-1); - -#if defined(linux) - /* Per Dave Jones, every effort will be made to keep the - * agpgart interface backwards compatible, so allow all - * future versions. - */ - if ( -#if (AGPGART_MAJOR_VERSION > 0) /* quiet compiler */ - agpinf.version.major < AGPGART_MAJOR_VERSION || -#endif - (agpinf.version.major == AGPGART_MAJOR_VERSION && - agpinf.version.minor < AGPGART_MINOR_VERSION)) { - xf86DrvMsg(screenNum, X_ERROR, - "GARTInit: Kernel agpgart driver version is not current" - " (%d.%d vs %d.%d)\n", - agpinf.version.major, agpinf.version.minor, - AGPGART_MAJOR_VERSION, AGPGART_MINOR_VERSION); - close(gartFd); - gartFd = -1; - return FALSE; - } -#endif - - return TRUE; -} - -Bool -xf86AgpGARTSupported(void) -{ - return GARTInit(-1); -} - -AgpInfoPtr -xf86GetAGPInfo(int screenNum) -{ - struct _agp_info agpinf; - AgpInfoPtr info; - - if (!GARTInit(screenNum)) - return NULL; - - - if ((info = xcalloc(sizeof(AgpInfo), 1)) == NULL) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86GetAGPInfo: Failed to allocate AgpInfo\n"); - return NULL; - } - - memset((char*)&agpinf, 0, sizeof(agpinf)); - - if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n", - strerror(errno)); - return NULL; - } - - info->bridgeId = agpinf.bridge_id; - info->agpMode = agpinf.agp_mode; - info->base = agpinf.aper_base; - info->size = agpinf.aper_size; - info->totalPages = agpinf.pg_total; - info->systemPages = agpinf.pg_system; - info->usedPages = agpinf.pg_used; - - xf86DrvMsg(screenNum, X_INFO, "Kernel reported %zu total, %zu used\n", agpinf.pg_total, agpinf.pg_used); - - return info; -} - -/* - * XXX If multiple screens can acquire the GART, should we have a reference - * count instead of using acquiredScreen? - */ - -Bool -xf86AcquireGART(int screenNum) -{ - if (screenNum != -1 && !GARTInit(screenNum)) - return FALSE; - - if (screenNum == -1 || acquiredScreen != screenNum) { - if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) { - xf86DrvMsg(screenNum, X_WARNING, - "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n", - strerror(errno)); - return FALSE; - } - acquiredScreen = screenNum; - } - return TRUE; -} - -Bool -xf86ReleaseGART(int screenNum) -{ - if (screenNum != -1 && !GARTInit(screenNum)) - return FALSE; - - if (acquiredScreen == screenNum) { - /* - * The FreeBSD agp driver removes allocations on release. - * The Linux driver doesn't. xf86ReleaseGART() is expected - * to give up access to the GART, but not to remove any - * allocations. - */ -#if !defined(linux) - if (screenNum == -1) -#endif - { - if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) { - xf86DrvMsg(screenNum, X_WARNING, - "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n", - strerror(errno)); - return FALSE; - } - acquiredScreen = -1; - } - return TRUE; - } - return FALSE; -} - -int -xf86AllocateGARTMemory(int screenNum, unsigned long size, int type, - unsigned long *physical) -{ - struct _agp_allocate alloc; - int pages; - - /* - * Allocates "size" bytes of GART memory (rounds up to the next - * page multiple) or type "type". A handle (key) for the allocated - * memory is returned. On error, the return value is -1. - */ - - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return -1; - - pages = (size / AGP_PAGE_SIZE); - if (size % AGP_PAGE_SIZE != 0) - pages++; - - /* XXX check for pages == 0? */ - - alloc.pg_count = pages; - alloc.type = type; - - if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: " - "allocation of %d pages failed\n\t(%s)\n", pages, - strerror(errno)); - return -1; - } - - if (physical) - *physical = alloc.physical; - - return alloc.key; -} - -Bool -xf86DeallocateGARTMemory(int screenNum, int key) -{ - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return FALSE; - - if (acquiredScreen != screenNum) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86UnbindGARTMemory: AGP not acquired by this screen\n"); - return FALSE; - } - -#ifdef __linux__ - if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)key) != 0) { -#else - if (ioctl(gartFd, AGPIOC_DEALLOCATE, &key) != 0) { -#endif - xf86DrvMsg(screenNum, X_WARNING,"xf86DeAllocateGARTMemory: " - "deallocation gart memory with key %d failed\n\t(%s)\n", - key, strerror(errno)); - return FALSE; - } - - return TRUE; -} - -/* Bind GART memory with "key" at "offset" */ -Bool -xf86BindGARTMemory(int screenNum, int key, unsigned long offset) -{ - struct _agp_bind bind; - int pageOffset; - - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return FALSE; - - if (acquiredScreen != screenNum) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86BindGARTMemory: AGP not acquired by this screen\n"); - return FALSE; - } - - if (offset % AGP_PAGE_SIZE != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " - "offset (0x%lx) is not page-aligned (%d)\n", - offset, AGP_PAGE_SIZE); - return FALSE; - } - pageOffset = offset / AGP_PAGE_SIZE; - - xf86DrvMsgVerb(screenNum, X_INFO, 3, - "xf86BindGARTMemory: bind key %d at 0x%08lx " - "(pgoffset %d)\n", key, offset, pageOffset); - - bind.pg_start = pageOffset; - bind.key = key; - - if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " - "binding of gart memory with key %d\n" - "\tat offset 0x%lx failed (%s)\n", - key, offset, strerror(errno)); - return FALSE; - } - - return TRUE; -} - - -/* Unbind GART memory with "key" */ -Bool -xf86UnbindGARTMemory(int screenNum, int key) -{ - struct _agp_unbind unbind; - - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return FALSE; - - if (acquiredScreen != screenNum) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86UnbindGARTMemory: AGP not acquired by this screen\n"); - return FALSE; - } - - unbind.priority = 0; - unbind.key = key; - - if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: " - "unbinding of gart memory with key %d " - "failed (%s)\n", key, strerror(errno)); - return FALSE; - } - - xf86DrvMsgVerb(screenNum, X_INFO, 3, - "xf86UnbindGARTMemory: unbind key %d\n", key); - - return TRUE; -} - - -/* XXX Interface may change. */ -Bool -xf86EnableAGP(int screenNum, CARD32 mode) -{ - agp_setup setup; - - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return FALSE; - - setup.agp_mode = mode; - if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: " - "AGPIOC_SETUP with mode %ld failed (%s)\n", - (unsigned long)mode, strerror(errno)); - return FALSE; - } - - return TRUE; -} - +/* + * Abstraction of the AGP GART interface. + * + * This version is for Linux and Free/Open/NetBSD. + * + * Copyright © 2000 VA Linux Systems, Inc. + * Copyright © 2001 The XFree86 Project, Inc. + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86OSpriv.h" + +#if defined(linux) +#include +#include +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +#include +#include +#endif + +#ifndef AGP_DEVICE +#define AGP_DEVICE "/dev/agpgart" +#endif +/* AGP page size is independent of the host page size. */ +#ifndef AGP_PAGE_SIZE +#define AGP_PAGE_SIZE 4096 +#endif +#define AGPGART_MAJOR_VERSION 0 +#define AGPGART_MINOR_VERSION 99 + +static int gartFd = -1; +static int acquiredScreen = -1; +static Bool initDone = FALSE; +/* + * Close /dev/agpgart. This frees all associated memory allocated during + * this server generation. + */ +Bool +xf86GARTCloseScreen(int screenNum) +{ + if(gartFd != -1) { + close(gartFd); + acquiredScreen = -1; + gartFd = -1; + initDone = FALSE; + } + return TRUE; +} + +/* + * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called. + */ +static Bool +GARTInit(int screenNum) +{ + struct _agp_info agpinf; + + if (initDone) + return (gartFd != -1); + + initDone = TRUE; + + if (gartFd == -1) + gartFd = open(AGP_DEVICE, O_RDWR, 0); + else + return FALSE; + + if (gartFd == -1) { + xf86DrvMsg(screenNum, X_ERROR, + "GARTInit: Unable to open " AGP_DEVICE " (%s)\n", + strerror(errno)); + return FALSE; + } + + xf86AcquireGART(-1); + /* Check the kernel driver version. */ + if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { + xf86DrvMsg(screenNum, X_ERROR, + "GARTInit: AGPIOC_INFO failed (%s)\n", strerror(errno)); + close(gartFd); + gartFd = -1; + return FALSE; + } + xf86ReleaseGART(-1); + +#if defined(linux) + /* Per Dave Jones, every effort will be made to keep the + * agpgart interface backwards compatible, so allow all + * future versions. + */ + if ( +#if (AGPGART_MAJOR_VERSION > 0) /* quiet compiler */ + agpinf.version.major < AGPGART_MAJOR_VERSION || +#endif + (agpinf.version.major == AGPGART_MAJOR_VERSION && + agpinf.version.minor < AGPGART_MINOR_VERSION)) { + xf86DrvMsg(screenNum, X_ERROR, + "GARTInit: Kernel agpgart driver version is not current" + " (%d.%d vs %d.%d)\n", + agpinf.version.major, agpinf.version.minor, + AGPGART_MAJOR_VERSION, AGPGART_MINOR_VERSION); + close(gartFd); + gartFd = -1; + return FALSE; + } +#endif + + return TRUE; +} + +Bool +xf86AgpGARTSupported(void) +{ + return GARTInit(-1); +} + +AgpInfoPtr +xf86GetAGPInfo(int screenNum) +{ + struct _agp_info agpinf; + AgpInfoPtr info; + + if (!GARTInit(screenNum)) + return NULL; + + + if ((info = calloc(sizeof(AgpInfo), 1)) == NULL) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86GetAGPInfo: Failed to allocate AgpInfo\n"); + return NULL; + } + + memset((char*)&agpinf, 0, sizeof(agpinf)); + + if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n", + strerror(errno)); + return NULL; + } + + info->bridgeId = agpinf.bridge_id; + info->agpMode = agpinf.agp_mode; + info->base = agpinf.aper_base; + info->size = agpinf.aper_size; + info->totalPages = agpinf.pg_total; + info->systemPages = agpinf.pg_system; + info->usedPages = agpinf.pg_used; + + xf86DrvMsg(screenNum, X_INFO, "Kernel reported %zu total, %zu used\n", agpinf.pg_total, agpinf.pg_used); + + return info; +} + +/* + * XXX If multiple screens can acquire the GART, should we have a reference + * count instead of using acquiredScreen? + */ + +Bool +xf86AcquireGART(int screenNum) +{ + if (screenNum != -1 && !GARTInit(screenNum)) + return FALSE; + + if (screenNum == -1 || acquiredScreen != screenNum) { + if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) { + xf86DrvMsg(screenNum, X_WARNING, + "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n", + strerror(errno)); + return FALSE; + } + acquiredScreen = screenNum; + } + return TRUE; +} + +Bool +xf86ReleaseGART(int screenNum) +{ + if (screenNum != -1 && !GARTInit(screenNum)) + return FALSE; + + if (acquiredScreen == screenNum) { + /* + * The FreeBSD agp driver removes allocations on release. + * The Linux driver doesn't. xf86ReleaseGART() is expected + * to give up access to the GART, but not to remove any + * allocations. + */ +#if !defined(linux) + if (screenNum == -1) +#endif + { + if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) { + xf86DrvMsg(screenNum, X_WARNING, + "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n", + strerror(errno)); + return FALSE; + } + acquiredScreen = -1; + } + return TRUE; + } + return FALSE; +} + +int +xf86AllocateGARTMemory(int screenNum, unsigned long size, int type, + unsigned long *physical) +{ + struct _agp_allocate alloc; + int pages; + + /* + * Allocates "size" bytes of GART memory (rounds up to the next + * page multiple) or type "type". A handle (key) for the allocated + * memory is returned. On error, the return value is -1. + */ + + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return -1; + + pages = (size / AGP_PAGE_SIZE); + if (size % AGP_PAGE_SIZE != 0) + pages++; + + /* XXX check for pages == 0? */ + + alloc.pg_count = pages; + alloc.type = type; + + if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: " + "allocation of %d pages failed\n\t(%s)\n", pages, + strerror(errno)); + return -1; + } + + if (physical) + *physical = alloc.physical; + + return alloc.key; +} + +Bool +xf86DeallocateGARTMemory(int screenNum, int key) +{ + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return FALSE; + + if (acquiredScreen != screenNum) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86UnbindGARTMemory: AGP not acquired by this screen\n"); + return FALSE; + } + +#ifdef __linux__ + if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)key) != 0) { +#else + if (ioctl(gartFd, AGPIOC_DEALLOCATE, &key) != 0) { +#endif + xf86DrvMsg(screenNum, X_WARNING,"xf86DeAllocateGARTMemory: " + "deallocation gart memory with key %d failed\n\t(%s)\n", + key, strerror(errno)); + return FALSE; + } + + return TRUE; +} + +/* Bind GART memory with "key" at "offset" */ +Bool +xf86BindGARTMemory(int screenNum, int key, unsigned long offset) +{ + struct _agp_bind bind; + int pageOffset; + + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return FALSE; + + if (acquiredScreen != screenNum) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86BindGARTMemory: AGP not acquired by this screen\n"); + return FALSE; + } + + if (offset % AGP_PAGE_SIZE != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " + "offset (0x%lx) is not page-aligned (%d)\n", + offset, AGP_PAGE_SIZE); + return FALSE; + } + pageOffset = offset / AGP_PAGE_SIZE; + + xf86DrvMsgVerb(screenNum, X_INFO, 3, + "xf86BindGARTMemory: bind key %d at 0x%08lx " + "(pgoffset %d)\n", key, offset, pageOffset); + + bind.pg_start = pageOffset; + bind.key = key; + + if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " + "binding of gart memory with key %d\n" + "\tat offset 0x%lx failed (%s)\n", + key, offset, strerror(errno)); + return FALSE; + } + + return TRUE; +} + + +/* Unbind GART memory with "key" */ +Bool +xf86UnbindGARTMemory(int screenNum, int key) +{ + struct _agp_unbind unbind; + + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return FALSE; + + if (acquiredScreen != screenNum) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86UnbindGARTMemory: AGP not acquired by this screen\n"); + return FALSE; + } + + unbind.priority = 0; + unbind.key = key; + + if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: " + "unbinding of gart memory with key %d " + "failed (%s)\n", key, strerror(errno)); + return FALSE; + } + + xf86DrvMsgVerb(screenNum, X_INFO, 3, + "xf86UnbindGARTMemory: unbind key %d\n", key); + + return TRUE; +} + + +/* XXX Interface may change. */ +Bool +xf86EnableAGP(int screenNum, CARD32 mode) +{ + agp_setup setup; + + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return FALSE; + + setup.agp_mode = mode; + if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: " + "AGPIOC_SETUP with mode %ld failed (%s)\n", + (unsigned long)mode, strerror(errno)); + return FALSE; + } + + return TRUE; +} + diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c index 26a17425a..a515b4080 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c @@ -1,878 +1,878 @@ -/* - * Copyright 1992 by Orest Zborowski - * Copyright 1993 by David Wexelblat - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the names of Orest Zborowski and David Wexelblat - * not be used in advertising or publicity pertaining to distribution of - * the software without specific, written prior permission. Orest Zborowski - * and David Wexelblat make no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD - * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include - -#include -#include "input.h" -#include "scrnintstr.h" - -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "xf86OSpriv.h" -#ifdef __alpha__ -#include "shared/xf86Axp.h" -#endif - -#ifdef HAS_MTRR_SUPPORT -#include -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -static Bool ExtendedEnabled = FALSE; - -#ifdef __ia64__ - -#include "compiler.h" -#include - -#elif !defined(__powerpc__) && \ - !defined(__mc68000__) && \ - !defined(__sparc__) && \ - !defined(__mips__) && \ - !defined(__arm__) - -/* - * Due to conflicts with "compiler.h", don't rely on to declare - * these. - */ -extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on); -extern int iopl(int __level); - -#endif - -#ifdef __alpha__ -# define BUS_BASE bus_base -#else -#define BUS_BASE (0) -#endif /* __alpha__ */ - -/***************************************************************************/ -/* Video Memory Mapping section */ -/***************************************************************************/ - -static pointer mapVidMem(int, unsigned long, unsigned long, int); -static void unmapVidMem(int, pointer, unsigned long); -#if defined (__alpha__) -extern void sethae(unsigned long hae); -extern unsigned long _bus_base __P ((void)) __attribute__ ((const)); -extern unsigned long _bus_base_sparse __P ((void)) __attribute__ ((const)); - -static pointer mapVidMemSparse(int, unsigned long, unsigned long, int); -extern axpDevice lnxGetAXP(void); -static void unmapVidMemSparse(int, pointer, unsigned long); -static axpDevice axpSystem = -1; -static Bool needSparse; -static unsigned long hae_thresh; -static unsigned long hae_mask; -static unsigned long bus_base; -#endif - -#ifdef HAS_MTRR_SUPPORT - -#define SPLIT_WC_REGIONS 1 - -static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType); -static void undoWC(int, pointer); - -/* The file desc for /proc/mtrr. Once opened, left opened, and the mtrr - driver will clean up when we exit. */ -#define MTRR_FD_UNOPENED (-1) /* We have yet to open /proc/mtrr */ -#define MTRR_FD_PROBLEM (-2) /* We tried to open /proc/mtrr, but had - a problem. */ -static int mtrr_fd = MTRR_FD_UNOPENED; - -/* Open /proc/mtrr. FALSE on failure. Will always fail on Linux 2.0, - and will fail on Linux 2.2 with MTRR support configured out, - so verbosity should be chosen appropriately. */ -static Bool -mtrr_open(int verbosity) -{ - /* Only report absence of /proc/mtrr once. */ - static Bool warned = FALSE; - - if (mtrr_fd == MTRR_FD_UNOPENED) { - mtrr_fd = open("/proc/mtrr", O_WRONLY); - - if (mtrr_fd < 0) - mtrr_fd = MTRR_FD_PROBLEM; - } - - if (mtrr_fd == MTRR_FD_PROBLEM) { - /* To make sure we only ever warn once, need to check - verbosity outside xf86MsgVerb */ - if (!warned && verbosity <= xf86GetVerbosity()) { - xf86MsgVerb(X_WARNING, verbosity, - "System lacks support for changing MTRRs\n"); - warned = TRUE; - } - - return FALSE; - } - else - return TRUE; -} - -/* - * We maintain a list of WC regions for each physical mapping so they can - * be undone when unmapping. - */ - -struct mtrr_wc_region { - struct mtrr_sentry sentry; - Bool added; /* added WC or removed it */ - struct mtrr_wc_region * next; -}; - - -static struct mtrr_wc_region * -mtrr_cull_wc_region(int screenNum, unsigned long base, unsigned long size, - MessageType from) -{ - /* Some BIOS writers thought that setting wc over the mmio - region of a graphics devices was a good idea. Try to fix - it. */ - - struct mtrr_gentry gent; - struct mtrr_wc_region *wcreturn = NULL, *wcr; - int count, ret=0; - - /* Linux 2.0 users should not get a warning without -verbose */ - if (!mtrr_open(2)) - return NULL; - - for (gent.regnum = 0; - ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; - gent.regnum++) { - if (gent.type != MTRR_TYPE_WRCOMB - || gent.base + gent.size <= base - || base + size <= gent.base) - continue; - - /* Found an overlapping region. Delete it. */ - - wcr = xalloc(sizeof(*wcr)); - if (!wcr) - return NULL; - wcr->sentry.base = gent.base; - wcr->sentry.size = gent.size; - wcr->sentry.type = MTRR_TYPE_WRCOMB; - wcr->added = FALSE; - - count = 3; - while (count-- && - (ret = ioctl(mtrr_fd, MTRRIOC_KILL_ENTRY, &(wcr->sentry))) < 0); - - if (ret >= 0) { - xf86DrvMsg(screenNum, from, - "Removed MMIO write-combining range " - "(0x%lx,0x%lx)\n", - (unsigned long) gent.base, (unsigned long) gent.size); - wcr->next = wcreturn; - wcreturn = wcr; - gent.regnum--; - } else { - xfree(wcr); - xf86DrvMsgVerb(screenNum, X_WARNING, 0, - "Failed to remove MMIO " - "write-combining range (0x%lx,0x%lx)\n", - gent.base, (unsigned long) gent.size); - } - } - return wcreturn; -} - - -static struct mtrr_wc_region * -mtrr_remove_offending(int screenNum, unsigned long base, unsigned long size, - MessageType from) -{ - struct mtrr_gentry gent; - struct mtrr_wc_region *wcreturn = NULL, **wcr; - - if (!mtrr_open(2)) - return NULL; - - wcr = &wcreturn; - for (gent.regnum = 0; - ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++ ) { - if (gent.type == MTRR_TYPE_WRCOMB - && ((gent.base >= base && gent.base + gent.size < base + size) || - (gent.base > base && gent.base + gent.size <= base + size))) { - *wcr = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from); - if (*wcr) gent.regnum--; - while(*wcr) { - wcr = &((*wcr)->next); - } - } - } - return wcreturn; -} - - -static struct mtrr_wc_region * -mtrr_add_wc_region(int screenNum, unsigned long base, unsigned long size, - MessageType from) -{ - struct mtrr_wc_region **wcr, *wcreturn, *curwcr; - - /* - * There can be only one.... - */ - - wcreturn = mtrr_remove_offending(screenNum, base, size, from); - wcr = &wcreturn; - while (*wcr) { - wcr = &((*wcr)->next); - } - - /* Linux 2.0 should not warn, unless the user explicitly asks for - WC. */ - - if (!mtrr_open(from == X_CONFIG ? 0 : 2)) - return wcreturn; - - *wcr = curwcr = xalloc(sizeof(**wcr)); - if (!curwcr) - return wcreturn; - - curwcr->sentry.base = base; - curwcr->sentry.size = size; - curwcr->sentry.type = MTRR_TYPE_WRCOMB; - curwcr->added = TRUE; - curwcr->next = NULL; - -#if SPLIT_WC_REGIONS - /* - * Splits up the write-combining region if it is not aligned on a - * size boundary. - */ - - { - unsigned long lbase, d_size = 1; - unsigned long n_size = size; - unsigned long n_base = base; - - for (lbase = n_base, d_size = 1; !(lbase & 1); - lbase = lbase >> 1, d_size <<= 1); - while (d_size > n_size) - d_size = d_size >> 1; - DebugF("WC_BASE: 0x%lx WC_END: 0x%lx\n",base,base+d_size-1); - n_base += d_size; - n_size -= d_size; - if (n_size) { - xf86DrvMsgVerb(screenNum,X_INFO,3,"Splitting WC range: " - "base: 0x%lx, size: 0x%lx\n",base,size); - curwcr->next = mtrr_add_wc_region(screenNum, n_base, n_size,from); - } - curwcr->sentry.size = d_size; - } - - /*****************************************************************/ -#endif /* SPLIT_WC_REGIONS */ - - if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &curwcr->sentry) >= 0) { - /* Avoid printing on every VT switch */ - if (xf86ServerIsInitialising()) { - xf86DrvMsg(screenNum, from, - "Write-combining range (0x%lx,0x%lx)\n", - base, size); - } - return wcreturn; - } - else { - *wcr = curwcr->next; - xfree(curwcr); - - /* Don't complain about the VGA region: MTRR fixed - regions aren't currently supported, but might be in - the future. */ - if ((unsigned long)base >= 0x100000) { - xf86DrvMsgVerb(screenNum, X_WARNING, 0, - "Failed to set up write-combining range " - "(0x%lx,0x%lx)\n", base, size); - } - return wcreturn; - } -} - -static void -mtrr_undo_wc_region(int screenNum, struct mtrr_wc_region *wcr) -{ - struct mtrr_wc_region *p, *prev; - - if (mtrr_fd >= 0) { - p = wcr; - while (p) { - if (p->added) - ioctl(mtrr_fd, MTRRIOC_DEL_ENTRY, &p->sentry); - prev = p; - p = p->next; - xfree(prev); - } - } -} - -static pointer -setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, - MessageType from) -{ - if (enable) - return mtrr_add_wc_region(screenNum, base, size, from); - else - return mtrr_cull_wc_region(screenNum, base, size, from); -} - -static void -undoWC(int screenNum, pointer regioninfo) -{ - mtrr_undo_wc_region(screenNum, regioninfo); -} - -#endif /* HAS_MTRR_SUPPORT */ - -void -xf86OSInitVidMem(VidMemInfoPtr pVidMem) -{ - pVidMem->linearSupported = TRUE; -#ifdef __alpha__ - if (axpSystem == -1) { - axpSystem = lnxGetAXP(); - if ((needSparse = (_bus_base_sparse() > 0))) { - hae_thresh = xf86AXPParams[axpSystem].hae_thresh; - hae_mask = xf86AXPParams[axpSystem].hae_mask; - } - bus_base = _bus_base(); - } - if (needSparse) { - xf86Msg(X_INFO,"Machine needs sparse mapping\n"); - pVidMem->mapMem = mapVidMemSparse; - pVidMem->unmapMem = unmapVidMemSparse; - } else { - xf86Msg(X_INFO,"Machine type has 8/16 bit access\n"); - pVidMem->mapMem = mapVidMem; - pVidMem->unmapMem = unmapVidMem; - } -#else - pVidMem->mapMem = mapVidMem; - pVidMem->unmapMem = unmapVidMem; -#endif /* __alpha__ */ - - -#ifdef HAS_MTRR_SUPPORT - pVidMem->setWC = setWC; - pVidMem->undoWC = undoWC; -#endif - pVidMem->initialised = TRUE; -} - -#ifdef __sparc__ -/* Basically, you simply cannot do this on Sparc. You have to do something portable - * like use /dev/fb* or mmap() on /proc/bus/pci/X/Y nodes. -DaveM - */ -static pointer mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) -{ - return NULL; -} -#else -static pointer -mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) -{ - pointer base; - int fd; - int mapflags = MAP_SHARED; - int prot; - memType realBase, alignOff; - - realBase = Base & ~(getpagesize() - 1); - alignOff = Base - realBase; - DebugF("base: %lx, realBase: %lx, alignOff: %lx \n", - Base,realBase,alignOff); - -#if defined(__ia64__) || defined(__arm__) || defined(__s390__) -#ifndef MAP_WRITECOMBINED -#define MAP_WRITECOMBINED 0x00010000 -#endif -#ifndef MAP_NONCACHED -#define MAP_NONCACHED 0x00020000 -#endif - if(flags & VIDMEM_FRAMEBUFFER) - mapflags |= MAP_WRITECOMBINED; - else - mapflags |= MAP_NONCACHED; -#endif - -#if 0 - /* this will disappear when people upgrade their kernels */ - fd = open(DEV_MEM, - ((flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR) | O_SYNC); -#else - fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); -#endif - if (fd < 0) - { - FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", - strerror(errno)); - } - - if (flags & VIDMEM_READONLY) - prot = PROT_READ; - else - prot = PROT_READ | PROT_WRITE; - - /* This requires linux-0.99.pl10 or above */ - base = mmap((caddr_t)0, Size + alignOff, prot, mapflags, fd, - (off_t)realBase + BUS_BASE); - close(fd); - if (base == MAP_FAILED) { - FatalError("xf86MapVidMem: Could not mmap framebuffer" - " (0x%08lx,0x%lx) (%s)\n", Base, Size, - strerror(errno)); - } - DebugF("base: %lx aligned base: %lx\n",base, base + alignOff); - return (char *)base + alignOff; -} -#endif /* !(__sparc__) */ - -static void -unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) -{ - memType alignOff = (memType)Base - - ((memType)Base & ~(getpagesize() - 1)); - - DebugF("alignment offset: %lx\n",alignOff); - munmap((caddr_t)((memType)Base - alignOff), (Size + alignOff)); -} - - -/***************************************************************************/ -/* I/O Permissions section */ -/***************************************************************************/ - -#if defined(__powerpc__) -volatile unsigned char *ioBase = NULL; - -#ifndef __NR_pciconfig_iobase -#define __NR_pciconfig_iobase 200 -#endif - -#endif - -Bool -xf86EnableIO(void) -{ -#if defined(__powerpc__) - int fd; - unsigned int ioBase_phys; -#endif - - if (ExtendedEnabled) - return TRUE; - -#if defined(__powerpc__) - ioBase_phys = syscall(__NR_pciconfig_iobase, 2, 0, 0); - - fd = open("/dev/mem", O_RDWR); - if (ioBase == NULL) { - ioBase = (volatile unsigned char *)mmap(0, 0x20000, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - ioBase_phys); -/* Should this be fatal or just a warning? */ -#if 0 - if (ioBase == MAP_FAILED) { - xf86Msg(X_WARNING, - "xf86EnableIOPorts: Failed to map iobase (%s)\n", - strerror(errno)); - return FALSE; - } -#endif - } - close(fd); -#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__arm__) && !defined(__m32r__) - if (ioperm(0, 1024, 1) || iopl(3)) { - if (errno == ENODEV) - ErrorF("xf86EnableIOPorts: no I/O ports found\n"); - else - FatalError("xf86EnableIOPorts: failed to set IOPL" - " for I/O (%s)\n", strerror(errno)); - return FALSE; - } -# if !defined(__alpha__) - ioperm(0x40,4,0); /* trap access to the timer chip */ - ioperm(0x60,4,0); /* trap access to the keyboard controller */ -# endif -#endif - ExtendedEnabled = TRUE; - - return TRUE; -} - -void -xf86DisableIO(void) -{ - if (!ExtendedEnabled) - return; -#if defined(__powerpc__) - munmap(ioBase, 0x20000); - ioBase = NULL; -#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__arm__) && !defined(__s390__) && !defined(__m32r__) - iopl(0); - ioperm(0, 1024, 0); -#endif - ExtendedEnabled = FALSE; - - return; -} - -#if defined (__alpha__) - -#define vuip volatile unsigned int * - -extern int readDense8(pointer Base, register unsigned long Offset); -extern int readDense16(pointer Base, register unsigned long Offset); -extern int readDense32(pointer Base, register unsigned long Offset); -extern void -writeDenseNB8(int Value, pointer Base, register unsigned long Offset); -extern void -writeDenseNB16(int Value, pointer Base, register unsigned long Offset); -extern void -writeDenseNB32(int Value, pointer Base, register unsigned long Offset); -extern void -writeDense8(int Value, pointer Base, register unsigned long Offset); -extern void -writeDense16(int Value, pointer Base, register unsigned long Offset); -extern void -writeDense32(int Value, pointer Base, register unsigned long Offset); - -static int readSparse8(pointer Base, register unsigned long Offset); -static int readSparse16(pointer Base, register unsigned long Offset); -static int readSparse32(pointer Base, register unsigned long Offset); -static void -writeSparseNB8(int Value, pointer Base, register unsigned long Offset); -static void -writeSparseNB16(int Value, pointer Base, register unsigned long Offset); -static void -writeSparseNB32(int Value, pointer Base, register unsigned long Offset); -static void -writeSparse8(int Value, pointer Base, register unsigned long Offset); -static void -writeSparse16(int Value, pointer Base, register unsigned long Offset); -static void -writeSparse32(int Value, pointer Base, register unsigned long Offset); - -#define DENSE_BASE 0x2ff00000000UL -#define SPARSE_BASE 0x30000000000UL - -static unsigned long msb_set = 0; - -static pointer -mapVidMemSparse(int ScreenNum, unsigned long Base, unsigned long Size, int flags) -{ - int fd, prot; - unsigned long ret, rets = 0; - - static Bool was_here = FALSE; - - if (!was_here) { - was_here = TRUE; - - xf86WriteMmio8 = writeSparse8; - xf86WriteMmio16 = writeSparse16; - xf86WriteMmio32 = writeSparse32; - xf86WriteMmioNB8 = writeSparseNB8; - xf86WriteMmioNB16 = writeSparseNB16; - xf86WriteMmioNB32 = writeSparseNB32; - xf86ReadMmio8 = readSparse8; - xf86ReadMmio16 = readSparse16; - xf86ReadMmio32 = readSparse32; - } - - fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); - if (fd < 0) { - FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", - strerror(errno)); - } - -#if 0 - xf86Msg(X_INFO,"mapVidMemSparse: try Base 0x%lx size 0x%lx flags 0x%x\n", - Base, Size, flags); -#endif - - if (flags & VIDMEM_READONLY) - prot = PROT_READ; - else - prot = PROT_READ | PROT_WRITE; - - /* This requirers linux-0.99.pl10 or above */ - - /* - * Always do DENSE mmap, since read32/write32 currently require it. - */ - ret = (unsigned long)mmap((caddr_t)(DENSE_BASE + Base), Size, - prot, MAP_SHARED, fd, - (off_t) (bus_base + Base)); - - /* - * Do SPARSE mmap only when MMIO and not MMIO_32BIT, or FRAMEBUFFER - * and SPARSE (which should require the use of read/write macros). - * - * By not SPARSE mmapping an 8MB framebuffer, we can save approx. 256K - * bytes worth of pagetable (32 pages). - */ - if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || - ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) - { - rets = (unsigned long)mmap((caddr_t)(SPARSE_BASE + (Base << 5)), - Size << 5, prot, MAP_SHARED, fd, - (off_t) _bus_base_sparse() + (Base << 5)); - } - - close(fd); - - if (ret == (unsigned long)MAP_FAILED) { - FatalError("xf86MapVidMemSparse: Could not (dense) mmap fb (%s)\n", - strerror(errno)); - } - - if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || - ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) - { - if (rets == (unsigned long)MAP_FAILED || - rets != (SPARSE_BASE + (Base << 5))) - { - FatalError("mapVidMemSparse: Could not (sparse) mmap fb (%s)\n", - strerror(errno)); - } - } - -#if 1 - if (rets) - xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" - " to DENSE at 0x%lx and SPARSE at 0x%lx\n", - Base, Size, ret, rets); - else - xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" - " to DENSE only at 0x%lx\n", - Base, Size, ret); - -#endif - return (pointer) ret; -} - -static void -unmapVidMemSparse(int ScreenNum, pointer Base, unsigned long Size) -{ - unsigned long Offset = (unsigned long)Base - DENSE_BASE; -#if 1 - xf86Msg(X_INFO,"unmapVidMemSparse: unmapping Base 0x%lx Size 0x%lx\n", - Base, Size); -#endif - /* Unmap DENSE always. */ - munmap((caddr_t)Base, Size); - - /* Unmap SPARSE always, and ignore error in case we did not map it. */ - munmap((caddr_t)(SPARSE_BASE + (Offset << 5)), Size << 5); -} - -static int -readSparse8(pointer Base, register unsigned long Offset) -{ - register unsigned long result, shift; - register unsigned long msb; - - mem_barrier(); - Offset += (unsigned long)Base - DENSE_BASE; - shift = (Offset & 0x3) << 3; - if (Offset >= (hae_thresh)) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - - mem_barrier(); - result = *(vuip) (SPARSE_BASE + (Offset << 5)); - result >>= shift; - return 0xffUL & result; -} - -static int -readSparse16(pointer Base, register unsigned long Offset) -{ - register unsigned long result, shift; - register unsigned long msb; - - mem_barrier(); - Offset += (unsigned long)Base - DENSE_BASE; - shift = (Offset & 0x2) << 3; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - - mem_barrier(); - result = *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))); - result >>= shift; - return 0xffffUL & result; -} - -static int -readSparse32(pointer Base, register unsigned long Offset) -{ - /* NOTE: this is really using DENSE. */ - mem_barrier(); - return *(vuip)((unsigned long)Base+(Offset)); -} - -static void -writeSparse8(int Value, pointer Base, register unsigned long Offset) -{ - register unsigned long msb; - register unsigned int b = Value & 0xffU; - - write_mem_barrier(); - Offset += (unsigned long)Base - DENSE_BASE; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - - write_mem_barrier(); - *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; -} - -static void -writeSparse16(int Value, pointer Base, register unsigned long Offset) -{ - register unsigned long msb; - register unsigned int w = Value & 0xffffU; - - write_mem_barrier(); - Offset += (unsigned long)Base - DENSE_BASE; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - - write_mem_barrier(); - *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))) = w * 0x00010001; -} - -static void -writeSparse32(int Value, pointer Base, register unsigned long Offset) -{ - /* NOTE: this is really using DENSE. */ - write_mem_barrier(); - *(vuip)((unsigned long)Base + (Offset)) = Value; - return; -} - -static void -writeSparseNB8(int Value, pointer Base, register unsigned long Offset) -{ - register unsigned long msb; - register unsigned int b = Value & 0xffU; - - Offset += (unsigned long)Base - DENSE_BASE; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; -} - -static void -writeSparseNB16(int Value, pointer Base, register unsigned long Offset) -{ - register unsigned long msb; - register unsigned int w = Value & 0xffffU; - - Offset += (unsigned long)Base - DENSE_BASE; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - *(vuip)(SPARSE_BASE+(Offset<<5)+(1<<(5-2))) = w * 0x00010001; -} - -static void -writeSparseNB32(int Value, pointer Base, register unsigned long Offset) -{ - /* NOTE: this is really using DENSE. */ - *(vuip)((unsigned long)Base + (Offset)) = Value; - return; -} - -void (*xf86WriteMmio8)(int Value, pointer Base, unsigned long Offset) - = writeDense8; -void (*xf86WriteMmio16)(int Value, pointer Base, unsigned long Offset) - = writeDense16; -void (*xf86WriteMmio32)(int Value, pointer Base, unsigned long Offset) - = writeDense32; -void (*xf86WriteMmioNB8)(int Value, pointer Base, unsigned long Offset) - = writeDenseNB8; -void (*xf86WriteMmioNB16)(int Value, pointer Base, unsigned long Offset) - = writeDenseNB16; -void (*xf86WriteMmioNB32)(int Value, pointer Base, unsigned long Offset) - = writeDenseNB32; -int (*xf86ReadMmio8)(pointer Base, unsigned long Offset) - = readDense8; -int (*xf86ReadMmio16)(pointer Base, unsigned long Offset) - = readDense16; -int (*xf86ReadMmio32)(pointer Base, unsigned long Offset) - = readDense32; - -#endif /* __alpha__ */ +/* + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by David Wexelblat + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of Orest Zborowski and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Orest Zborowski + * and David Wexelblat make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +#include +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86OSpriv.h" +#ifdef __alpha__ +#include "shared/xf86Axp.h" +#endif + +#ifdef HAS_MTRR_SUPPORT +#include +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static Bool ExtendedEnabled = FALSE; + +#ifdef __ia64__ + +#include "compiler.h" +#include + +#elif !defined(__powerpc__) && \ + !defined(__mc68000__) && \ + !defined(__sparc__) && \ + !defined(__mips__) && \ + !defined(__arm__) + +/* + * Due to conflicts with "compiler.h", don't rely on to declare + * these. + */ +extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on); +extern int iopl(int __level); + +#endif + +#ifdef __alpha__ +# define BUS_BASE bus_base +#else +#define BUS_BASE (0) +#endif /* __alpha__ */ + +/***************************************************************************/ +/* Video Memory Mapping section */ +/***************************************************************************/ + +static pointer mapVidMem(int, unsigned long, unsigned long, int); +static void unmapVidMem(int, pointer, unsigned long); +#if defined (__alpha__) +extern void sethae(unsigned long hae); +extern unsigned long _bus_base __P ((void)) __attribute__ ((const)); +extern unsigned long _bus_base_sparse __P ((void)) __attribute__ ((const)); + +static pointer mapVidMemSparse(int, unsigned long, unsigned long, int); +extern axpDevice lnxGetAXP(void); +static void unmapVidMemSparse(int, pointer, unsigned long); +static axpDevice axpSystem = -1; +static Bool needSparse; +static unsigned long hae_thresh; +static unsigned long hae_mask; +static unsigned long bus_base; +#endif + +#ifdef HAS_MTRR_SUPPORT + +#define SPLIT_WC_REGIONS 1 + +static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType); +static void undoWC(int, pointer); + +/* The file desc for /proc/mtrr. Once opened, left opened, and the mtrr + driver will clean up when we exit. */ +#define MTRR_FD_UNOPENED (-1) /* We have yet to open /proc/mtrr */ +#define MTRR_FD_PROBLEM (-2) /* We tried to open /proc/mtrr, but had + a problem. */ +static int mtrr_fd = MTRR_FD_UNOPENED; + +/* Open /proc/mtrr. FALSE on failure. Will always fail on Linux 2.0, + and will fail on Linux 2.2 with MTRR support configured out, + so verbosity should be chosen appropriately. */ +static Bool +mtrr_open(int verbosity) +{ + /* Only report absence of /proc/mtrr once. */ + static Bool warned = FALSE; + + if (mtrr_fd == MTRR_FD_UNOPENED) { + mtrr_fd = open("/proc/mtrr", O_WRONLY); + + if (mtrr_fd < 0) + mtrr_fd = MTRR_FD_PROBLEM; + } + + if (mtrr_fd == MTRR_FD_PROBLEM) { + /* To make sure we only ever warn once, need to check + verbosity outside xf86MsgVerb */ + if (!warned && verbosity <= xf86GetVerbosity()) { + xf86MsgVerb(X_WARNING, verbosity, + "System lacks support for changing MTRRs\n"); + warned = TRUE; + } + + return FALSE; + } + else + return TRUE; +} + +/* + * We maintain a list of WC regions for each physical mapping so they can + * be undone when unmapping. + */ + +struct mtrr_wc_region { + struct mtrr_sentry sentry; + Bool added; /* added WC or removed it */ + struct mtrr_wc_region * next; +}; + + +static struct mtrr_wc_region * +mtrr_cull_wc_region(int screenNum, unsigned long base, unsigned long size, + MessageType from) +{ + /* Some BIOS writers thought that setting wc over the mmio + region of a graphics devices was a good idea. Try to fix + it. */ + + struct mtrr_gentry gent; + struct mtrr_wc_region *wcreturn = NULL, *wcr; + int count, ret=0; + + /* Linux 2.0 users should not get a warning without -verbose */ + if (!mtrr_open(2)) + return NULL; + + for (gent.regnum = 0; + ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; + gent.regnum++) { + if (gent.type != MTRR_TYPE_WRCOMB + || gent.base + gent.size <= base + || base + size <= gent.base) + continue; + + /* Found an overlapping region. Delete it. */ + + wcr = malloc(sizeof(*wcr)); + if (!wcr) + return NULL; + wcr->sentry.base = gent.base; + wcr->sentry.size = gent.size; + wcr->sentry.type = MTRR_TYPE_WRCOMB; + wcr->added = FALSE; + + count = 3; + while (count-- && + (ret = ioctl(mtrr_fd, MTRRIOC_KILL_ENTRY, &(wcr->sentry))) < 0); + + if (ret >= 0) { + xf86DrvMsg(screenNum, from, + "Removed MMIO write-combining range " + "(0x%lx,0x%lx)\n", + (unsigned long) gent.base, (unsigned long) gent.size); + wcr->next = wcreturn; + wcreturn = wcr; + gent.regnum--; + } else { + free(wcr); + xf86DrvMsgVerb(screenNum, X_WARNING, 0, + "Failed to remove MMIO " + "write-combining range (0x%lx,0x%lx)\n", + gent.base, (unsigned long) gent.size); + } + } + return wcreturn; +} + + +static struct mtrr_wc_region * +mtrr_remove_offending(int screenNum, unsigned long base, unsigned long size, + MessageType from) +{ + struct mtrr_gentry gent; + struct mtrr_wc_region *wcreturn = NULL, **wcr; + + if (!mtrr_open(2)) + return NULL; + + wcr = &wcreturn; + for (gent.regnum = 0; + ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++ ) { + if (gent.type == MTRR_TYPE_WRCOMB + && ((gent.base >= base && gent.base + gent.size < base + size) || + (gent.base > base && gent.base + gent.size <= base + size))) { + *wcr = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from); + if (*wcr) gent.regnum--; + while(*wcr) { + wcr = &((*wcr)->next); + } + } + } + return wcreturn; +} + + +static struct mtrr_wc_region * +mtrr_add_wc_region(int screenNum, unsigned long base, unsigned long size, + MessageType from) +{ + struct mtrr_wc_region **wcr, *wcreturn, *curwcr; + + /* + * There can be only one.... + */ + + wcreturn = mtrr_remove_offending(screenNum, base, size, from); + wcr = &wcreturn; + while (*wcr) { + wcr = &((*wcr)->next); + } + + /* Linux 2.0 should not warn, unless the user explicitly asks for + WC. */ + + if (!mtrr_open(from == X_CONFIG ? 0 : 2)) + return wcreturn; + + *wcr = curwcr = malloc(sizeof(**wcr)); + if (!curwcr) + return wcreturn; + + curwcr->sentry.base = base; + curwcr->sentry.size = size; + curwcr->sentry.type = MTRR_TYPE_WRCOMB; + curwcr->added = TRUE; + curwcr->next = NULL; + +#if SPLIT_WC_REGIONS + /* + * Splits up the write-combining region if it is not aligned on a + * size boundary. + */ + + { + unsigned long lbase, d_size = 1; + unsigned long n_size = size; + unsigned long n_base = base; + + for (lbase = n_base, d_size = 1; !(lbase & 1); + lbase = lbase >> 1, d_size <<= 1); + while (d_size > n_size) + d_size = d_size >> 1; + DebugF("WC_BASE: 0x%lx WC_END: 0x%lx\n",base,base+d_size-1); + n_base += d_size; + n_size -= d_size; + if (n_size) { + xf86DrvMsgVerb(screenNum,X_INFO,3,"Splitting WC range: " + "base: 0x%lx, size: 0x%lx\n",base,size); + curwcr->next = mtrr_add_wc_region(screenNum, n_base, n_size,from); + } + curwcr->sentry.size = d_size; + } + + /*****************************************************************/ +#endif /* SPLIT_WC_REGIONS */ + + if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &curwcr->sentry) >= 0) { + /* Avoid printing on every VT switch */ + if (xf86ServerIsInitialising()) { + xf86DrvMsg(screenNum, from, + "Write-combining range (0x%lx,0x%lx)\n", + base, size); + } + return wcreturn; + } + else { + *wcr = curwcr->next; + free(curwcr); + + /* Don't complain about the VGA region: MTRR fixed + regions aren't currently supported, but might be in + the future. */ + if ((unsigned long)base >= 0x100000) { + xf86DrvMsgVerb(screenNum, X_WARNING, 0, + "Failed to set up write-combining range " + "(0x%lx,0x%lx)\n", base, size); + } + return wcreturn; + } +} + +static void +mtrr_undo_wc_region(int screenNum, struct mtrr_wc_region *wcr) +{ + struct mtrr_wc_region *p, *prev; + + if (mtrr_fd >= 0) { + p = wcr; + while (p) { + if (p->added) + ioctl(mtrr_fd, MTRRIOC_DEL_ENTRY, &p->sentry); + prev = p; + p = p->next; + free(prev); + } + } +} + +static pointer +setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, + MessageType from) +{ + if (enable) + return mtrr_add_wc_region(screenNum, base, size, from); + else + return mtrr_cull_wc_region(screenNum, base, size, from); +} + +static void +undoWC(int screenNum, pointer regioninfo) +{ + mtrr_undo_wc_region(screenNum, regioninfo); +} + +#endif /* HAS_MTRR_SUPPORT */ + +void +xf86OSInitVidMem(VidMemInfoPtr pVidMem) +{ + pVidMem->linearSupported = TRUE; +#ifdef __alpha__ + if (axpSystem == -1) { + axpSystem = lnxGetAXP(); + if ((needSparse = (_bus_base_sparse() > 0))) { + hae_thresh = xf86AXPParams[axpSystem].hae_thresh; + hae_mask = xf86AXPParams[axpSystem].hae_mask; + } + bus_base = _bus_base(); + } + if (needSparse) { + xf86Msg(X_INFO,"Machine needs sparse mapping\n"); + pVidMem->mapMem = mapVidMemSparse; + pVidMem->unmapMem = unmapVidMemSparse; + } else { + xf86Msg(X_INFO,"Machine type has 8/16 bit access\n"); + pVidMem->mapMem = mapVidMem; + pVidMem->unmapMem = unmapVidMem; + } +#else + pVidMem->mapMem = mapVidMem; + pVidMem->unmapMem = unmapVidMem; +#endif /* __alpha__ */ + + +#ifdef HAS_MTRR_SUPPORT + pVidMem->setWC = setWC; + pVidMem->undoWC = undoWC; +#endif + pVidMem->initialised = TRUE; +} + +#ifdef __sparc__ +/* Basically, you simply cannot do this on Sparc. You have to do something portable + * like use /dev/fb* or mmap() on /proc/bus/pci/X/Y nodes. -DaveM + */ +static pointer mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + return NULL; +} +#else +static pointer +mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + pointer base; + int fd; + int mapflags = MAP_SHARED; + int prot; + memType realBase, alignOff; + + realBase = Base & ~(getpagesize() - 1); + alignOff = Base - realBase; + DebugF("base: %lx, realBase: %lx, alignOff: %lx \n", + Base,realBase,alignOff); + +#if defined(__ia64__) || defined(__arm__) || defined(__s390__) +#ifndef MAP_WRITECOMBINED +#define MAP_WRITECOMBINED 0x00010000 +#endif +#ifndef MAP_NONCACHED +#define MAP_NONCACHED 0x00020000 +#endif + if(flags & VIDMEM_FRAMEBUFFER) + mapflags |= MAP_WRITECOMBINED; + else + mapflags |= MAP_NONCACHED; +#endif + +#if 0 + /* this will disappear when people upgrade their kernels */ + fd = open(DEV_MEM, + ((flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR) | O_SYNC); +#else + fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); +#endif + if (fd < 0) + { + FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", + strerror(errno)); + } + + if (flags & VIDMEM_READONLY) + prot = PROT_READ; + else + prot = PROT_READ | PROT_WRITE; + + /* This requires linux-0.99.pl10 or above */ + base = mmap((caddr_t)0, Size + alignOff, prot, mapflags, fd, + (off_t)realBase + BUS_BASE); + close(fd); + if (base == MAP_FAILED) { + FatalError("xf86MapVidMem: Could not mmap framebuffer" + " (0x%08lx,0x%lx) (%s)\n", Base, Size, + strerror(errno)); + } + DebugF("base: %lx aligned base: %lx\n",base, base + alignOff); + return (char *)base + alignOff; +} +#endif /* !(__sparc__) */ + +static void +unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) +{ + memType alignOff = (memType)Base + - ((memType)Base & ~(getpagesize() - 1)); + + DebugF("alignment offset: %lx\n",alignOff); + munmap((caddr_t)((memType)Base - alignOff), (Size + alignOff)); +} + + +/***************************************************************************/ +/* I/O Permissions section */ +/***************************************************************************/ + +#if defined(__powerpc__) +volatile unsigned char *ioBase = NULL; + +#ifndef __NR_pciconfig_iobase +#define __NR_pciconfig_iobase 200 +#endif + +#endif + +Bool +xf86EnableIO(void) +{ +#if defined(__powerpc__) + int fd; + unsigned int ioBase_phys; +#endif + + if (ExtendedEnabled) + return TRUE; + +#if defined(__powerpc__) + ioBase_phys = syscall(__NR_pciconfig_iobase, 2, 0, 0); + + fd = open("/dev/mem", O_RDWR); + if (ioBase == NULL) { + ioBase = (volatile unsigned char *)mmap(0, 0x20000, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, + ioBase_phys); +/* Should this be fatal or just a warning? */ +#if 0 + if (ioBase == MAP_FAILED) { + xf86Msg(X_WARNING, + "xf86EnableIOPorts: Failed to map iobase (%s)\n", + strerror(errno)); + return FALSE; + } +#endif + } + close(fd); +#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__arm__) && !defined(__m32r__) + if (ioperm(0, 1024, 1) || iopl(3)) { + if (errno == ENODEV) + ErrorF("xf86EnableIOPorts: no I/O ports found\n"); + else + FatalError("xf86EnableIOPorts: failed to set IOPL" + " for I/O (%s)\n", strerror(errno)); + return FALSE; + } +# if !defined(__alpha__) + ioperm(0x40,4,0); /* trap access to the timer chip */ + ioperm(0x60,4,0); /* trap access to the keyboard controller */ +# endif +#endif + ExtendedEnabled = TRUE; + + return TRUE; +} + +void +xf86DisableIO(void) +{ + if (!ExtendedEnabled) + return; +#if defined(__powerpc__) + munmap(ioBase, 0x20000); + ioBase = NULL; +#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__arm__) && !defined(__s390__) && !defined(__m32r__) + iopl(0); + ioperm(0, 1024, 0); +#endif + ExtendedEnabled = FALSE; + + return; +} + +#if defined (__alpha__) + +#define vuip volatile unsigned int * + +extern int readDense8(pointer Base, register unsigned long Offset); +extern int readDense16(pointer Base, register unsigned long Offset); +extern int readDense32(pointer Base, register unsigned long Offset); +extern void +writeDenseNB8(int Value, pointer Base, register unsigned long Offset); +extern void +writeDenseNB16(int Value, pointer Base, register unsigned long Offset); +extern void +writeDenseNB32(int Value, pointer Base, register unsigned long Offset); +extern void +writeDense8(int Value, pointer Base, register unsigned long Offset); +extern void +writeDense16(int Value, pointer Base, register unsigned long Offset); +extern void +writeDense32(int Value, pointer Base, register unsigned long Offset); + +static int readSparse8(pointer Base, register unsigned long Offset); +static int readSparse16(pointer Base, register unsigned long Offset); +static int readSparse32(pointer Base, register unsigned long Offset); +static void +writeSparseNB8(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseNB16(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseNB32(int Value, pointer Base, register unsigned long Offset); +static void +writeSparse8(int Value, pointer Base, register unsigned long Offset); +static void +writeSparse16(int Value, pointer Base, register unsigned long Offset); +static void +writeSparse32(int Value, pointer Base, register unsigned long Offset); + +#define DENSE_BASE 0x2ff00000000UL +#define SPARSE_BASE 0x30000000000UL + +static unsigned long msb_set = 0; + +static pointer +mapVidMemSparse(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + int fd, prot; + unsigned long ret, rets = 0; + + static Bool was_here = FALSE; + + if (!was_here) { + was_here = TRUE; + + xf86WriteMmio8 = writeSparse8; + xf86WriteMmio16 = writeSparse16; + xf86WriteMmio32 = writeSparse32; + xf86WriteMmioNB8 = writeSparseNB8; + xf86WriteMmioNB16 = writeSparseNB16; + xf86WriteMmioNB32 = writeSparseNB32; + xf86ReadMmio8 = readSparse8; + xf86ReadMmio16 = readSparse16; + xf86ReadMmio32 = readSparse32; + } + + fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); + if (fd < 0) { + FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", + strerror(errno)); + } + +#if 0 + xf86Msg(X_INFO,"mapVidMemSparse: try Base 0x%lx size 0x%lx flags 0x%x\n", + Base, Size, flags); +#endif + + if (flags & VIDMEM_READONLY) + prot = PROT_READ; + else + prot = PROT_READ | PROT_WRITE; + + /* This requirers linux-0.99.pl10 or above */ + + /* + * Always do DENSE mmap, since read32/write32 currently require it. + */ + ret = (unsigned long)mmap((caddr_t)(DENSE_BASE + Base), Size, + prot, MAP_SHARED, fd, + (off_t) (bus_base + Base)); + + /* + * Do SPARSE mmap only when MMIO and not MMIO_32BIT, or FRAMEBUFFER + * and SPARSE (which should require the use of read/write macros). + * + * By not SPARSE mmapping an 8MB framebuffer, we can save approx. 256K + * bytes worth of pagetable (32 pages). + */ + if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || + ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) + { + rets = (unsigned long)mmap((caddr_t)(SPARSE_BASE + (Base << 5)), + Size << 5, prot, MAP_SHARED, fd, + (off_t) _bus_base_sparse() + (Base << 5)); + } + + close(fd); + + if (ret == (unsigned long)MAP_FAILED) { + FatalError("xf86MapVidMemSparse: Could not (dense) mmap fb (%s)\n", + strerror(errno)); + } + + if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || + ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) + { + if (rets == (unsigned long)MAP_FAILED || + rets != (SPARSE_BASE + (Base << 5))) + { + FatalError("mapVidMemSparse: Could not (sparse) mmap fb (%s)\n", + strerror(errno)); + } + } + +#if 1 + if (rets) + xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" + " to DENSE at 0x%lx and SPARSE at 0x%lx\n", + Base, Size, ret, rets); + else + xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" + " to DENSE only at 0x%lx\n", + Base, Size, ret); + +#endif + return (pointer) ret; +} + +static void +unmapVidMemSparse(int ScreenNum, pointer Base, unsigned long Size) +{ + unsigned long Offset = (unsigned long)Base - DENSE_BASE; +#if 1 + xf86Msg(X_INFO,"unmapVidMemSparse: unmapping Base 0x%lx Size 0x%lx\n", + Base, Size); +#endif + /* Unmap DENSE always. */ + munmap((caddr_t)Base, Size); + + /* Unmap SPARSE always, and ignore error in case we did not map it. */ + munmap((caddr_t)(SPARSE_BASE + (Offset << 5)), Size << 5); +} + +static int +readSparse8(pointer Base, register unsigned long Offset) +{ + register unsigned long result, shift; + register unsigned long msb; + + mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + shift = (Offset & 0x3) << 3; + if (Offset >= (hae_thresh)) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + + mem_barrier(); + result = *(vuip) (SPARSE_BASE + (Offset << 5)); + result >>= shift; + return 0xffUL & result; +} + +static int +readSparse16(pointer Base, register unsigned long Offset) +{ + register unsigned long result, shift; + register unsigned long msb; + + mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + shift = (Offset & 0x2) << 3; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + + mem_barrier(); + result = *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))); + result >>= shift; + return 0xffffUL & result; +} + +static int +readSparse32(pointer Base, register unsigned long Offset) +{ + /* NOTE: this is really using DENSE. */ + mem_barrier(); + return *(vuip)((unsigned long)Base+(Offset)); +} + +static void +writeSparse8(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int b = Value & 0xffU; + + write_mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + + write_mem_barrier(); + *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; +} + +static void +writeSparse16(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int w = Value & 0xffffU; + + write_mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + + write_mem_barrier(); + *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))) = w * 0x00010001; +} + +static void +writeSparse32(int Value, pointer Base, register unsigned long Offset) +{ + /* NOTE: this is really using DENSE. */ + write_mem_barrier(); + *(vuip)((unsigned long)Base + (Offset)) = Value; + return; +} + +static void +writeSparseNB8(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int b = Value & 0xffU; + + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; +} + +static void +writeSparseNB16(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int w = Value & 0xffffU; + + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + *(vuip)(SPARSE_BASE+(Offset<<5)+(1<<(5-2))) = w * 0x00010001; +} + +static void +writeSparseNB32(int Value, pointer Base, register unsigned long Offset) +{ + /* NOTE: this is really using DENSE. */ + *(vuip)((unsigned long)Base + (Offset)) = Value; + return; +} + +void (*xf86WriteMmio8)(int Value, pointer Base, unsigned long Offset) + = writeDense8; +void (*xf86WriteMmio16)(int Value, pointer Base, unsigned long Offset) + = writeDense16; +void (*xf86WriteMmio32)(int Value, pointer Base, unsigned long Offset) + = writeDense32; +void (*xf86WriteMmioNB8)(int Value, pointer Base, unsigned long Offset) + = writeDenseNB8; +void (*xf86WriteMmioNB16)(int Value, pointer Base, unsigned long Offset) + = writeDenseNB16; +void (*xf86WriteMmioNB32)(int Value, pointer Base, unsigned long Offset) + = writeDenseNB32; +int (*xf86ReadMmio8)(pointer Base, unsigned long Offset) + = readDense8; +int (*xf86ReadMmio16)(pointer Base, unsigned long Offset) + = readDense16; +int (*xf86ReadMmio32)(pointer Base, unsigned long Offset) + = readDense32; + +#endif /* __alpha__ */ -- cgit v1.2.3