Index: sys/conf/files.i386 diff -u sys/conf/files.i386:1.1.1.1 sys/conf/files.i386:1.1.1.1.2.1 --- sys/conf/files.i386:1.1.1.1 Mon Apr 10 22:53:55 2000 +++ sys/conf/files.i386 Tue Apr 11 00:44:41 2000 @@ -131,6 +131,8 @@ gnu/i386/isa/dgm.c optional dgm gnu/i386/isa/sound/awe_wave.c optional awe i386/apm/apm.c optional apm +i386/acpi/acpi.c optional acpi +i386/acpi/ec.c optional ec acpi i386/i386/atomic.c standard \ compile-with "${CC} -c ${CFLAGS} ${DEFINED_PROF:S/^$/-fomit-frame-pointer/} ${.IMPSRC}" i386/i386/autoconf.c standard Index: sys/conf/options.i386 diff -u sys/conf/options.i386:1.1.1.1 sys/conf/options.i386:1.1.1.1.2.1 --- sys/conf/options.i386:1.1.1.1 Mon Apr 10 22:53:55 2000 +++ sys/conf/options.i386 Tue Apr 11 00:44:41 2000 @@ -196,6 +196,8 @@ # Temporary options for moving to pnpbios PNPBIOS opt_pnp.h +ACPI_DEBUG opt_acpi.h + # ------------------------------- # EOF # ------------------------------- Index: sys/dev/kbd/atkbdc.c diff -u sys/dev/kbd/atkbdc.c:1.1.1.1 sys/dev/kbd/atkbdc.c:1.1.1.1.2.1 --- sys/dev/kbd/atkbdc.c:1.1.1.1 Mon Apr 10 22:54:06 2000 +++ sys/dev/kbd/atkbdc.c Mon Apr 10 23:49:39 2000 @@ -268,6 +268,12 @@ || (read_status(kbdcp(p)) & KBDS_ANY_BUFFER_FULL)); } +/*SCI Command*/ +int kbdc_sci_ready(KBDC p) +{ + return (read_status(kbdcp(p))&KBDS_SCI_QUERY); + +} /* queuing functions */ static int Index: sys/dev/kbd/atkbdcreg.h diff -u sys/dev/kbd/atkbdcreg.h:1.1.1.1 sys/dev/kbd/atkbdcreg.h:1.1.1.1.2.1 --- sys/dev/kbd/atkbdcreg.h:1.1.1.1 Mon Apr 10 22:54:07 2000 +++ sys/dev/kbd/atkbdcreg.h Mon Apr 10 23:49:39 2000 @@ -113,6 +113,7 @@ #define KBDS_KBD_BUFFER_FULL 0x0001 #define KBDS_AUX_BUFFER_FULL 0x0021 #define KBDS_INPUT_BUFFER_FULL 0x0002 +#define KBDS_SCI_QUERY 0x0020 /* return code */ #define KBD_ACK 0x00fa @@ -221,6 +222,7 @@ KBDC atkbdc_open(int unit); int kbdc_lock(KBDC kbdc, int lock); int kbdc_data_ready(KBDC kbdc); +int kbdc_sci_ready(KBDC kbdc); int write_controller_command(KBDC kbdc,int c); int write_controller_data(KBDC kbdc,int c); Index: sys/i386/acpi/acpi.c diff -u /dev/null sys/i386/acpi/acpi.c:1.1.2.2 --- /dev/null Mon Apr 17 20:01:32 2000 +++ sys/i386/acpi/acpi.c Mon Apr 17 19:58:32 2000 @@ -0,0 +1,1739 @@ +/*- + * Copyright (c) 1999 Takanori Watanabe + * Copyright (c) 1999 Mitsuru IWASAKI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_acpi.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* + * ACPI pmap subsystem + */ +#define ACPI_SMAP_MAX_SIZE 16 + +struct ACPIaddr { + int entries; + struct { + vm_offset_t pa_base; + vm_offset_t va_base; + vm_size_t size; + u_int32_t type; + } t [ACPI_SMAP_MAX_SIZE]; +}; + +static void acpi_pmap_init(void); +static void acpi_pmap_release(void); +static vm_offset_t acpi_pmap_ptv(vm_offset_t pa); +static vm_offset_t acpi_pmap_vtp(vm_offset_t va); + +/* + * These data cannot be in acpi_softc because they should be initialized + * before probing device. + */ + +static struct ACPIaddr acpi_addr; +struct ACPIrsdp *acpi_rsdp; + +/* softc */ +typedef struct acpi_softc { + struct ACPIsdt *rsdt; + struct ACPIsdt *facp; + struct FACPbody *facp_body; + struct ACPIsdt *dsdt; + struct FACS *facs; + struct acpi_system_state_package system_state_package; + int system_state_initialized; + int ecgpe; + driver_intr_t *ecintr; + void *ecarg; +} acpi_softc_t; +static devclass_t acpi_devclass; + +/* Character device stuff */ + +static d_open_t acpiopen; +static d_close_t acpiclose; +static d_ioctl_t acpiioctl; +static d_mmap_t acpimmap; +#define CDEV_MAJOR 210 +static struct cdevsw acpi_cdevsw = { + /* open */ acpiopen, + /* close */ acpiclose, + /* read */ noread, + /* write */ nowrite, + /* ioctl */ acpiioctl, + /* poll */ nopoll, + /* mmap */ acpimmap, + /* strategy */ nostrategy, + /* name */ "acpi", + /* maj */ CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ 0, + /* bmaj */ -1 +}; + +/* Miscellous utility functions */ +static void acpi_facp_proc(acpi_softc_t *sc); +static int acpi_sdt_checksum(struct ACPIsdt * sdt); + +#define ACPI_REGISTERS_INPUT 0 +#define ACPI_REGISTERS_OUTPUT 1 +static void acpi_enable_disable(acpi_softc_t *sc, boolean_t enable); +static void acpi_io_pm1_status(acpi_softc_t *sc, boolean_t io, + u_int32_t *a, u_int32_t *b); +static void acpi_io_pm1_enable(acpi_softc_t *sc, boolean_t io, + u_int32_t *a, u_int32_t *b); +static void acpi_io_pm1_control(acpi_softc_t *sc, boolean_t io, + u_int32_t *a, u_int32_t *b); +static void acpi_io_pm2_control(acpi_softc_t *sc, boolean_t io, u_int32_t *val); +static void acpi_io_pm_timer(acpi_softc_t *sc, boolean_t io, u_int32_t *val); +static void acpi_io_gpe0_status(acpi_softc_t *sc, boolean_t io, u_int32_t *val); +static void acpi_io_gpe0_enable(acpi_softc_t *sc, boolean_t io, u_int32_t *val); +static void acpi_io_gpe1_status(acpi_softc_t *sc, boolean_t io, u_int32_t *val); +static void acpi_io_gpe1_enable(acpi_softc_t *sc, boolean_t io, u_int32_t *val); +static void acpi_registers_input(u_int32_t ioaddr, + u_int32_t *value, u_int32_t size); +static void acpi_registers_output(u_int32_t ioaddr, + u_int32_t *value, u_int32_t size); + +/* System sleeping state stuff */ +static void acpi_set_sleeping_state(acpi_softc_t *sc, u_int8_t state); +static void acpi_execute_pts(acpi_softc_t *sc, u_int8_t state); +static void acpi_execute_wak(acpi_softc_t *sc, u_int8_t state); +static void acpi_trans_sleeping_state(acpi_softc_t *sc, u_int8_t state); +static void acpi_soft_off(void *data,int howto); + +/* for debugging */ +static int acpi_debug = 0; +SYSCTL_INT(_debug, OID_AUTO, acpi_debug, CTLFLAG_RW, &acpi_debug, 1, ""); + +#define ACPIPRINTF(args...) printf("acpi0: " args) + +void +acpi_init_addr_range() +{ + acpi_addr.entries = 0; +} + +void +acpi_register_addr_range(u_int64_t base, u_int64_t size, u_int32_t type) +{ + int i; + vm_offset_t pa_base, pa_next_base; + u_int32_t ext_size; + + if (acpi_addr.entries == ACPI_SMAP_MAX_SIZE) + return; /* no room */ + + for (i = 0; i < acpi_addr.entries; i++) { + if (type != acpi_addr.t[i].type) + continue; + + pa_base = acpi_addr.t[i].pa_base; + pa_next_base = pa_base + acpi_addr.t[i].size; + + /* continuous or overlap? */ + if (base > pa_base && base <= pa_next_base) { + ext_size = size - (pa_next_base - base); + acpi_addr.t[i].size += ext_size; + return; + } + } + + i = acpi_addr.entries; + acpi_addr.t[i].pa_base = base; + acpi_addr.t[i].size = size; + acpi_addr.t[i].type = type; + acpi_addr.entries++; +} + +static void +acpi_pmap_init() +{ + int i; + vm_offset_t va; + + for (i = 0; i < acpi_addr.entries; i++) { + va = (vm_offset_t) pmap_mapdev(acpi_addr.t[i].pa_base, + acpi_addr.t[i].size); + acpi_addr.t[i].va_base = va; + ACPIPRINTF("ADDR RANGE %x %x (mapped 0x%x)\n", + acpi_addr.t[i].pa_base, acpi_addr.t[i].size, va); + } +} + +static void +acpi_pmap_release() +{ +#if 0 + int i; + + for (i = 0; i < acpi_addr.entries; i++) { + pmap_unmapdev(acpi_addr.t[i].va_base, acpi_addr.t[i].size); + } +#endif +} + +static vm_offset_t +acpi_pmap_ptv(vm_offset_t pa) +{ + int i; + vm_offset_t va = 0; + + for (i = 0; i < acpi_addr.entries; i++) { + if (pa >= acpi_addr.t[i].pa_base && + pa < acpi_addr.t[i].pa_base + acpi_addr.t[i].size) { + va = acpi_addr.t[i].va_base + pa - acpi_addr.t[i].pa_base; + return (va); + } + } + + return (va); +} + +static vm_offset_t +acpi_pmap_vtp(vm_offset_t va) +{ + int i; + vm_offset_t pa = 0; + + for (i = 0; i < acpi_addr.entries; i++) { + if (va >= acpi_addr.t[i].va_base && + va < acpi_addr.t[i].va_base + acpi_addr.t[i].size) { + pa = acpi_addr.t[i].pa_base + va - acpi_addr.t[i].va_base; + return (pa); + } + } + + return (pa); +} + +static int +acpi_sdt_checksum(struct ACPIsdt *sdt) +{ + int i; + u_char cksm = 0, *ckbf = (u_char *) sdt; + + for (i = 0; i < sdt->len; i++) + cksm += ckbf[i]; + + return ((cksm == 0) ? 0 : EINVAL); +} + +static void +acpi_facp_proc(acpi_softc_t *sc) +{ + struct ACPIsdt *facp = sc->facp, *dsdt; + struct FACPbody *body = (struct FACPbody *) facp->body; + struct FACS *facs; + + ACPIPRINTF(" FACP found\n"); + sc->facp_body = body; + dsdt = (struct ACPIsdt *) acpi_pmap_ptv(body->dsdt_ptr); + sc->dsdt = NULL; + sc->facs = NULL; + if (dsdt == NULL) { + return; + } + + if (strncmp(dsdt->signature, "DSDT", 4) == 0 && + acpi_sdt_checksum(dsdt) == 0) { + ACPIPRINTF(" DSDT found Size=%d bytes\n", dsdt->len); + sc->dsdt = dsdt; + } + + facs = (struct FACS *) acpi_pmap_ptv(body->facs_ptr); + if (facs == NULL) { + return; + } + + /* + * FACS has no checksum (modified by both OS and BIOS) and in many + * cases,It is in NVS area. + */ + if (strncmp(facs->signature, "FACS", 4) == 0) { + sc->facs = facs; + ACPIPRINTF(" FACS Found Size=%d bytes\n", facs->len); + } +} + +/* XXX should be moved to acpi.h */ +#define ACPI_PM1_ALL_ENABLE_BITS 0x0721 /* 0000 0111 0010 0001 */ +#define ACPI_PM1_TMR_EN 0x0001 +#define ACPI_PM1_GBL_EN 0x0020 +#define ACPI_PM1_PWRBTN_EN 0x0100 +#define ACPI_PM1_SLPBTN_EN 0x0200 +#define ACPI_PM1_RTC_EN 0x0400 + +/* Fixed ACPI Description Table Fixed Feature Flags (5.2.5 Table 5-6) */ +#define ACPI_FACP_FLAGS_WBINVD 0x00000001 +#define ACPI_FACP_FLAGS_WBINVD_FLUSH 0x00000002 +#define ACPI_FACP_FLAGS_PROC_C1 0x00000004 +#define ACPI_FACP_FLAGS_P_LVL2L_UP 0x00000008 +#define ACPI_FACP_FLAGS_PWR_BUTTON 0x00000010 +#define ACPI_FACP_FLAGS_SLP_BUTTON 0x00000020 +#define ACPI_FACP_FLAGS_FIX_RTC 0x00000040 +#define ACPI_FACP_FLAGS_RTC_S4 0x00000080 +#define ACPI_FACP_FLAGS_TMR_VAL_EXT 0x00000100 +#define ACPI_FACP_FLAGS_DCK_CAP 0x00000200 +/* + * System sleeping state stuff. + */ + +static void +acpi_trans_sleeping_state(acpi_softc_t *sc, u_int8_t state) +{ + u_int32_t val_a, val_b; + u_int8_t slp_typx; + + disable_intr(); + /* clear WAK_STS bit by writing a one */ + acpi_io_pm1_status(sc, ACPI_REGISTERS_INPUT, + &val_a, &val_b); + val_a = val_b = 0; + val_a |= 0x1 << 15; /* WAK_STS */ + val_b |= 0x1 << 15; /* WAK_STS */ + acpi_io_pm1_status(sc, ACPI_REGISTERS_OUTPUT, + &val_a, &val_b); + + slp_typx = sc->system_state_package.mode[state].slp_typ_a; + val_a = slp_typx << 10 | 0x1 << 13; /* SLP_TYPx | SLP_EN */ + slp_typx = sc->system_state_package.mode[state].slp_typ_b; + val_b = slp_typx << 10 | 0x1 << 13; /* SLP_TYPx | SLP_EN */ + acpi_io_pm1_control(sc, ACPI_REGISTERS_OUTPUT, + &val_a, &val_b); + enable_intr(); +} + +static void +acpi_soft_off(void *data, int howto) +{ + acpi_softc_t *sc = (acpi_softc_t *) data; + acpi_trans_sleeping_state(sc, 5); +} + +static void +acpi_set_sleeping_state(acpi_softc_t *sc, u_int8_t state) +{ + u_int8_t slp_typ_a, slp_typ_b; + + /* Prepare to sleep */ + acpi_execute_pts(sc, state); + + if (!sc->system_state_initialized) { + return; + } + + slp_typ_a = sc->system_state_package.mode[state].slp_typ_a; + slp_typ_b = sc->system_state_package.mode[state].slp_typ_b; + + if (slp_typ_a == ACPI_UNSUPPORTSLPTYP || + slp_typ_b == ACPI_UNSUPPORTSLPTYP) { + return; /* unsupported sleeping type */ + } + + /* + * XXX currently supported S1 and S5 only. + */ + switch (state) { + case 1: + acpi_trans_sleeping_state(sc, state); + acpi_execute_wak(sc, state); + break; + case 5: + /* Power the system off using ACPI */ + EVENTHANDLER_REGISTER(shutdown_final, acpi_soft_off, sc, + SHUTDOWN_PRI_LAST); + shutdown_nice(); /* XXX */ + break; + default: + break; + } +} + +static void +acpi_process_event(acpi_softc_t *sc, u_int32_t status_a, u_int32_t status_b, + u_int32_t status_0, u_int32_t status_1) +{ + if (status_a & ACPI_PM1_PWRBTN_EN || status_b & ACPI_PM1_PWRBTN_EN) { + acpi_set_sleeping_state(sc, 5); + } + + if (status_a & ACPI_PM1_SLPBTN_EN || status_b & ACPI_PM1_SLPBTN_EN) { + acpi_set_sleeping_state(sc, 1); + } +} + +static void +acpi_intr(void *data) +{ + acpi_softc_t *sc = (acpi_softc_t *) data; + u_int32_t enable_a, enable_b, enable_0, enable_1; + u_int32_t status_a, status_b, status_0, status_1; + u_int32_t val_a, val_b; + int debug = acpi_debug; /* Save debug level */ + int i; + u_int32_t bitmask; + acpi_debug = 0; /* Shut up */ + + /* Power Management 1 Status Registers */ + status_a = status_b = enable_a = enable_b = 0; + acpi_io_pm1_status(sc, ACPI_REGISTERS_INPUT, &status_a, &status_b); + /* Get Current Intrrupt Mask */ + acpi_io_pm1_enable(sc, ACPI_REGISTERS_INPUT, &enable_a, &enable_b); + /* Disable events and re-enable again */ + if ((status_a & enable_a) != 0 || (status_b & enable_b) != 0) { + acpi_debug = debug; /* OK, you can speak */ + + ACPIPRINTF("pm1_status intr CALLED\n"); + + /* Disable all intrrupt generation */ + val_a = enable_a & (~ACPI_PM1_ALL_ENABLE_BITS); + val_b = enable_b & (~ACPI_PM1_ALL_ENABLE_BITS); + acpi_io_pm1_enable(sc, ACPI_REGISTERS_OUTPUT, + &val_a, &val_b); + + /* Clear intrrupt status */ + val_a = enable_a & ACPI_PM1_ALL_ENABLE_BITS; + val_b = enable_b & ACPI_PM1_ALL_ENABLE_BITS; + acpi_io_pm1_status(sc, ACPI_REGISTERS_OUTPUT, + &val_a, &val_b); + /* Re-enable intrrupt */ + acpi_io_pm1_enable(sc, ACPI_REGISTERS_OUTPUT, + &enable_a, &enable_b); + + acpi_debug = 0; /* Shut up again */ + } + + /* General-Purpose Events 0 Status Registers */ + status_0 = enable_0 = 0; + acpi_io_gpe0_status(sc, ACPI_REGISTERS_INPUT, &status_0); + /* Get Current Intrrupt Mask */ + acpi_io_gpe0_enable(sc, ACPI_REGISTERS_INPUT, &enable_0); + /* Disable events and re-enable again */ + if ((status_0 & enable_0) != 0) { + if((sc->ecgpe != -1)&&(status_0&1<ecgpe )){ + if(sc->ecintr!=NULL){ + (*sc->ecintr)(sc->ecarg); + } + }else{ + acpi_debug = debug; /* OK, you can speak */ + + for(i=0,bitmask=1;ifacp_body->gpe0_len/2*8;i++){ + if( bitmask&status_0 ){ + ACPIPRINTF("INVOKE \\_GPE._L%02x or so\n",i); + } + bitmask=bitmask<<1; + } + } + /* Disable all intrrupt generation */ + val_a = enable_0 & ~status_0; +#if 0 + /* or should we disable all? */ + val_a = 0x0; +#endif + acpi_io_gpe0_enable(sc, ACPI_REGISTERS_OUTPUT, &val_a); + + /* Clear intrrupt status */ + val_a = enable_0; /* XXX */ + acpi_io_gpe0_status(sc, ACPI_REGISTERS_OUTPUT, &val_a); + + /* Re-enable intrrupt */ + acpi_io_gpe0_enable(sc, ACPI_REGISTERS_OUTPUT, &enable_0); + + acpi_debug = 0; /* Shut up again */ + } + + /* General-Purpose Events 1 Status Registers */ + status_1 = enable_1 = 0; + acpi_io_gpe1_status(sc, ACPI_REGISTERS_INPUT, &status_1); + /* Get Current Intrrupt Mask */ + acpi_io_gpe1_enable(sc, ACPI_REGISTERS_INPUT, &enable_1); + /* Disable events and re-enable again */ + if ((status_1 & enable_1) != 0) { + acpi_debug = debug; /* OK, you can speak */ + + ACPIPRINTF("gpe1_status intr CALLED\n"); + + /* Disable all intrrupt generation */ + val_a = enable_1 & ~status_1; +#if 0 + /* or should we disable all? */ + val_a = 0x0; +#endif + acpi_io_gpe1_enable(sc, ACPI_REGISTERS_OUTPUT, &val_a); + + /* Clear intrrupt status */ + val_a = enable_1; /* XXX */ + acpi_io_gpe1_status(sc, ACPI_REGISTERS_OUTPUT, &val_a); + + /* Re-enable intrrupt */ + acpi_io_gpe1_enable(sc, ACPI_REGISTERS_OUTPUT, &enable_1); + + acpi_debug = 0; /* Shut up again */ + } + + /* do something to handle the events... */ + acpi_process_event(sc, status_a, status_b, status_0, status_1); + + acpi_debug = debug; /* Restore debug level */ +} +/*XXX MESSY INTERFACE XXX*/ +int acpi_setup_ecintr(driver_intr_t *ecintr,void *ecarg) +{ + acpi_softc_t *sc=devclass_get_softc(acpi_devclass,0); + if(sc->ecintr!=NULL){ + return ENOMEM; + } + sc->ecintr=ecintr; + sc->ecarg=ecarg; + return 0; +} +/*This interface is go away after AML Parser comes in kernel*/ +int acpi_setup_ecgpe(int ecgpe) +{ + intrmask_t s; + u_int32_t enable_0; + acpi_softc_t *sc=devclass_get_softc(acpi_devclass,0); + s=splhigh(); + acpi_io_gpe0_enable(sc,ACPI_REGISTERS_INPUT,&enable_0); + if(sc->ecgpe!=-1) + enable_0&=~(1<ecgpe); + if(ecgpe!=-1) + enable_0|=1<ecgpe=ecgpe; + splx(s); + return 0; +} + +int acpi_acquire_global_lock() +{ + acpi_softc_t *sc=devclass_get_softc(acpi_devclass,0); + int res=0; + u_int32_t *glock; + if(sc->facs){ + glock=&sc->facs->g_lock; + /*Invoke Assembler code for mutex */ + res= ___acpi_acquire_global_lock(glock); + } + + return res; +} +int acpi_release_global_lock() +{ + acpi_softc_t *sc=devclass_get_softc(acpi_devclass,0); + int res=0; + u_int32_t *glock,cnta,cntb; + if(sc->facs){ + glock=&sc->facs->g_lock; + /*Invoke Assembler code for mutex */ + res=___acpi_release_global_lock(glock); + } + acpi_io_pm1_control(sc,ACPI_REGISTERS_INPUT,&cnta,&cntb); + cnta|=(1<<2); + acpi_io_pm1_control(sc,ACPI_REGISTERS_OUTPUT,&cnta,&cntb); + return res; +} +static void +acpi_identify(driver_t *driver, device_t parent) +{ + device_t child; + + child = BUS_ADD_CHILD(parent, 0, "acpi", 0); + + if (child == NULL) + panic("acpi_identify"); +} + + +static int +acpi_probe(device_t dev) +{ + static char oemstring[7]; + + if (acpi_rsdp == NULL) { + return (ENXIO); + } + bzero(oemstring, sizeof(oemstring)); + strncpy(oemstring, acpi_rsdp->oem, sizeof(acpi_rsdp->oem)); + + printf("ACPI: Found ACPI BIOS data at %p (<%s>, RSDT@%x)\n", + acpi_rsdp, oemstring, acpi_rsdp->addr); + + device_set_desc(dev, oemstring); +#ifdef ACPI_DEBUG + acpi_debug = 1; +#endif + return (0); +} + +static int +acpi_attach(device_t dev) +{ + acpi_softc_t *sc = device_get_softc(dev); + struct ACPIsdt *rsdt, *sdt; + struct resource *res_port, *res_irq; + int entries; + int i; + int rid; + int port, irq; + int err; + u_int32_t *ptrs; + u_int32_t status_a, status_b; + u_int32_t flags; + void *ih; + char sigstring[5]; + + acpi_pmap_init(); + + rsdt = (struct ACPIsdt *) acpi_pmap_ptv(acpi_rsdp->addr); + if (rsdt == 0) { + ACPIPRINTF("cannot map physical memory\n"); + return (ENXIO); + } + if ((strncmp(rsdt->signature, "RSDT", 4) != 0) || + (acpi_sdt_checksum(rsdt) != 0)) { + ACPIPRINTF("RSDT is broken\n"); + acpi_pmap_release(); + return (ENXIO); + } + sc->rsdt = rsdt; + sc->ecgpe=-1; /*Temporally*/ + sc->ecintr=NULL; + sc->ecarg=NULL; + entries = (rsdt->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); + ACPIPRINTF("RSDT have %d entries\n", entries); + ptrs = (u_int32_t *) & rsdt->body; + + for (i = 0; i < entries; i++) { + sdt = (struct ACPIsdt *) acpi_pmap_ptv((vm_offset_t) ptrs[i]); + bzero(sigstring, sizeof(sigstring)); + strncpy(sigstring, sdt->signature, sizeof(sdt->signature)); + ACPIPRINTF("RSDT entry%d %s\n", i, sigstring); + + if (strncmp(sdt->signature, "FACP", 4) == 0 && + acpi_sdt_checksum(sdt) == 0) { + sc->facp = sdt; + acpi_facp_proc(sc); + } + } + + /* Allocate the port range and interrupt */ + port = sc->facp_body->smi_cmd; + rid = 0; + res_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, port, port, 1, RF_ACTIVE); + + if (res_port == NULL) { + ACPIPRINTF("could not allocate port\n"); + acpi_pmap_release(); + return (ENOMEM); + } + irq = sc->facp_body->sci_int; + rid = 0; + res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, irq, 1, + RF_SHAREABLE | RF_ACTIVE); + + if (res_irq == NULL) { + bus_release_resource(dev, SYS_RES_IOPORT, 0, res_port); + acpi_pmap_release(); + return (ENOMEM); + } + err = bus_setup_intr(dev, res_irq, INTR_TYPE_MISC, + (driver_intr_t *) acpi_intr, sc, &ih); + if (err) { + ACPIPRINTF("could not setup irq, %d\n", err); + acpi_pmap_release(); + return (err); + } + + acpi_enable_disable(sc, 1); + ACPIPRINTF("at 0x%x irq %d\n", port, irq); + + /* + * Setup PM1 Enable Registers Fixed Feature Enable Bits (4.7.3.1.2) + * based on flags field of Fixed ACPI Description Table (5.2.5). + */ + acpi_io_pm1_enable(sc, ACPI_REGISTERS_INPUT, &status_a, &status_b); + flags = sc->facp_body->flags; + if ((flags & ACPI_FACP_FLAGS_PWR_BUTTON) == 0) { + status_a |= ACPI_PM1_PWRBTN_EN; + status_b |= ACPI_PM1_PWRBTN_EN; + } + if ((flags & ACPI_FACP_FLAGS_SLP_BUTTON) == 0) { + status_a |= ACPI_PM1_SLPBTN_EN; + status_b |= ACPI_PM1_SLPBTN_EN; + } + acpi_io_pm1_enable(sc, ACPI_REGISTERS_OUTPUT, &status_a, &status_b); + +#if 0 + /* + * XXX + * This should be done based on level event handlers in + * \_GPE scope (4.7.2.2.1.2). + */ + + /* try to enable all bits */ + status_a = 0xffff; + acpi_io_gpe0_enable(sc, ACPI_REGISTERS_OUTPUT, &status_a); +#endif + + /* print all event status for debugging */ + acpi_io_pm1_status(sc, ACPI_REGISTERS_INPUT, &status_a, &status_b); + acpi_io_pm1_enable(sc, ACPI_REGISTERS_INPUT, &status_a, &status_b); + acpi_io_gpe0_status(sc, ACPI_REGISTERS_INPUT, &status_a); + acpi_io_gpe0_enable(sc, ACPI_REGISTERS_INPUT, &status_a); + acpi_io_gpe1_status(sc, ACPI_REGISTERS_INPUT, &status_a); + acpi_io_gpe1_enable(sc, ACPI_REGISTERS_INPUT, &status_a); + acpi_io_pm1_control(sc, ACPI_REGISTERS_INPUT, &status_a, &status_b); + acpi_io_pm2_control(sc, ACPI_REGISTERS_INPUT, &status_a); + acpi_io_pm_timer(sc, ACPI_REGISTERS_INPUT, &status_a); + + acpi_pmap_release(); + + make_dev(&acpi_cdevsw, 0, 0, 5, 0660, "acpi"); + return (0); +} + +static device_method_t acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, acpi_identify), + DEVMETHOD(device_probe, acpi_probe), + DEVMETHOD(device_attach, acpi_attach), + + {0, 0} +}; + +static driver_t acpi_driver = { + "acpi", + acpi_methods, + sizeof(acpi_softc_t), /* no softc (XXX) */ +}; + + +DRIVER_MODULE(acpi, nexus, acpi_driver, acpi_devclass, 0, 0); + +/* + * ACPI Registers I/O + */ + +static void +acpi_registers_input(u_int32_t ioaddr, u_int32_t *value, u_int32_t size) +{ + int i; + u_int32_t val; + + val = 0; + for (i = size - 1; i >= 0; i--) { + val = (val << 8) | inb(ioaddr + i); + } + *value = val; +} + +static void +acpi_registers_output(u_int32_t ioaddr, u_int32_t *value, u_int32_t size) +{ + int i; + u_int32_t val; + + val = *value; + for (i = 0; i < size; i++) { + outb(ioaddr + i, val & 0xff); + val >>= 8; + } +} + +static void +acpi_enable_disable(acpi_softc_t *sc, boolean_t enable) +{ + struct FACPbody *facp = sc->facp_body; + u_int32_t ioaddr = facp->smi_cmd; + u_char val; + + if (enable) { + val = facp->acpi_enable; + } else { + val = facp->acpi_disable; + } + + outb(ioaddr, val); + + if (acpi_debug) { + ACPIPRINTF("acpi_enable_disable(%d) = (%x)\n", enable, val); + } +} + +static void +acpi_io_pm1_status(acpi_softc_t *sc, boolean_t io, u_int32_t *status_a, u_int32_t *status_b) +{ + struct FACPbody *facp = sc->facp_body; + int size = facp->pm1_evt_len / 2; + + if (io == ACPI_REGISTERS_INPUT) { + acpi_registers_input(facp->pm1a_evt_blk, status_a, size); + + *status_b = 0; + if (facp->pm1b_evt_blk) { + acpi_registers_input(facp->pm1b_evt_blk, status_b, size); + } + } else { + acpi_registers_output(facp->pm1a_evt_blk, status_a, size); + + if (facp->pm1b_evt_blk) { + acpi_registers_output(facp->pm1b_evt_blk, status_b, size); + } + } + + if (acpi_debug) { + ACPIPRINTF("acpi_io_pm1_status(%d) = (%x, %x)\n", + io, *status_a, *status_b); + } + + return; +} + +static void +acpi_io_pm1_enable(acpi_softc_t *sc, boolean_t io, u_int32_t *status_a, u_int32_t *status_b) +{ + struct FACPbody *facp = sc->facp_body; + int size = facp->pm1_evt_len / 2; + + if (io == ACPI_REGISTERS_INPUT) { + acpi_registers_input(facp->pm1a_evt_blk + size, status_a, size); + + *status_b = 0; + if (facp->pm1b_evt_blk) { + acpi_registers_input(facp->pm1b_evt_blk + size, status_b, size); + } + } else { + acpi_registers_output(facp->pm1a_evt_blk + size, status_a, size); + + if (facp->pm1b_evt_blk) { + acpi_registers_output(facp->pm1b_evt_blk + size, status_b, size); + } + } + + if (acpi_debug) { + ACPIPRINTF("acpi_io_pm1_enable(%d) = (%x, %x)\n", + io, *status_a, *status_b); + } + + return; +} + +static void +acpi_io_pm1_control(acpi_softc_t *sc, boolean_t io, u_int32_t *value_a, u_int32_t *value_b) +{ + struct FACPbody *facp = sc->facp_body; + int size = facp->pm1_cnt_len; + + if (io == ACPI_REGISTERS_INPUT) { + acpi_registers_input(facp->pm1a_cnt_blk, value_a, size); + + *value_b = 0; + if (facp->pm1b_evt_blk) { + acpi_registers_input(facp->pm1b_cnt_blk, value_b, size); + } + } else { + acpi_registers_output(facp->pm1a_cnt_blk, value_a, size); + + if (facp->pm1b_evt_blk) { + acpi_registers_output(facp->pm1b_cnt_blk, value_b, size); + } + } + + if (acpi_debug) { + ACPIPRINTF("acpi_io_pm1_control(%d) = (%x, %x)\n", + io, *value_a, *value_b); + } + + return; +} + +static void +acpi_io_pm2_control(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + struct FACPbody *facp = sc->facp_body; + int size = facp->pm2_cnt_len; + + if (!facp->pm2_cnt_blk) { + return; /* optional */ + } + + if (io == ACPI_REGISTERS_INPUT) { + acpi_registers_input(facp->pm2_cnt_blk, val, size); + } else { + acpi_registers_output(facp->pm2_cnt_blk, val, size); + } + + if (acpi_debug) { + ACPIPRINTF("acpi_io_pm2_control(%d) = (%x)\n", + io, *val); + } + + return; +} + +static void +acpi_io_pm_timer(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + struct FACPbody *facp = sc->facp_body; + int size = 0x4; /* 32-bits */ + + if (io == ACPI_REGISTERS_INPUT) { + acpi_registers_input(facp->pm_tmr_blk, val, size); + } else { + return; /* XXX read-only */ + } + + if (acpi_debug) { + ACPIPRINTF("acpi_io_pm_timer(%d) = (%x)\n", + io, *val); + } + + return; +} + +static void +acpi_io_gpe0_status(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + struct FACPbody *facp = sc->facp_body; + int size = facp->gpe0_len / 2; + + if (!facp->gpe0_blk) { + return; /* optional */ + } + + if (io == ACPI_REGISTERS_INPUT) { + acpi_registers_input(facp->gpe0_blk, val, size); + } else { + acpi_registers_output(facp->gpe0_blk, val, size); + } + + if (acpi_debug) { + ACPIPRINTF("acpi_io_gpe0_status(%d) = (%x)\n", + io, *val); + } + + return; +} + +static void +acpi_io_gpe0_enable(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + struct FACPbody *facp = sc->facp_body; + int size = facp->gpe0_len / 2; + + if (!facp->gpe0_blk) { + return; /* optional */ + } + + if (io == ACPI_REGISTERS_INPUT) { + acpi_registers_input(facp->gpe0_blk + size, val, size); + } else { + acpi_registers_output(facp->gpe0_blk + size, val, size); + } + + if (acpi_debug) { + ACPIPRINTF("acpi_io_gpe0_enable(%d) = (%x)\n", + io, *val); + } + + return; +} + +static void +acpi_io_gpe1_status(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + struct FACPbody *facp = sc->facp_body; + int size = facp->gpe1_len / 2; + + if (!facp->gpe1_blk) { + return; /* optional */ + } + + if (io == ACPI_REGISTERS_INPUT) { + acpi_registers_input(facp->gpe1_blk, val, size); + } else { + acpi_registers_output(facp->gpe1_blk, val, size); + } + + if (acpi_debug) { + ACPIPRINTF("acpi_io_gpe1_status(%d) = (%x)\n", + io, *val); + } + + return; +} + +static void +acpi_io_gpe1_enable(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + struct FACPbody *facp = sc->facp_body; + int size = facp->gpe1_len / 2; + + if (!facp->gpe1_blk) { + return; /* optional */ + } + + if (io == ACPI_REGISTERS_INPUT) { + acpi_registers_input(facp->gpe1_blk + size, val, size); + } else { + acpi_registers_output(facp->gpe1_blk + size, val, size); + } + + if (acpi_debug) { + ACPIPRINTF("acpi_io_gpe1_enable(%d) = (%x)\n", + io, *val); + } + + return; +} + +static int +acpiopen(dev_t dev, int flag, int fmt, struct proc * p) +{ + return (0); +} + +static int +acpiclose(dev_t dev, int flag, int fmt, struct proc * p) +{ + return (0); +} + +static int +acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc * p) +{ + acpi_softc_t *sc = devclass_get_softc(acpi_devclass, minor(dev)); + int error = 0; + int i, state; + struct acpi_system_state_package *ssp; + + if (sc == NULL) { + return (EINVAL); + } + + switch (cmd) { + case ACPIIO_ENABLE: + acpi_enable_disable(sc, 1); + break; + + case ACPIIO_DISABLE: + acpi_enable_disable(sc, 0); + break; + + case ACPIIO_SETSLPSTATE: + state = *(int *)addr; + if (state >= 0 && state <= 5) { + acpi_set_sleeping_state(sc, state); + } else { + error = EINVAL; + } + if (acpi_debug) + ACPIPRINTF("ACPIIO_SETSLPSTATE = %d\n", state); + break; + + case ACPIIO_GETSLPSTATEPKG: + ssp = (struct acpi_system_state_package *)addr; + *ssp = sc->system_state_package; + if (acpi_debug) { + ACPIPRINTF("ACPIIO_GETSLPSTATEPKG\n"); + for (i = 0; i < 6; i++) { + ACPIPRINTF(" [%d] = (%d,%d)\n", i, + sc->system_state_package.mode[i].slp_typ_a, + sc->system_state_package.mode[i].slp_typ_b); + } + } + break; + + case ACPIIO_SETSLPSTATEPKG: + ssp = (struct acpi_system_state_package *)addr; + sc->system_state_package = *ssp; + sc->system_state_initialized = 1; + if (acpi_debug) { + ACPIPRINTF("ACPIIO_SETSLPSTATEPKG\n"); + for (i = 0; i < 6; i++) { + ACPIPRINTF(" [%d] = (%d,%d)\n", i, + sc->system_state_package.mode[i].slp_typ_a, + sc->system_state_package.mode[i].slp_typ_b); + } + } + break; + + default: + error = EINVAL; + break; + } + + return (error); +} + +static int +acpimmap(dev_t dev, vm_offset_t offset, int nprot) +{ + acpi_softc_t *sc = devclass_get_softc(acpi_devclass, minor(dev)); + + if (sc == NULL) { + return (EINVAL); + } + return (i386_btop(acpi_pmap_vtp((vm_offset_t)(sc->dsdt + offset)))); +} + +/* + * Builtin Control method code. + */ + +#define ACPI_BUILTIN_STATEPACKAGE /* stupid? :-) Yes, I know. */ + +/* + * Macros for ASL translation. +*/ +#define OperationRegion(RegionName, RegionSpace, Offset, Length) \ + /* XXX Supports StstemIO RegionSpace only */ \ + u_int32_t RegionName = Offset; + +#define Field(RegionName, AccessType, LockRule, UpdateRule, Offset, FieldName, Bitlen) \ + /* XXX Supports ByteAcc AccessType only */ \ + u_int32_t FieldName = RegionName + (Offset / 8); \ + u_int32_t FieldName##_OFFSET = (Offset % 8); \ + u_int32_t FieldName##_MASK = (~((1 << Bitlen) - 1) << (Offset % 8)) | (Offset % 8); \ + u_int32_t FieldName##_LEN = Bitlen / 8 + ((Bitlen % 8)? 1 : 0); + +#define IndexField(IndexName, DataName, AccessType, LockRule, UpdateRule, Offset, FieldName, Bitlen) \ + /* XXX Supports ByteAcc AccessType only */ \ + u_int32_t FieldName##_POS = (Offset / 8); \ + u_int32_t FieldName##_INDEX = IndexName; \ + u_int32_t FieldName##_INDEX_OFFSET = IndexName##_OFFSET; \ + u_int32_t FieldName##_INDEX_MASK = IndexName##_MASK; \ + u_int32_t FieldName##_INDEX_LEN = IndexName##_LEN; \ + u_int32_t FieldName##_DATA = DataName; \ + u_int32_t FieldName##_DATA_OFFSET = DataName##_OFFSET; \ + u_int32_t FieldName##_DATA_MASK = DataName##_MASK; \ + u_int32_t FieldName##_DATA_LEN = DataName##_LEN; + +#define StoreIndexField(VAL, FIELD) \ + /* XXX Supports StstemIO RegionSpace only */ \ + acpi_registers_input(FIELD##_INDEX, &tmp, FIELD##_INDEX_LEN); \ + tmp = (tmp & FIELD##_INDEX_MASK) | (FIELD##_POS << FIELD##_INDEX_OFFSET); \ + acpi_registers_output(FIELD##_INDEX, &tmp, FIELD##_INDEX_LEN); \ + acpi_registers_input(FIELD##_DATA, &tmp, FIELD##_DATA##_LEN); \ + tmp = (tmp & FIELD##_DATA_MASK) | (VAL << FIELD##_DATA_OFFSET); \ + acpi_registers_output(FIELD##_DATA, &tmp, FIELD##_INDEX_LEN); + +#define Mutex(MutexName, SyncLevel) /* Mutex() will be ingnored */ + +#define Acquire(SyncObject, TimeoutValue) /* Acquire() will be ingnored */ + +#define Release(SyncObject) /* Release() will be ingnored */ + +#define Return(Arg) /* Return() will be ingnored */ + +#define If(x) if(x) + +#define LNot(x) !(x) + +#define LEqual(op1, op2) op1 == op2 + +#define Store(VAL, OBJ) \ + /* XXX Supports StstemIO RegionSpace only */ \ + acpi_registers_input(OBJ, &tmp, OBJ##_LEN); \ + tmp = (tmp & OBJ##_MASK) | (VAL << OBJ##_OFFSET); \ + acpi_registers_output(OBJ, &tmp, OBJ##_LEN); + +#define Or(op1, op2, op3) \ + op3 = op1 | op2; + +#define One 0x1 + +#define Zero 0x0 + +/* + * _PTS and _WAK for P2B. + */ +static void +acpi_execute_pts_p2b(acpi_softc_t *sc, u_int8_t Arg0) +{ + + /* Original ASL code + * + Name(\_S0, Package() { + 0x5 + 0x5 + 0x0 + 0x0 + }) + Name(\_S1, Package() { + 0x7 + 0x7 + 0x0 + 0x0 + }) + Name(\_S5, Package() { + 0x6 + 0x6 + 0x0 + 0x0 + }) + OperationRegion(\DEBG, SystemIO, 0x80, 0x1) + Field(\DEBG, ByteAcc, NoLock, Preserve) { + DBG1, 8 + } + OperationRegion(GPOB, SystemIO, 0xe42c, 0x10) + Field(GPOB, ByteAcc, NoLock, Preserve) { + Offset(0x18), + TO12, 1, + Offset(0x40), + FANM, 1, + Offset(0x48), + PLED, 1, + Offset(0x4c), + Offset(0x4e), + Offset(0x5e), + MSG0, 1 + } + Method(\_PTS, 1) { + If(LNot(LEqual(Arg0, 0x5))) { + Store(0x0, FANM) + Store(0x0, PLED) + } + If(LEqual(Arg0, 0x1)) { + Store(One, TO12) + } + If(LEqual(Arg0, 0x2)) { + } + Store(One, TO12) + Or(Arg0, 0xf0, Local2) + Store(Local2, DBG1) + } + * + */ + + u_int32_t tmp; + u_int8_t Local2; +#ifdef ACPI_BUILTIN_STATEPACKAGE + struct acpi_system_state_package system_state_package = {{ + {0x5, 0x5}, + {0x7, 0x7}, + {ACPI_UNSUPPORTSLPTYP, ACPI_UNSUPPORTSLPTYP}, + {ACPI_UNSUPPORTSLPTYP, ACPI_UNSUPPORTSLPTYP}, + {ACPI_UNSUPPORTSLPTYP, ACPI_UNSUPPORTSLPTYP}, + {0x6, 0x6}, + }}; +#endif + + OperationRegion(_DEBG, SystemIO, 0x80, 0x1) + Field(_DEBG, ByteAcc, NoLock, Preserve, 0x0, DBG1, 8) + + OperationRegion(GPOB, SystemIO, 0xe42c, 0x10) + Field(GPOB, ByteAcc, NoLock, Preserve, 0x18, TO12, 1) + Field(GPOB, ByteAcc, NoLock, Preserve, 0x40, FANM, 1) + Field(GPOB, ByteAcc, NoLock, Preserve, 0x48, PLED, 1) + +#ifdef ACPI_BUILTIN_STATEPACKAGE + sc->system_state_package = system_state_package; + sc->system_state_initialized = 1; +#endif + + If(LNot(LEqual(Arg0, 0x5))) { + Store(0x0, FANM) + Store(0x0, PLED) + } + If(LEqual(Arg0, 0x1)) { + Store(One, TO12) + } + If(LEqual(Arg0, 0x2)) { + } + Store(One, TO12) + Or(Arg0, 0xf0, Local2) + Store(Local2, DBG1) + +} + +static void +acpi_execute_wak_p2b(acpi_softc_t *sc, u_int8_t Arg0) +{ + u_int32_t tmp; + OperationRegion(_DEBG, SystemIO, 0x80, 0x1) + Field(_DEBG, ByteAcc, NoLock, Preserve, 0x0, DBG1, 8) + OperationRegion(GPOB, SystemIO, 0xe42c, 0x10) + Field(GPOB, ByteAcc, NoLock, Preserve, 0x40, FANM, 1) + Field(GPOB, ByteAcc, NoLock, Preserve, 0x48, PLED, 1) + + Store(0x1, FANM) + Store(One, PLED) + Store(0xff, DBG1) +} + +/* + * _PTS for MobioNX. + */ +static void +acpi_execute_pts_mobionx(acpi_softc_t *sc, u_int8_t Arg0) +{ + /* Original ASL code + * + Name(_S0, Package() { + 0x0 + 0x0 + }) + Name(_S3, Package() { + 0x3 + 0x0 + }) + Name(_S4, Package() { + 0x4 + 0x0 + }) + Name(_S5, Package() { + 0x4 + 0x0 + }) + OperationRegion(SMI0, SystemMemory, 0x4ffff2c, 0x90) + Field(SMI0, AnyAcc, NoLock, Preserve) { + BCMD, 8, + DID, 32, + INFO, 32 + } + OperationRegion(SMI1, SystemIO, 0xfe00, 0x2) + Field(SMI1, AnyAcc, NoLock, Preserve) { + SMIC, 8 + } + Mutex(MPHS, 0) + Method(PHS, 9) { + Acquire(MPHS, 0xffff) + Store(Arg0, BCMD) + Store(0x0, DID) + Store(Zero, SMIC) + Store(0x0, BCMD) + Release(MPHS) + Return(INFO) + } + + Method(_PTS, 1) { + If(LEqual(Arg0, 0x3)) { + PHS + 0x85 + } + } + * + */ + + u_int32_t tmp; +#ifdef ACPI_BUILTIN_STATEPACKAGE + struct acpi_system_state_package system_state_package = {{ + {0x0, 0x0}, + {ACPI_UNSUPPORTSLPTYP, ACPI_UNSUPPORTSLPTYP}, + {ACPI_UNSUPPORTSLPTYP, ACPI_UNSUPPORTSLPTYP}, + {0x3, 0x0}, + {0x4, 0x0}, + {0x4, 0x0}, + }}; +#endif + +#if 0 + OperationRegion(SMI0, SystemMemory, 0x4ffff2c, 0x90) + Field(SMI0, AnyAcc, NoLock, Preserve, 0, BCMD, 8) + Field(SMI0, AnyAcc, NoLock, Preserve, 8, DID, 32) +#endif + vm_offset_t SMI0 = acpi_pmap_ptv(0x4ffff2c); + u_int8_t *BCMD; + u_int32_t *DID; + + OperationRegion(SMI1, SystemIO, 0xfe00, 0x2) + Field(SMI1, AnyAcc, NoLock, Preserve, 0, SMIC, 8); + +#ifdef ACPI_BUILTIN_STATEPACKAGE + sc->system_state_package = system_state_package; + sc->system_state_initialized = 1; +#endif + + BCMD = (u_int8_t *) SMI0 + (0 / 8); + DID = (u_int32_t *) SMI0 + (8 / 8); + + If(LEqual(Arg0, 0x3)) { + Mutex(MPHS, 0) + /* PHS(0x85) */ + Acquire(MPHS, 0xffff) +#if 0 + Store(0x85, BCMD) + Store(0x0, DID) +#endif + *BCMD = 0x85; + *DID = 0x0; + + Store(Zero, SMIC) +#if 0 + Store(0x0, BCMD) +#endif + *BCMD = 0x0; + Release(MPHS) + Return(INFO) + } +} + +/* + * _PTS for Chandra2. + */ +static void +acpi_execute_pts_chandra2(acpi_softc_t *sc, u_int8_t Arg0) +{ + /* Original ASL code + * + OperationRegion(CTRC, SystemIO, 0x1d6, 0x2) + Field(CTRC, ByteAcc, NoLock, Preserve) { + CIDX, 8, + CDAT, 8 + } + IndexField(CIDX, CDAT, ByteAcc, NoLock, Preserve) { + WKST, 8, + SLNO, 8, + SYSI, 8, + MSGI, 8 + } + + Name(\_S0, Package() { + 0x0 + 0x0 + 0x0 + }) + Name(\_S1, Package() { + 0x1 + 0x1 + 0x0 + }) + Name(\_S2, Package() { + 0x2 + 0x2 + 0x0 + }) + Name(\_S3, Package() { + 0x3 + 0x3 + 0x0 + }) + Name(\_S4, Package() { + 0x4 + 0x4 + 0x0 + }) + Name(\_S5, Package() { + 0x5 + 0x5 + 0x0 + }) + + Method(\_PTS, 1) { + Store(Arg0, SLNO) + } + * + */ + + u_int32_t tmp; +#ifdef ACPI_BUILTIN_STATEPACKAGE + struct acpi_system_state_package system_state_package = {{ + {0x0, 0x0}, + {0x1, 0x1}, + {0x2, 0x2}, + {0x3, 0x3}, + {0x4, 0x4}, + {0x5, 0x5}, + }}; +#endif + + OperationRegion(CTRC, SystemIO, 0x1d6, 0x2) + Field(CTRC, ByteAcc, NoLock, Preserve, 0, CIDX, 8) + Field(CTRC, ByteAcc, NoLock, Preserve, 8, CDAT, 8) + IndexField(CIDX, CDAT, ByteAcc, NoLock, Preserve, 8, SLNO, 8) + +#ifdef ACPI_BUILTIN_STATEPACKAGE + sc->system_state_package = system_state_package; + sc->system_state_initialized = 1; +#endif + + StoreIndexField(Arg0, SLNO) +} + +/* + * _PTS and _WAK for AWARDBIOS. + */ +static void +acpi_execute_pts_awardbios(acpi_softc_t *sc, u_int8_t Arg0) +{ + /* Original ASL code + * + Name(\_S0, Package() { + 0x5 + 0x5 + }) + Name(\_S1, Package() { + 0x2 + 0x2 + }) + Name(\_S5, Package() { + Zero + Zero + }) + + OperationRegion(\DEBG, SystemIO, 0x80, 0x1) + Field(\DEBG, ByteAcc, NoLock, Preserve) { + DBG1, 8 + } + Method(\_PTS, 1) { + Or(Arg0, 0xf0, Local0) + Store(Local0, DBG1) + } + * + */ + + u_int32_t tmp; + u_int8_t Local0; +#ifdef ACPI_BUILTIN_STATEPACKAGE + struct acpi_system_state_package system_state_package = {{ + {0x5, 0x5}, + {0x2, 0x2}, + {ACPI_UNSUPPORTSLPTYP, ACPI_UNSUPPORTSLPTYP}, + {ACPI_UNSUPPORTSLPTYP, ACPI_UNSUPPORTSLPTYP}, + {ACPI_UNSUPPORTSLPTYP, ACPI_UNSUPPORTSLPTYP}, + {0x0, 0x0}, + }}; +#endif + + OperationRegion(_DEBG, SystemIO, 0x80, 0x1) + Field(_DEBG, ByteAcc, NoLock, Preserve, 0, DBG1, 8) + +#ifdef ACPI_BUILTIN_STATEPACKAGE + sc->system_state_package = system_state_package; + sc->system_state_initialized = 1; +#endif + + Or(Arg0, 0xf0, Local0) + Store(Local0, DBG1) +} + +static void +acpi_execute_wak_awardbios(acpi_softc_t *sc, u_int8_t Arg0) +{ + u_int32_t tmp; + + OperationRegion(_DEBG, SystemIO, 0x80, 0x1) + Field(_DEBG, ByteAcc, NoLock, Preserve, 0, DBG1, 8) + + Store(0xff, DBG1) +} + +/* + * _PTS and _WAK for Z505FX and Z505JX. + */ +static void +acpi_execute_pts_Z505FX(acpi_softc_t *sc, u_int8_t Arg0) +{ + /* Original ASL code + * + Name(_S0, Package() { + 0x5 + 0x5 + }) + Name(_S1, Package() { + 0x4 + 0x4 + }) + Name(_S3, Package() { + 0x1 + 0x1 + }) + Name(_S4, Package() { + 0x0 + 0x0 + }) + Name(_S5, Package() { + 0x0 + 0x0 + }) + * + */ + +#ifdef ACPI_BUILTIN_STATEPACKAGE + struct acpi_system_state_package system_state_package = {{ + {0x5, 0x5}, + {0x4, 0x4}, + {ACPI_UNSUPPORTSLPTYP, ACPI_UNSUPPORTSLPTYP}, + {0x1, 0x1}, + {0x0, 0x0}, + {0x0, 0x0}, + }}; + + sc->system_state_package = system_state_package; + sc->system_state_initialized = 1; +#endif + +} + +static void +acpi_execute_wak_Z505FX(acpi_softc_t *sc, u_int8_t Arg0) +{ + /* Original ASL code + * + Method(_WAK, 1) { + Notify(\_SB.PWRB, 0x2) + Return(Zero) + } + * + */ + + /* How to implement? */ +} + +typedef struct { + char *oemid; + char *oemtblid; + u_int32_t oemrev_range[2]; + void (*pts_func)(acpi_softc_t *, u_int8_t); + void (*wak_func)(acpi_softc_t *, u_int8_t); +} acpi_builtin_method_t; + +static acpi_builtin_method_t method_table[] = { + { + "ASUS", "P2B", {0x1000, 0x1000}, + acpi_execute_pts_p2b, acpi_execute_wak_p2b + }, + { + "NEC", "ND000004", {0x1, 0x1}, + acpi_execute_pts_mobionx, NULL + }, + { + "RIOS", "Clavius", {0x2, 0x2}, + acpi_execute_pts_chandra2, NULL + }, + { + "AWARD", "AWRDACPI", {0x1000, 0x1000}, + acpi_execute_pts_awardbios, acpi_execute_wak_awardbios + }, + { + "SONY", "", {0x0, 0x0}, + acpi_execute_pts_Z505FX, acpi_execute_wak_Z505FX + }, + { + " SONY", "Z0", {0x1310859, 0x1310859}, + acpi_execute_pts_Z505FX, acpi_execute_wak_Z505FX + }, + { NULL, NULL, {NULL, NULL}, NULL, NULL} +}; + +#define ACPI_METHOD_PTS 0 +#define ACPI_METHOD_WAK 1 + +static void +acpi_execute_method(acpi_softc_t *sc, u_int8_t state, u_int8_t method) +{ + u_char oemid[6]; + u_char oemtblid[8]; + u_int32_t oemrev; + int id_len, tblid_len; + acpi_builtin_method_t *table_ptr; + char *method_name[] = {"pts", "wak"}; + + memcpy(oemid, sc->dsdt->oemid, sizeof oemid); + memcpy(oemtblid, sc->dsdt->oemtblid, sizeof oemtblid); + oemrev = sc->dsdt->oemrev; + + table_ptr = method_table; + while (table_ptr->oemid) { + id_len = strlen(table_ptr->oemid); + tblid_len = strlen(table_ptr->oemtblid); + + if ((!strncmp(oemid, table_ptr->oemid, id_len)) && + (!strncmp(oemtblid, table_ptr->oemtblid, tblid_len)) && + (oemrev >= table_ptr->oemrev_range[0]) && + (oemrev <= table_ptr->oemrev_range[1])) { + if (acpi_debug) { + ACPIPRINTF("acpi_execute_%s(%s, %s, %x).\n", + method_name[method], table_ptr->oemid, + table_ptr->oemtblid, oemrev); + } + + switch (method) { + case ACPI_METHOD_PTS: + if (table_ptr->pts_func) { + table_ptr->pts_func(sc, state); + } + break; + case ACPI_METHOD_WAK: + if (table_ptr->wak_func) { + table_ptr->wak_func(sc, state); + } + break; + default: + break; + } + return; + } + table_ptr++; + } + + /* not found */ + if (acpi_debug) { + ACPIPRINTF("acpi_execute_%s not found.\n", + method_name[method]); + } +} + +static void +acpi_execute_pts(acpi_softc_t *sc, u_int8_t state) +{ + acpi_execute_method(sc, state, ACPI_METHOD_PTS); +} + +static void +acpi_execute_wak(acpi_softc_t *sc, u_int8_t state) +{ + acpi_execute_method(sc, state, ACPI_METHOD_WAK); +} Index: sys/i386/acpi/ec.c diff -u /dev/null sys/i386/acpi/ec.c:1.1.2.4 --- /dev/null Mon Apr 17 20:01:33 2000 +++ sys/i386/acpi/ec.c Mon Apr 17 19:58:33 2000 @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CDEV_MAJOR 210 + +#define EC_MINOR 0x10 + +#define NUM_EC_REG 0x100 + +#define RD_EC 0x80 /*Read Embedded Controller*/ +#define WR_EC 0x81 /*Write Embedded Controller*/ +#define BE_EC 0x82 /*Burst Enable Embedded Controller*/ +#define BD_EC 0x83 /*Burst Disable Embedded Controller*/ +#define QR_EC 0x84 /*Query Embedded Controller */ + +struct ec_softc{ + KBDC kbdc; + int iscommand; + int isopen; + int ispending; + u_int8_t buffer[NUM_EC_REG]; +}; +static int ec_probe(device_t); +static int ec_attach(device_t); +u_int8_t ec_read_addr(device_t dev,u_int8_t); +void ec_write_addr(device_t dev,u_int8_t,u_int8_t); +devclass_t ec_devclass; +static device_method_t ec_methods[] = { + DEVMETHOD(device_probe, ec_probe), + DEVMETHOD(device_attach, ec_attach), + + { 0 , 0} +}; + +static d_open_t ecopen; +static d_close_t ecclose; +static d_ioctl_t ecioctl; +static d_read_t ecread; +static d_write_t ecwrite; +static int ec_intr(device_t ); +static struct cdevsw ec_cdevsw = { + /* open */ ecopen, + /* close */ ecclose, + /* read */ ecread, + /* write */ ecwrite, + /* ioctl */ ecioctl, + /* poll */ nopoll, + /* mmap */ nommap, + /* strategy */ nostrategy, + /* name */ "ec", + /* maj */ CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ 0, + /* bmaj */ -1 +}; +#define ECDEV_SOFTC(unit) devclass_get_softc(ec_devclass,minor(dev)&0xf) +#define ECDEV_DEVICE(unit) devclass_get_device(ec_devclass,minor(dev)&0xf) +static int ec_query(device_t dev) +{ + int query; + struct ec_softc *sc = device_get_softc(dev); + while(kbdc_sci_ready(sc->kbdc)){ + write_controller_command(sc->kbdc,QR_EC);/*EC_QUERY*/ + query=read_controller_data(sc->kbdc); + device_printf(dev,"EC_QUERY data%x\n",query); + if(query==-1) + break ; + } +} +int ec_intr(device_t dev) +{ + struct ec_softc *sc=device_get_softc(dev); + if(sc->iscommand){ + wakeup(&sc->iscommand); + }else{ + ec_query(dev); + } + return 0; +} + +int ec_probe(device_t dev) +{ + device_set_desc(dev,"Embedded Controller"); + return 0; +} +int ec_attach(device_t dev) +{ + int ret; + device_t parent=device_get_parent(dev); + struct ec_softc *sc=device_get_softc(dev); + KBDC kbdc; + kbdc = atkbdc_open(device_get_unit(parent)); + if(kbdc==NULL){ + return ENOMEM; + } + sc->kbdc=kbdc; + ret=acpi_setup_ecintr((driver_intr_t *)ec_intr,dev); + sc->iscommand=0; + sc->isopen=0; + sc->ispending=0; + make_dev(&ec_cdevsw,EC_MINOR,0,5,0660,"ec"); + return ret; +} + +static int +ecopen(dev_t dev,int flag, int fmt,struct proc *p) +{ + struct ec_softc *sc=ECDEV_SOFTC(dev); + + if(sc->isopen!=0){ + return EBUSY; + }else{ + sc->iscommand=0; + sc->isopen=1; + } + + return 0; +} +static int +ecclose(dev_t dev,int flag,int fmt,struct proc *p) +{ + struct ec_softc *sc=ECDEV_SOFTC(dev); + + sc->isopen=0; + sc->iscommand=0; + return 0; +} +static int +ecioctl(dev_t dev,u_long cmd, caddr_t addr,int flag, struct proc *p) +{ +#if 0 + device_t d=ECDEV_DEVICE(dev); +#endif + switch(cmd){ + case ACPIIO_ECGPE_SET: + return acpi_setup_ecgpe(*addr); + default: + return ENXIO; + } + return ENXIO; +} + +int ec_burst_enable(device_t dev) +{ + struct ec_softc *sc=device_get_softc(dev); + int s; + int err; + s=splhigh(); + sc->iscommand=1; + write_controller_command(sc->kbdc,BE_EC); + splx(s); + do{ + tsleep(&sc->iscommand,TTIPRI|PCATCH,"ecbew",400); + }while(read_controller_data(sc->kbdc)!=0x90); + return 0; +} +int ec_burst_disabl(device_t dev) +{ + struct ec_softc *sc=device_get_softc(dev); + int s; + int err; + s=splhigh(); + write_controller_command(sc->kbdc,BD_EC); + splx(s); + tsleep(&sc->iscommand,TTIPRI|PCATCH,"ecbdw",0); + s=splhigh(); + sc->iscommand=0; + ec_query(dev); + splx(s); + return 0; +} +/* + * This should be exported and This should be called from + * upper half. + */ +u_int8_t ec_read_addr(device_t dev,u_int8_t addr) +{ + int s; + u_int8_t ret; + struct ec_softc *sc=device_get_softc(dev); + write_controller_command(sc->kbdc,RD_EC); + write_controller_data(sc->kbdc,addr); + tsleep(&sc->iscommand,TTIPRI|PCATCH,"ecrdw",50); + ret=read_controller_data(sc->kbdc); + +} + +void ec_write_addr(device_t dev,u_int8_t addr,u_int8_t data) +{ + int s; + struct ec_softc *sc=device_get_softc(dev); + write_controller_command(sc->kbdc,WR_EC); + write_controller_data(sc->kbdc,addr); + write_controller_data(sc->kbdc,data); + tsleep(&sc->iscommand,TTIPRI|PCATCH,"ecwrw",50); + return ; +} + +static int ecwrite(dev_t dev,struct uio *uio,int flag) +{ + device_t d=ECDEV_DEVICE(dev); + struct ec_softc *sc=device_get_softc(d); + int off = uio->uio_offset; + int resid= uio->uio_resid; + int end; + int i,count; + u_int8_t *writebuffer=&sc->buffer[off]; + + end=(off+residuio_offset; + int resid= uio->uio_resid; + int end; + int i,count; + u_int8_t *readbuffer=sc->buffer+off; + ec_burst_enable(d); + end=(off+resid 0 #include #endif - +#if NACPI > 0 +#include +#endif #define BIOS_START 0xe0000 #define BIOS_SIZE 0x20000 @@ -136,11 +138,29 @@ printf("pnpbios: Bad PnP BIOS data checksum\n"); } } +#if NACPI>0 + /* + * ACPI BIOS + * acpi_rsdp is GLOBAL and holds RSD PTR signature + */ + if ((sigaddr = bios_sigsearch(0, "RSD PTR ", 8, 16, 0)) != 0) { + /* get a virtual pointer to the structure */ + acpi_rsdp = (struct ACPIrsdp *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); + for (cv = (u_int8_t *)acpi_rsdp, ck = 0, i = 0; i < sizeof(struct ACPIrsdp); i++) { + ck += cv[i]; + } + + /* If checksum is NG, disable it */ + if (ck != 0) { + printf("ACPI: Bad ACPI BIOS data checksum\n"); + acpi_rsdp=NULL;/* 0xa0000<=RSD_PTR<0x100000*/ + } + } +#endif if (bootverbose) { /* look for other know signatures */ printf("Other BIOS signatures found:\n"); - printf("ACPI: %08x\n", bios_sigsearch(0, "RSD PTR ", 8, 16, 0)); } } Index: sys/i386/i386/machdep.c diff -u sys/i386/i386/machdep.c:1.1.1.1 sys/i386/i386/machdep.c:1.1.1.1.2.1 --- sys/i386/i386/machdep.c:1.1.1.1 Mon Apr 10 22:54:22 2000 +++ sys/i386/i386/machdep.c Mon Apr 10 23:49:50 2000 @@ -37,7 +37,7 @@ * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 * $FreeBSD: /ctm/FreeBSD/anoncvs/cvs/src/sys/i386/i386/machdep.c,v 1.389 2000/04/02 15:24:04 phk Exp $ */ - +#include "acpi.h" #include "apm.h" #include "ether.h" #include "npx.h" @@ -125,6 +125,10 @@ #include #include +#if NACPI > 0 +#include +#endif + extern void init386 __P((int first)); extern void dblfault_handler __P((void)); @@ -1496,6 +1500,10 @@ smap = (void *)vm86_addpage(&vmc, 1, KERNBASE + (1 << PAGE_SHIFT)); vm86_getptr(&vmc, (vm_offset_t)smap, &vmf.vmf_es, &vmf.vmf_di); +#if NACPI > 0 + acpi_init_addr_range(); +#endif + physmap_idx = 0; vmf.vmf_ebx = 0; do { @@ -1512,6 +1520,14 @@ (u_int32_t)smap->base, *(u_int32_t *)((char *)&smap->length + 4), (u_int32_t)smap->length); + +#if NACPI > 0 + /* Save ACPI related memory Info */ + if (smap->type == 0x03 || smap->type == 0x04) { + acpi_register_addr_range(smap->base, + smap->length, smap->type); + } +#endif if (smap->type != 0x01) goto next_run; Index: sys/i386/include/pc/acpi.h diff -u /dev/null sys/i386/include/pc/acpi.h:1.1.2.1 --- /dev/null Mon Apr 17 20:01:34 2000 +++ sys/i386/include/pc/acpi.h Mon Apr 10 23:49:52 2000 @@ -0,0 +1,183 @@ +/*- + * Copyright (c) 1999 Takanori Watanabe + * Copyright (c) 1999 Mitsuru IWASAKI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_PC_ACPI_H_ +#define _MACHINE_PC_ACPI_H_ + +#include + +/* Root System Description Pointer */ +struct ACPIrsdp { + u_char signature[8]; + u_char sum; + u_char oem[6]; + u_char res; + u_int32_t addr; +} __attribute__((packed)); + +/* System Description Table */ +struct ACPIsdt { + u_char signature[4]; + u_int32_t len; + u_char rev; + u_char check; + u_char oemid[6]; + u_char oemtblid[8]; + u_int32_t oemrev; + u_char creator[4]; + u_int32_t crerev; +#define SIZEOF_SDT_HDR 36 /* struct size except body */ + u_int32_t body[1];/* This member should be casted */ +} __attribute__((packed)); + +/* Fixed ACPI Description Table (body) */ +struct FACPbody { + u_int32_t facs_ptr; + u_int32_t dsdt_ptr; + u_int8_t int_model; +#define ACPI_FACP_INTMODEL_PIC 0 /* Standard PC-AT PIC */ +#define ACPI_FACP_INTMODEL_APIC 1 /* Multiple APIC */ + u_char reserved1; + u_int16_t sci_int; + u_int32_t smi_cmd; + u_int8_t acpi_enable; + u_int8_t acpi_disable; + u_int8_t s4biosreq; + u_int8_t reserved2; + u_int32_t pm1a_evt_blk; + u_int32_t pm1b_evt_blk; + u_int32_t pm1a_cnt_blk; + u_int32_t pm1b_cnt_blk; + u_int32_t pm2_cnt_blk; + u_int32_t pm_tmr_blk; + u_int32_t gpe0_blk; + u_int32_t gpe1_blk; + u_int8_t pm1_evt_len; + u_int8_t pm1_cnt_len; + u_int8_t pm2_cnt_len; + u_int8_t pm_tmr_len; + u_int8_t gpe0_len; + u_int8_t gpe1_len; + u_int8_t gpe1_base; + u_int8_t reserved3; + u_int16_t p_lvl2_lat; + u_int16_t p_lvl3_lat; + u_int16_t flush_size; + u_int16_t flush_stride; + u_int8_t duty_off; + u_int8_t duty_width; + u_int8_t day_alrm; + u_int8_t mon_alrm; + u_int8_t century; + u_char reserved4[3]; + u_int32_t flags; +#define ACPI_FACP_FLAG_WBINVD 1 /* WBINVD is correctly supported */ +#define ACPI_FACP_FLAG_WBINVD_FLUSH 2 /* WBINVD flushes caches */ +#define ACPI_FACP_FLAG_PROC_C1 4 /* C1 power state supported */ +#define ACPI_FACP_FLAG_P_LVL2_UP 8 /* C2 power state works on SMP */ +#define ACPI_FACP_FLAG_PWR_BUTTON 16 /* Power button uses control method */ +#define ACPI_FACP_FLAG_SLP_BUTTON 32 /* Sleep button uses control method */ +#define ACPI_FACP_FLAG_FIX_RTC 64 /* RTC wakeup not supported */ +#define ACPI_FACP_FLAG_RTC_S4 128 /* RTC can wakeup from S4 state */ +#define ACPI_FACP_FLAG_TMR_VAL_EXT 256 /* TMR_VAL is 32bit */ +#define ACPI_FACP_FLAG_DCK_CAP 512 /* Can support docking */ +} __attribute__((packed)); + +/* Firmware ACPI Control Structure */ +struct FACS { + u_char signature[4]; + u_int32_t len; + u_char hard_sig[4]; + /* + * NOTE This should be filled with physical address below 1MB!! + * sigh.... + */ + u_int32_t firm_wake_vec; + u_int32_t g_lock; /* bit field */ + /* 5.2.6.1 Global Lock */ +#define ACPI_GLOBAL_LOCK_PENDING 1 +#define ACPI_GLOBAL_LOCK_OWNED 2 + u_int32_t flags; /* bit field */ +#define ACPI_FACS_FLAG_S4BIOS_F 1 /* Supports S4BIOS_SEQ */ + char reserved[40]; +} __attribute__((packed)); + +#ifdef _KERNEL +extern struct ACPIrsdp *acpi_rsdp; /* ACPI Root System Description Table */ + +void acpi_init_addr_range(void); +void acpi_register_addr_range(u_int64_t base, u_int64_t size, u_int32_t type); +#endif /* KERNEL */ + +/* + * Structure for System State Package (7.5.2). + */ +struct acpi_system_state_package { + struct { + u_int8_t slp_typ_a; /* 3-bit only. */ + u_int8_t slp_typ_b; /* (4.7.3.2.1) */ + } mode[6]; +}; + +/* + * XXX set this to acpi_system_state_package.mode[?].slp_typ_[ab] + * if the mode is not supported. + */ +#define ACPI_UNSUPPORTSLPTYP 0xff /* unsupported sleeping type */ + +#define ACPIIO_ENABLE _IO('P', 1) +#define ACPIIO_DISABLE _IO('P', 2) +#define ACPIIO_SETSLPSTATE _IOW('P', 3, int) + +/* + * XXX followings are the temporary ioctl requests + * until kernel AML parser developed. + */ +#define ACPIIO_GETSLPSTATEPKG \ + _IOR('P', IOCPARM_MASK - 2, struct acpi_system_state_package) +#define ACPIIO_SETSLPSTATEPKG \ + _IOW('P', IOCPARM_MASK - 1, struct acpi_system_state_package) +/*These interface is not for acpi but ec driver*/ +#define ACPIIO_ECGPE_SET _IO('P',IOCPARM_MASK-3) + +#ifdef _KERNEL +void *acpi_map_physical(vm_offset_t pa, size_t length); +struct ACPIrsdp *acpi_find_rsd_ptr(void); +int acpi_checksum(void *p, size_t length); +struct ACPIsdt *acpi_map_sdt(vm_offset_t pa); +void acpi_print_rsd_ptr(struct ACPIrsdp * rp); +void acpi_print_sdt(struct ACPIsdt * sdp); +void acpi_print_rsdt(struct ACPIsdt * rsdp); +void acpi_print_facp(struct FACPbody * facp); +void acpi_print_dsdt(struct ACPIsdt * dsdp); +int acpi_setup_ecintr(driver_intr_t ecintr, void *ecarg); +int acpi_setup_ecgpe(int ecgpe); +#endif /* !KERNEL */ + +#endif /* _MACHINE_PC_ACPI_H_ */