diff options
author | Jordan Crouse <jordan.crouse@amd.com> | 2007-04-11 13:37:02 -0600 |
---|---|---|
committer | Jordan Crouse <jordan.crouse@amd.com> | 2007-04-11 13:37:52 -0600 |
commit | 8bfed84a1f972325cdf61876d7f7dfd0e8f0d4d5 (patch) | |
tree | f2fc2c5527a285a0cfa4d7a843026c22c6955482 | |
parent | 2d7689990c19fd74d5fad11bcf6317a7874a6057 (diff) |
Add Linux MSR suport for LX
Extend the GX MSR support to LX - this is to support the VSAless
OFW, and share code.
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/amd.h | 4 | ||||
-rw-r--r-- | src/amd_lx_driver.c | 60 | ||||
-rw-r--r-- | src/amd_msr.c | 64 | ||||
-rw-r--r-- | src/cim/cim_defs.h | 30 | ||||
-rw-r--r-- | src/cimarron.c | 9 | ||||
-rw-r--r-- | src/durango.c | 67 |
7 files changed, 172 insertions, 63 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 02525e3..6ea5106 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,6 +46,7 @@ amd_drv_la_SOURCES = \ cim_dev.h \ amd_driver.c \ amd_common.c \ + amd_msr.c \ amd_gx_driver.c\ amd_gx_accel.c \ amd_gx_cursor.c \ @@ -478,4 +478,8 @@ void GeodePointerMoved(int index, int x, int y); void GeodeFreeScreen(int scrnIndex, int flags); int GeodeCalculatePitchBytes(unsigned int width, unsigned int bpp); +/* amd_msr.c */ +int GeodeReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi); +int GeodeWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi); + #endif /* _AMD_GEODE_H_ */ diff --git a/src/amd_lx_driver.c b/src/amd_lx_driver.c index a7b352a..e1e555b 100644 --- a/src/amd_lx_driver.c +++ b/src/amd_lx_driver.c @@ -376,6 +376,60 @@ LXSaveScreen(ScreenPtr pScrn, int mode) return TRUE; } +/* This is an overly complex MSR read mechanism */ + +/* From Cimarron - the VSAII read/write methods - we use these as fallback */ + +#define LX_MSR_READ(adr,lo,hi) \ + __asm__ __volatile__( \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ + " in %%dx, %%ax" \ + : "=a" (lo), "=d" (hi) \ + : "c" (adr)) + +#define LX_MSR_WRITE(adr,high,low) \ + { int d0, d1, d2, d3, d4; \ + __asm__ __volatile__( \ + " push %%ebx\n" \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ + " mov %6, %%ebx\n" \ + " mov %7, %0\n" \ + " mov %5, %3\n" \ + " xor %2, %2\n" \ + " xor %1, %1\n" \ + " out %%ax, %%dx\n" \ + " pop %%ebx\n" \ + : "=a"(d0),"=&D"(d1),"=&S"(d2), \ + "=c"(d3),"=d"(d4) \ + : "1"(adr),"2"(high),"3"(low)); \ + } + +static void +LXReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi) +{ + if (GeodeReadMSR(addr, lo, hi) == -1) { + unsigned int l, h; + + LX_MSR_READ(addr, l, h); + *lo = l; + *hi = h; + } +} + +static void +LXWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi) +{ + if (GeodeWriteMSR(addr, lo, hi) == -1) + LX_MSR_WRITE(addr, lo, hi); +} + + static Bool LXMapMem(ScrnInfoPtr pScrni) { @@ -419,6 +473,12 @@ LXMapMem(ScrnInfoPtr pScrni) pGeode->FBBase = cim_fb_ptr; + /* This may not be the best place to do this */ + /* Set up the MSR read/write hooks for cimarron */ + + cim_rdmsr = LXReadMSR; + cim_wrmsr = LXWriteMSR; + if (!pGeode->NoAccel) pGeode->pExa->memoryBase = pGeode->FBBase; diff --git a/src/amd_msr.c b/src/amd_msr.c new file mode 100644 index 0000000..b50134e --- /dev/null +++ b/src/amd_msr.c @@ -0,0 +1,64 @@ +#define _LARGEFILE64_SOURCE +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/errno.h> + +static int _msr_open(void) +{ + static int msrfd = 0; + + if (msrfd == 0) { + msrfd = open("/dev/cpu/0/msr", O_RDWR); + if (msrfd == -1) + ErrorF("Unable to open /dev/cpu/0/msr: %d\n", errno); + } + + return msrfd; +} + +int GeodeReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi) +{ + unsigned int data[2]; + int fd = _msr_open(); + int ret; + + if (fd == -1) + return -1; + + ret = lseek64(fd, (off64_t) addr, SEEK_SET); + + if (ret == -1) + return -1; + + ret = read(fd, (void *) data, sizeof(data)); + + if (ret != 8) + return -1; + + *hi = data[1]; + *lo = data[0]; + + return 0; +} + +int GeodeWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi) +{ + unsigned int data[2]; + int fd = _msr_open(); + + if (fd == -1) + return - 1; + + if (lseek64(fd, (off64_t) addr, SEEK_SET) == -1) + return -1; + + data[0] = lo; + data[1] = hi; + + if (write(fd, (void *) data, 8) != 8) + return -1; + + return 0; +} diff --git a/src/cim/cim_defs.h b/src/cim/cim_defs.h index 176bdb4..eea2f49 100644 --- a/src/cim/cim_defs.h +++ b/src/cim/cim_defs.h @@ -282,6 +282,33 @@ wrmsr(addr, val1, val2); \ } +#elif CIMARRON_MSR_HOOKS + + +#define MSR_READ(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long addr, val1, val2; \ + \ + addr = device_add | msr_reg; \ + if (cim_rdmsr) { \ + cim_rdmsr (addr, &val1, &val2); \ + \ + ((Q_WORD *)(data64_ptr))->high = val2; \ + ((Q_WORD *)(data64_ptr))->low = val1; \ + } \ +} + +#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long addr, val1, val2; \ + \ + val2 = ((Q_WORD *)(data64_ptr))->high; \ + val1 = ((Q_WORD *)(data64_ptr))->low; \ + \ + addr = (device_add & 0xFFFF0000) | (unsigned long)msr_reg; \ + if (cim_wrmsr) \ + cim_wrmsr(addr, val1, val2); \ +} #endif #endif /* #ifdef CIMARRON_INCLUDE_MSR_MACROS */ @@ -728,4 +755,7 @@ cim_outb(unsigned short port, unsigned char data) #endif /* CIMARRON_INCLUDE_IO_MACROS */ +extern void (*cim_rdmsr)(unsigned long, unsigned long *, unsigned long *); +extern void (*cim_wrmsr)(unsigned long, unsigned long, unsigned long); + #endif diff --git a/src/cimarron.c b/src/cimarron.c index 76d8615..52da038 100644 --- a/src/cimarron.c +++ b/src/cimarron.c @@ -132,6 +132,7 @@ #define CIMARRON_MSR_VSA_IO 0 #define CIMARRON_MSR_ABSTRACTED_ASM 1 #define CIMARRON_MSR_KERNEL_ROUTINE 0 +#define CIMARRON_MSR_HOOKS 1 #define CIMARRON_INCLUDE_IO_MACROS #define CIMARRON_IO_DIRECT_ACCESS 0 @@ -173,6 +174,14 @@ unsigned char *cim_vid_ptr = (unsigned char *)0; unsigned char *cim_vip_ptr = (unsigned char *)0; unsigned char *cim_vg_ptr = (unsigned char *)0; +/* Define hooks for reading and writing MSRs - this is a major hack + * to share the MSR code with the GX code */ + +#ifdef CIMARRON_MSR_HOOKS +void (*cim_rdmsr)(unsigned long, unsigned long *, unsigned long *); +void (*cim_wrmsr)(unsigned long, unsigned long, unsigned long); +#endif + /*----------------------------------------------------------------------*/ /* INCLUDE RELEVANT CIMARRON HEADERS */ /*----------------------------------------------------------------------*/ diff --git a/src/durango.c b/src/durango.c index 527e02b..77ba16a 100644 --- a/src/durango.c +++ b/src/durango.c @@ -177,67 +177,8 @@ gfx_outd(unsigned short port, unsigned long data) : "1"(msr | adr),"2"(*(high)),"3"(*(low))); \ } -static int lnx_msr_open(void) -{ - static int msrfd = 0; - - if (msrfd == 0) { - msrfd = open("/dev/cpu/0/msr", O_RDWR); - if (msrfd == -1) - ErrorF("Unable to open /dev/cpu/0/msr: %d\n", errno); - } - - return msrfd; -} - -/* These are the preferred method (in Linux) to read the MSRs */ - -int lnx_msr_read(unsigned long addr, unsigned long *hi, unsigned long *lo) -{ - unsigned int data[2]; - int fd = lnx_msr_open(); - int ret; - - if (fd == -1) - return - 1; - - ret = lseek64(fd, (off64_t) addr, SEEK_SET); - - if (ret == -1) { - return -1; - } - - ret = read(fd, (void *) data, sizeof(data)); - - if (ret != 8) { - return -1; - } - - *hi = data[1]; - *lo = data[0]; - - return 0; -} - -int lnx_msr_write(unsigned long addr, unsigned long *hi, unsigned long *lo) -{ - unsigned int data[2]; - int fd = lnx_msr_open(); - - if (fd == -1) - return - 1; - - if (lseek64(fd, (off64_t) addr, SEEK_SET) == -1) - return -1; - - data[0] = *lo; - data[1] = *hi; - - if (write(fd, (void *) data, 8) != 8) - return -1; - - return 0; -} +extern int GeodeWriteMSR(unsigned long, unsigned long, unsigned long); +extern int GeodeReadMSR(unsigned long, unsigned long *, unsigned long *); void gfx_msr_asm_write(unsigned short reg, unsigned long addr, unsigned long *hi, unsigned long *lo) @@ -245,7 +186,7 @@ unsigned long *hi, unsigned long *lo) static int msr_method = 0; if (msr_method == 0) { - if (!(lnx_msr_write(addr | reg, hi, lo))) + if (!GeodeWriteMSR(addr | reg, *lo, *hi)) return; msr_method = 1; @@ -261,7 +202,7 @@ unsigned long *hi, unsigned long *lo) static int msr_method = 0; if (msr_method == 0) { - if (!(lnx_msr_read(addr | reg, hi, lo))) + if (!GeodeReadMSR(addr | reg, lo, hi)) return; ErrorF("Unable to read the MSR - reverting to the VSA method.\n"); |