From fc4d01582080f5022cc83a3fc98e90193078d12e Mon Sep 17 00:00:00 2001 From: njl Date: Sun, 17 Jun 2007 07:18:23 +0000 Subject: 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 MFC after: 1 week --- sys/i386/cpufreq/smist.c | 87 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 17 deletions(-) (limited to 'sys/i386/cpufreq') 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 #include +#include #include #include @@ -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 -- cgit v1.1