summaryrefslogtreecommitdiffstats
path: root/sys/i386/cpufreq
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2007-06-17 07:18:23 +0000
committernjl <njl@FreeBSD.org>2007-06-17 07:18:23 +0000
commitfc4d01582080f5022cc83a3fc98e90193078d12e (patch)
tree9bd6767e856bbd99258dbc5e24b602e625b0e96e /sys/i386/cpufreq
parent26b1418aec0e344485edfdbd363bb6a118d8f92c (diff)
downloadFreeBSD-src-fc4d01582080f5022cc83a3fc98e90193078d12e.zip
FreeBSD-src-fc4d01582080f5022cc83a3fc98e90193078d12e.tar.gz
Use bus_dma to get a page in the first 4 GB. Since the physical address
of the magic string is passed in a 32-bit register, we can't use high memory in the PAE case. This also eliminates a use of vtophys(). Tested by: Jeff Shimbo <jts767 / gmail.com> MFC after: 1 week
Diffstat (limited to 'sys/i386/cpufreq')
-rw-r--r--sys/i386/cpufreq/smist.c87
1 files changed, 70 insertions, 17 deletions
diff --git a/sys/i386/cpufreq/smist.c b/sys/i386/cpufreq/smist.c
index 0b0c99e..2e41ed7 100644
--- a/sys/i386/cpufreq/smist.c
+++ b/sys/i386/cpufreq/smist.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/systm.h>
+#include <machine/bus.h>
#include <machine/md_var.h>
#include <machine/vm86.h>
@@ -71,6 +72,8 @@ struct smist_softc {
struct cf_setting sets[2]; /* Only two settings. */
};
+static char smist_magic[] = "Copyright (c) 1999 Intel Corporation";
+
static void smist_identify(driver_t *driver, device_t parent);
static int smist_probe(device_t dev);
static int smist_attach(device_t dev);
@@ -147,34 +150,84 @@ int15_gsic_call(int *sig, int *smi_cmd, int *command, int *smi_data, int *flags)
return (0);
}
-static int
-set_ownership(device_t dev)
-{
- int result;
- struct smist_softc *sc;
- vm_paddr_t pmagic;
- static char magic[] = "Copyright (c) 1999 Intel Corporation";
+/* Temporary structure to hold mapped page and status. */
+struct set_ownership_data {
+ int smi_cmd;
+ int command;
+ int result;
+ void *buf;
+};
- sc = device_get_softc(dev);
- if (!sc)
- return (ENXIO);
+/* Perform actual SMI call to enable SpeedStep. */
+static void
+set_ownership_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct set_ownership_data *data;
- pmagic = vtophys(magic);
+ data = arg;
+ if (error) {
+ data->result = error;
+ return;
+ }
+ /* Copy in the magic string and send it by writing to the SMI port. */
+ strlcpy(data->buf, smist_magic, PAGE_SIZE);
__asm __volatile(
"movl $-1, %%edi\n\t"
"out %%al, (%%dx)\n"
- : "=D" (result)
- : "a" (sc->command),
+ : "=D" (data->result)
+ : "a" (data->command),
"b" (0),
"c" (0),
- "d" (sc->smi_cmd),
- "S" (pmagic)
+ "d" (data->smi_cmd),
+ "S" ((uint32_t)segs[0].ds_addr)
);
+}
- DPRINT(dev, "taking ownership over BIOS return %d\n", result);
+static int
+set_ownership(device_t dev)
+{
+ struct smist_softc *sc;
+ struct set_ownership_data cb_data;
+ bus_dma_tag_t tag;
+ bus_dmamap_t map;
+
+ /*
+ * Specify the region to store the magic string. Since its address is
+ * passed to the BIOS in a 32-bit register, we have to make sure it is
+ * located in a physical page below 4 GB (i.e., for PAE.)
+ */
+ sc = device_get_softc(dev);
+ if (bus_dma_tag_create(/*parent*/ NULL,
+ /*alignment*/ PAGE_SIZE, /*no boundary*/ 0,
+ /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, /*highaddr*/ BUS_SPACE_MAXADDR,
+ NULL, NULL, /*maxsize*/ PAGE_SIZE, /*segments*/ 1,
+ /*maxsegsize*/ PAGE_SIZE, 0, busdma_lock_mutex, &Giant,
+ &tag) != 0) {
+ device_printf(dev, "can't create mem tag\n");
+ return (ENXIO);
+ }
+ if (bus_dmamem_alloc(tag, &cb_data.buf, BUS_DMA_NOWAIT, &map) != 0) {
+ bus_dma_tag_destroy(tag);
+ device_printf(dev, "can't alloc mapped mem\n");
+ return (ENXIO);
+ }
- return (result ? ENXIO : 0);
+ /* Load the physical page map and take ownership in the callback. */
+ cb_data.smi_cmd = sc->smi_cmd;
+ cb_data.command = sc->command;
+ if (bus_dmamap_load(tag, map, cb_data.buf, PAGE_SIZE, set_ownership_cb,
+ &cb_data, BUS_DMA_NOWAIT) != 0) {
+ bus_dmamem_free(tag, cb_data.buf, map);
+ bus_dma_tag_destroy(tag);
+ device_printf(dev, "can't load mem\n");
+ return (ENXIO);
+ };
+ DPRINT(dev, "taking ownership over BIOS return %d\n", cb_data.result);
+ bus_dmamap_unload(tag, map);
+ bus_dmamem_free(tag, cb_data.buf, map);
+ bus_dma_tag_destroy(tag);
+ return (cb_data.result ? ENXIO : 0);
}
static int
OpenPOWER on IntegriCloud