Home | History | Annotate | Line # | Download | only in acpi
acpi_machdep.c revision 1.1.2.2
      1 /* $NetBSD: acpi_machdep.c,v 1.1.2.2 2011/06/23 14:19:47 cherry Exp $ */
      2 
      3 /*
      4  * Copyright 2001 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed for the NetBSD Project by
     20  *	Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 /*
     39  * Machine-dependent routines for ACPICA.
     40  */
     41 
     42 #include <sys/cdefs.h>
     43 __KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.1.2.2 2011/06/23 14:19:47 cherry Exp $");
     44 
     45 #include <sys/param.h>
     46 #include <sys/systm.h>
     47 #include <sys/device.h>
     48 
     49 #include <uvm/uvm_extern.h>
     50 
     51 #include <machine/bus.h>
     52 #include <machine/cpufunc.h>
     53 
     54 #include <dev/acpi/acpica.h>
     55 #include <dev/acpi/acpivar.h>
     56 
     57 #include <machine/acpi_machdep.h>
     58 #include <machine/mpbiosvar.h>
     59 #include <machine/mpacpi.h>
     60 #include <machine/i82093reg.h>
     61 #include <machine/i82093var.h>
     62 #include <machine/pic.h>
     63 
     64 #include <dev/pci/pcivar.h>
     65 
     66 #include <dev/isa/isareg.h>
     67 #include <dev/isa/isavar.h>
     68 
     69 #include "ioapic.h"
     70 
     71 #include "acpica.h"
     72 #include "opt_mpbios.h"
     73 #include "opt_acpi.h"
     74 
     75 extern uint32_t cpus_attached;
     76 
     77 ACPI_STATUS
     78 acpi_md_OsInitialize(void)
     79 {
     80 	return AE_OK;
     81 }
     82 
     83 ACPI_PHYSICAL_ADDRESS
     84 acpi_md_OsGetRootPointer(void)
     85 {
     86 	ACPI_PHYSICAL_ADDRESS PhysicalAddress;
     87 	ACPI_STATUS Status;
     88 
     89 	Status = AcpiFindRootPointer(&PhysicalAddress);
     90 
     91 	if (ACPI_FAILURE(Status))
     92 		PhysicalAddress = 0;
     93 
     94 	return PhysicalAddress;
     95 }
     96 
     97 ACPI_STATUS
     98 acpi_md_OsInstallInterruptHandler(uint32_t InterruptNumber,
     99     ACPI_OSD_HANDLER ServiceRoutine, void *Context, void **cookiep)
    100 {
    101 	void *ih;
    102 	struct pic *pic;
    103 #if NIOAPIC > 0
    104 	struct ioapic_softc *sc;
    105 #endif
    106 	int irq, pin, trigger;
    107 
    108 #if NIOAPIC > 0
    109 	/*
    110 	 * Can only match on ACPI global interrupt numbers if the ACPI
    111 	 * interrupt info was extracted, which is in the ACPI case.
    112 	 */
    113 	if (mpacpi_sci_override != NULL) {
    114 		pic = mpacpi_sci_override->ioapic;
    115 		pin = mpacpi_sci_override->ioapic_pin;
    116 		if (mpacpi_sci_override->redir & IOAPIC_REDLO_LEVEL)
    117 			trigger = IST_LEVEL;
    118 		else
    119 			trigger = IST_EDGE;
    120 		if (pic->pic_type == PIC_IOAPIC)
    121 			irq = -1;
    122 		else
    123 			irq = (int)InterruptNumber;
    124 		goto sci_override;
    125 	}
    126 #endif
    127 
    128 	/*
    129 	 * There was no ACPI interrupt source override,
    130 	 *
    131 	 * If the interrupt is handled via IOAPIC, mark it
    132 	 * as level-triggered, active low in the table.
    133 	 */
    134 
    135 #if NIOAPIC > 0
    136 	sc = ioapic_find_bybase(InterruptNumber);
    137 	if (sc != NULL) {
    138 		pic = &sc->sc_pic;
    139 		struct mp_intr_map *mip;
    140 
    141 		if (pic->pic_type == PIC_IOAPIC) {
    142 			pin = (int)InterruptNumber - pic->pic_vecbase;
    143 			irq = -1;
    144 		} else {
    145 			irq = pin = (int)InterruptNumber;
    146 		}
    147 
    148 		mip = sc->sc_pins[pin].ip_map;
    149 		if (mip) {
    150 			mip->flags &= ~3;
    151 			mip->flags |= MPS_INTPO_ACTLO;
    152 			mip->redir |= IOAPIC_REDLO_ACTLO;
    153 		}
    154 	} else
    155 #endif
    156 	{
    157 		pic = &i8259_pic;
    158 		irq = pin = (int)InterruptNumber;
    159 	}
    160 
    161 	trigger = IST_LEVEL;
    162 
    163 #if NIOAPIC > 0
    164 sci_override:
    165 #endif
    166 
    167 	/*
    168 	 * XXX probably, IPL_BIO is enough.
    169 	 */
    170 	ih = intr_establish(irq, pic, pin, trigger, IPL_TTY,
    171 	    (int (*)(void *)) ServiceRoutine, Context, false);
    172 
    173 	if (ih == NULL)
    174 		return AE_NO_MEMORY;
    175 
    176 	*cookiep = ih;
    177 
    178 	return AE_OK;
    179 }
    180 
    181 void
    182 acpi_md_OsRemoveInterruptHandler(void *cookie)
    183 {
    184 	intr_disestablish(cookie);
    185 }
    186 
    187 ACPI_STATUS
    188 acpi_md_OsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress,
    189     uint32_t Length, void **LogicalAddress)
    190 {
    191 	int rv;
    192 
    193 	rv = _x86_memio_map(x86_bus_space_mem, PhysicalAddress,
    194 	    Length, 0, (bus_space_handle_t *)LogicalAddress);
    195 
    196 	return (rv != 0) ? AE_NO_MEMORY : AE_OK;
    197 }
    198 
    199 void
    200 acpi_md_OsUnmapMemory(void *LogicalAddress, uint32_t Length)
    201 {
    202 	(void) _x86_memio_unmap(x86_bus_space_mem,
    203 	    (bus_space_handle_t)LogicalAddress, Length, NULL);
    204 }
    205 
    206 ACPI_STATUS
    207 acpi_md_OsGetPhysicalAddress(void *LogicalAddress,
    208     ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
    209 {
    210 	paddr_t pa;
    211 
    212 	if (pmap_extract(pmap_kernel(), (vaddr_t) LogicalAddress, &pa)) {
    213 		*PhysicalAddress = pa;
    214 		return AE_OK;
    215 	}
    216 
    217 	return AE_ERROR;
    218 }
    219 
    220 BOOLEAN
    221 acpi_md_OsReadable(void *Pointer, uint32_t Length)
    222 {
    223 	BOOLEAN rv = TRUE;
    224 	vaddr_t sva, eva;
    225 	pt_entry_t *pte;
    226 
    227 	sva = trunc_page((vaddr_t) Pointer);
    228 	eva = round_page((vaddr_t) Pointer + Length);
    229 
    230 	if (sva < VM_MIN_KERNEL_ADDRESS)
    231 		return FALSE;
    232 
    233 	for (; sva < eva; sva += PAGE_SIZE) {
    234 		pte = kvtopte(sva);
    235 		if ((*pte & PG_V) == 0) {
    236 			rv = FALSE;
    237 			break;
    238 		}
    239 	}
    240 
    241 	return rv;
    242 }
    243 
    244 BOOLEAN
    245 acpi_md_OsWritable(void *Pointer, uint32_t Length)
    246 {
    247 	BOOLEAN rv = FALSE;
    248 	vaddr_t sva, eva;
    249 	pt_entry_t *pte;
    250 
    251 	sva = trunc_page((vaddr_t) Pointer);
    252 	eva = round_page((vaddr_t) Pointer + Length);
    253 
    254 	if (sva < VM_MIN_KERNEL_ADDRESS)
    255 		return FALSE;
    256 
    257 	for (; sva < eva; sva += PAGE_SIZE) {
    258 		pte = kvtopte(sva);
    259 		if ((*pte & (PG_V|PG_W)) != (PG_V|PG_W)) {
    260 			rv = FALSE;
    261 			break;
    262 		}
    263 	}
    264 
    265 	return rv;
    266 }
    267 
    268 void
    269 acpi_md_OsDisableInterrupt(void)
    270 {
    271 	x86_disable_intr();
    272 }
    273 
    274 void
    275 acpi_md_OsEnableInterrupt(void)
    276 {
    277 	x86_enable_intr();
    278 }
    279 
    280 uint32_t
    281 acpi_md_ncpus(void)
    282 {
    283 	return popcount32(cpus_attached);
    284 }
    285 
    286 void
    287 acpi_md_callback(void)
    288 {
    289 #ifdef MPBIOS
    290 	if (!mpbios_scanned)
    291 #endif
    292 	mpacpi_find_interrupts(acpi_softc);
    293 
    294 #ifndef XEN
    295 	acpi_md_sleep_init();
    296 #endif
    297 }
    298