diff options
author | msmith <msmith@FreeBSD.org> | 2000-09-30 20:12:27 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 2000-09-30 20:12:27 +0000 |
commit | 43b494595ef50e9426434fd028f71567c7fc2e36 (patch) | |
tree | 04488cdbfa2a244cc961901253683a6d7f5405b8 /sys/dev/acpi/acpi_io.c | |
parent | 8cc643d7ff3e76e0d1cadc99dbd6ad666b8a0171 (diff) | |
download | FreeBSD-src-43b494595ef50e9426434fd028f71567c7fc2e36.zip FreeBSD-src-43b494595ef50e9426434fd028f71567c7fc2e36.tar.gz |
More updates to the ACPI code:
- Move all register I/O into acpi_io.c
- Move event handling into acpi_event.c
- Reorganise headers into acpivar/acpireg/acpiio
- Move find-RSDT and find-ACPI-owned-memory into acpi_machdep
- Allocate all resources (except those detailed only by AML)
as real resources. Add infrastructure that will make adding
resource support to AML code easy.
- Remove all ACPI #ifdefs in non-ACPI code
- Removed unnecessary includes
- Minor style and commenting fixes
Reviewed by: iwasaki
Diffstat (limited to 'sys/dev/acpi/acpi_io.c')
-rw-r--r-- | sys/dev/acpi/acpi_io.c | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/sys/dev/acpi/acpi_io.c b/sys/dev/acpi/acpi_io.c new file mode 100644 index 0000000..1d1384f --- /dev/null +++ b/sys/dev/acpi/acpi_io.c @@ -0,0 +1,356 @@ +/*- + * Copyright (c) 1999 Takanori Watanabe <takawata@shidahara1.planet.sci.kobe-u.ac.jp> + * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> + * 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 <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <machine/bus.h> + +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> + +/* + * ACPI Register I/O + */ +static __inline void +acpi_register_input(acpi_softc_t *sc, int res, int offset, u_int32_t *value, u_int32_t size) +{ + bus_space_tag_t bst; + bus_space_handle_t bsh; + u_int32_t val; + + if (sc->iores[res].rsc == NULL) + return; + + bst = sc->iores[res].btag; + bsh = sc->iores[res].bhandle; + + switch (size) { + case 1: + val = bus_space_read_1(bst, bsh, offset); + break; + case 2: + val = bus_space_read_2(bst, bsh, offset); + break; + case 3: + val = bus_space_read_4(bst, bsh, offset); + val &= 0x00ffffff; + break; + case 4: + val = bus_space_read_4(bst, bsh, offset); + break; + default: + ACPI_DEVPRINTF("acpi_register_input(): invalid size (%d)\n", size); + val = 0; + break; + } + + *value = val; +} + +static __inline void +acpi_register_output(acpi_softc_t *sc, int res, int offset, u_int32_t *value, u_int32_t size) +{ + bus_space_tag_t bst; + bus_space_handle_t bsh; + u_int32_t val; + + if (sc->iores[res].rsc == NULL) + return; + + val = *value; + bst = sc->iores[res].btag; + bsh = sc->iores[res].bhandle; + + switch (size) { + case 1: + bus_space_write_1(bst, bsh, offset, val & 0xff); + break; + case 2: + bus_space_write_2(bst, bsh, offset, val & 0xffff); + break; + case 3: + bus_space_write_2(bst, bsh, offset, val & 0xffff); + bus_space_write_1(bst, bsh, offset + 2, (val >> 16) & 0xff); + break; + case 4: + bus_space_write_4(bst, bsh, offset, val); + break; + default: + ACPI_DEVPRINTF("acpi_register_output(): invalid size\n"); + break; + } +} + +static __inline void +acpi_io_mirreg(acpi_softc_t *sc, boolean_t io, u_int32_t *data, + int res, int altres, int offset, int size) +{ + u_int32_t result; + + if (io == ACPI_REGISTER_INPUT) { + acpi_register_input(sc, res, offset, &result, size); + *data = result; + acpi_register_input(sc, altres, offset, &result, size); + *data |= result; + } else { + acpi_register_output(sc, res, offset, data, size); + acpi_register_output(sc, altres, offset, data, size); + } + + return; +} + +void +acpi_enable_disable(acpi_softc_t *sc, boolean_t enable) +{ + u_int8_t val; + + val = enable ? sc->facp_body->acpi_enable : sc->facp_body->acpi_disable; + bus_space_write_1(sc->iores[ACPI_RES_SMI_CMD].btag, + sc->iores[ACPI_RES_SMI_CMD].bhandle, + 0, val); + sc->enabled = enable; + + ACPI_DEBUGPRINT("acpi_enable_disable(%d) = (%x)\n", enable, val); +} + +void +acpi_io_pm1_status(acpi_softc_t *sc, boolean_t io, u_int32_t *status) +{ + int size; + struct FACPbody *facp; + + facp = sc->facp_body; + size = facp->pm1_evt_len / 2; + acpi_io_mirreg(sc, io, status, ACPI_RES_PM1A_EVT, ACPI_RES_PM1B_EVT, 0, size); + + ACPI_DEBUGPRINT("acpi_io_pm1_status(%d) = (%x)\n", io, *status); +} + +void +acpi_io_pm1_enable(acpi_softc_t *sc, boolean_t io, u_int32_t *enable) +{ + int size; + struct FACPbody *facp; + + facp = sc->facp_body; + size = facp->pm1_evt_len / 2; + acpi_io_mirreg(sc, io, enable, ACPI_RES_PM1A_EVT, ACPI_RES_PM1B_EVT, size, size); + + ACPI_DEBUGPRINT("acpi_io_pm1_enable(%d) = (%x)\n", io, *enable); +} + +/* + * PM1 is awkward because the SLP_TYP bits are not common between the two registers. + * A better interface than this might pass the SLP_TYP bits separately. + */ +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; + u_int32_t result; + + facp = sc->facp_body; + + if (io == ACPI_REGISTER_INPUT) { + acpi_register_input(sc, ACPI_RES_PM1A_CNT, 0, &result, facp->pm1_cnt_len); + *value_a = result; + acpi_register_input(sc, ACPI_RES_PM1B_CNT, 0, &result, facp->pm1_cnt_len); + *value_a |= result; + *value_a &= ~ACPI_CNT_SLP_TYPX; /* mask the SLP_TYP bits */ + } else { + acpi_register_output(sc, ACPI_RES_PM1A_CNT, 0, value_a, facp->pm1_cnt_len); + acpi_register_output(sc, ACPI_RES_PM1B_CNT, 0, value_b, facp->pm1_cnt_len); + } + + ACPI_DEBUGPRINT("acpi_io_pm1_control(%d) = (%x, %x)\n", io, *value_a, *value_b); +} + +void +acpi_io_pm2_control(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + int size; + struct FACPbody *facp; + + facp = sc->facp_body; + size = facp->pm2_cnt_len; + + if (size == 0) /* port is optional */ + return; + + if (io == ACPI_REGISTER_INPUT) { + acpi_register_input(sc, ACPI_RES_PM2_CNT, 0, val, size); + } else { + acpi_register_output(sc, ACPI_RES_PM2_CNT, 0, val, size); + } + + ACPI_DEBUGPRINT("acpi_io_pm2_control(%d) = (%x)\n", io, *val); + + return; +} + +void +acpi_io_pm_timer(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + if (io == ACPI_REGISTER_INPUT) { + acpi_register_input(sc, ACPI_RES_PM_TMR, 0, val, sizeof(u_int32_t)); + + ACPI_DEBUGPRINT("acpi_io_pm_timer(%d) = (%x)\n", io, *val); + } +} + +void +acpi_io_gpe0_status(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + int size; + struct FACPbody *facp; + + facp = sc->facp_body; + size = facp->gpe0_len / 2; + + if (size == 0) /* port is optional */ + return; + + if (io == ACPI_REGISTER_INPUT) { + acpi_register_input(sc, ACPI_RES_GPE0, 0, val, size); + } else { + acpi_register_output(sc, ACPI_RES_GPE0, 0, val, size); + } + + ACPI_DEBUGPRINT("acpi_io_gpe0_status(%d) = (%x)\n", io, *val); +} + +void +acpi_io_gpe0_enable(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + int size; + struct FACPbody *facp; + + facp = sc->facp_body; + size = facp->gpe0_len / 2; + + if (size == 0) /* port is optional */ + return; + + if (io == ACPI_REGISTER_INPUT) { + acpi_register_input(sc, ACPI_RES_GPE0, size, val, size); + } else { + acpi_register_output(sc, ACPI_RES_GPE0, size, val, size); + } + + ACPI_DEBUGPRINT("acpi_io_gpe0_enable(%d) = (%x)\n", io, *val); +} + +void +acpi_io_gpe1_status(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + int size; + struct FACPbody *facp; + + facp = sc->facp_body; + size = facp->gpe1_len / 2; + + if (size == 0) /* port is optional */ + return; + + if (io == ACPI_REGISTER_INPUT) { + acpi_register_input(sc, ACPI_RES_GPE1, 0, val, size); + } else { + acpi_register_output(sc, ACPI_RES_GPE1, 0, val, size); + } + + ACPI_DEBUGPRINT("acpi_io_gpe1_status(%d) = (%x)\n", io, *val); +} + +void +acpi_io_gpe1_enable(acpi_softc_t *sc, boolean_t io, u_int32_t *val) +{ + int size; + struct FACPbody *facp; + + facp = sc->facp_body; + size = facp->gpe1_len / 2; + + if (size == 0) /* port is optional */ + return; + + if (io == ACPI_REGISTER_INPUT) { + acpi_register_input(sc, ACPI_RES_GPE1, size, val, size); + } else { + acpi_register_output(sc, ACPI_RES_GPE1, size, val, size); + } + + ACPI_DEBUGPRINT("acpi_io_gpe0_enable(%d) = (%x)\n", io, *val); +} + +void +acpi_gpe_enable_bit(acpi_softc_t *sc, u_int32_t bit, boolean_t on_off) +{ + u_int32_t value; + int res; + + /* + * Is the bit in the first GPE port? + */ + if (bit < ((sc->facp_body->gpe0_len / 2) * 8)) { + res = ACPI_RES_GPE0; + } else { + /* + * Is the bit in the second GPE port? + */ + bit -= sc->facp_body->gpe1_base; + if (bit < ((sc->facp_body->gpe1_len / 2) * 8)) { + res = ACPI_RES_GPE1; + } else { + return; /* do nothing */ + } + } + + switch (res) { + case ACPI_RES_GPE0: + acpi_io_gpe0_enable(sc, ACPI_REGISTER_INPUT, &value); + break; + case ACPI_RES_GPE1: + acpi_io_gpe1_enable(sc, ACPI_REGISTER_INPUT, &value); + break; + } + value = (value & ~(1 << bit)) | (on_off ? (1 << bit) : 0); + switch (res) { + case ACPI_RES_GPE0: + acpi_io_gpe0_enable(sc, ACPI_REGISTER_OUTPUT, &value); + break; + case ACPI_RES_GPE1: + acpi_io_gpe1_enable(sc, ACPI_REGISTER_OUTPUT, &value); + break; + } +} + |