Annotation of sys/arch/i386/i386/acpi_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: acpi_machdep.c,v 1.6 2007/05/29 08:22:14 gwk Exp $ */
! 2: /*
! 3: * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
! 4: *
! 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: #include <sys/param.h>
! 19: #include <sys/systm.h>
! 20: #include <sys/kernel.h>
! 21: #include <sys/device.h>
! 22: #include <sys/malloc.h>
! 23:
! 24: #include <uvm/uvm_extern.h>
! 25:
! 26: #include <machine/bus.h>
! 27: #include <i386/isa/isa_machdep.h>
! 28:
! 29: #include <dev/isa/isareg.h>
! 30: #include <dev/acpi/acpireg.h>
! 31: #include <dev/acpi/acpivar.h>
! 32:
! 33: #include "bios.h"
! 34: #include "apm.h"
! 35:
! 36: #if NBIOS > 0
! 37: #include <machine/biosvar.h>
! 38: #endif
! 39:
! 40: #define ACPI_BIOS_RSDP_WINDOW_BASE 0xe0000
! 41: #define ACPI_BIOS_RSDP_WINDOW_SIZE 0x20000
! 42:
! 43: #if NAPM > 0 && NBIOS > 0
! 44: extern bios_apminfo_t *apm;
! 45: #endif
! 46:
! 47: u_int8_t *acpi_scan(struct acpi_mem_map *, paddr_t, size_t);
! 48:
! 49: int
! 50: acpi_map(paddr_t pa, size_t len, struct acpi_mem_map *handle)
! 51: {
! 52: paddr_t pgpa = trunc_page(pa);
! 53: paddr_t endpa = round_page(pa + len);
! 54: vaddr_t va = uvm_km_valloc(kernel_map, endpa - pgpa);
! 55:
! 56: if (va == 0)
! 57: return (ENOMEM);
! 58:
! 59: handle->baseva = va;
! 60: handle->va = (u_int8_t *)(va + (u_long)(pa & PGOFSET));
! 61: handle->vsize = endpa - pgpa;
! 62: handle->pa = pa;
! 63:
! 64: do {
! 65: pmap_kenter_pa(va, pgpa, VM_PROT_READ | VM_PROT_WRITE);
! 66: va += NBPG;
! 67: pgpa += NBPG;
! 68: } while (pgpa < endpa);
! 69:
! 70: return 0;
! 71: }
! 72:
! 73: void
! 74: acpi_unmap(struct acpi_mem_map *handle)
! 75: {
! 76: pmap_kremove(handle->baseva, handle->vsize);
! 77: uvm_km_free(kernel_map, handle->baseva, handle->vsize);
! 78: }
! 79:
! 80: u_int8_t *
! 81: acpi_scan(struct acpi_mem_map *handle, paddr_t pa, size_t len)
! 82: {
! 83: size_t i;
! 84: u_int8_t *ptr;
! 85: struct acpi_rsdp1 *rsdp;
! 86:
! 87: if (acpi_map(pa, len, handle))
! 88: return (NULL);
! 89: for (ptr = handle->va, i = 0;
! 90: i < len;
! 91: ptr += 16, i += 16)
! 92: if (memcmp(ptr, RSDP_SIG, sizeof(RSDP_SIG) - 1) == 0) {
! 93: rsdp = (struct acpi_rsdp1 *)ptr;
! 94: /*
! 95: * Only checksum whichever portion of the
! 96: * RSDP that is actually present
! 97: */
! 98: if (rsdp->revision == 0 &&
! 99: acpi_checksum(ptr, sizeof(struct acpi_rsdp1)) == 0)
! 100: return (ptr);
! 101: else if (rsdp->revision == 2 &&
! 102: acpi_checksum(ptr, sizeof(struct acpi_rsdp)) == 0)
! 103: return (ptr);
! 104: }
! 105: acpi_unmap(handle);
! 106:
! 107: return (NULL);
! 108: }
! 109:
! 110: int
! 111: acpi_probe(struct device *parent, struct cfdata *match, struct acpi_attach_args *aaa)
! 112: {
! 113: struct acpi_mem_map handle;
! 114: u_int8_t *ptr;
! 115: paddr_t ebda;
! 116: #if NAPM > 0
! 117: extern int apm_attached;
! 118:
! 119: if (apm_attached)
! 120: return (0);
! 121: #endif
! 122: #if NBIOS > 0
! 123: {
! 124: bios_memmap_t *im;
! 125:
! 126: /*
! 127: * First look for ACPI entries in the BIOS memory map
! 128: */
! 129: for (im = bios_memmap; im->type != BIOS_MAP_END; im++)
! 130: if (im->type == BIOS_MAP_ACPI) {
! 131: if ((ptr = acpi_scan(&handle, im->addr, im->size)))
! 132: goto havebase;
! 133: }
! 134: }
! 135: #endif
! 136:
! 137: /*
! 138: * Next try to find ACPI table entries in the EBDA
! 139: */
! 140: if (acpi_map(0, NBPG, &handle))
! 141: printf("acpi: failed to map BIOS data area\n");
! 142: else {
! 143: ebda = *(const u_int16_t *)(&handle.va[0x40e]);
! 144: ebda <<= 4;
! 145: acpi_unmap(&handle);
! 146:
! 147: if (ebda && ebda < IOM_BEGIN) {
! 148: if ((ptr = acpi_scan(&handle, ebda, 1024)))
! 149: goto havebase;
! 150: }
! 151: }
! 152:
! 153: /*
! 154: * Finally try to find the ACPI table entries in the
! 155: * BIOS memory
! 156: */
! 157: if ((ptr = acpi_scan(&handle, ACPI_BIOS_RSDP_WINDOW_BASE,
! 158: ACPI_BIOS_RSDP_WINDOW_SIZE)))
! 159: goto havebase;
! 160:
! 161: return (0);
! 162:
! 163: havebase:
! 164: aaa->aaa_pbase = ptr - handle.va + handle.pa;
! 165: acpi_unmap(&handle);
! 166:
! 167: return (1);
! 168: }
! 169:
! 170: void
! 171: acpi_attach_machdep(struct acpi_softc *sc)
! 172: {
! 173: #ifdef ACPI_ENABLE
! 174: sc->sc_interrupt = isa_intr_establish(NULL, sc->sc_fadt->sci_int,
! 175: IST_LEVEL, IPL_TTY, acpi_interrupt, sc, "acpi");
! 176: #endif
! 177: }
CVSweb