summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Crouse <jordan.crouse@amd.com>2007-04-11 13:37:02 -0600
committerJordan Crouse <jordan.crouse@amd.com>2007-04-11 13:37:52 -0600
commit8bfed84a1f972325cdf61876d7f7dfd0e8f0d4d5 (patch)
treef2fc2c5527a285a0cfa4d7a843026c22c6955482
parent2d7689990c19fd74d5fad11bcf6317a7874a6057 (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.am1
-rw-r--r--src/amd.h4
-rw-r--r--src/amd_lx_driver.c60
-rw-r--r--src/amd_msr.c64
-rw-r--r--src/cim/cim_defs.h30
-rw-r--r--src/cimarron.c9
-rw-r--r--src/durango.c67
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 \
diff --git a/src/amd.h b/src/amd.h
index 9691eca..5cddf9a 100644
--- a/src/amd.h
+++ b/src/amd.h
@@ -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");