acpi_apm.c revision 119944
185556Siwasaki/*- 285556Siwasaki * Copyright (c) 2001 Mitsuru IWASAKI 385556Siwasaki * All rights reserved. 485556Siwasaki * 585556Siwasaki * Redistribution and use in source and binary forms, with or without 685556Siwasaki * modification, are permitted provided that the following conditions 785556Siwasaki * are met: 885556Siwasaki * 1. Redistributions of source code must retain the above copyright 985556Siwasaki * notice, this list of conditions and the following disclaimer. 1085556Siwasaki * 2. Redistributions in binary form must reproduce the above copyright 1185556Siwasaki * notice, this list of conditions and the following disclaimer in the 1285556Siwasaki * documentation and/or other materials provided with the distribution. 1385556Siwasaki * 1485556Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1585556Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1685556Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1785556Siwasaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1885556Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1985556Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2085556Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2185556Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2285556Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2385556Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2485556Siwasaki * SUCH DAMAGE. 2585556Siwasaki */ 2685556Siwasaki 27115681Sobrien#include <sys/cdefs.h> 28115681Sobrien__FBSDID("$FreeBSD: head/sys/i386/acpica/acpi_machdep.c 119944 2003-09-10 05:29:30Z jhb $"); 29115681Sobrien 3085556Siwasaki#include <sys/param.h> 3185556Siwasaki#include <sys/bus.h> 3285556Siwasaki#include <sys/conf.h> 3385556Siwasaki#include <sys/fcntl.h> 3485556Siwasaki#include <sys/uio.h> 3585556Siwasaki 3685556Siwasaki#include "acpi.h" 3785556Siwasaki 3885556Siwasaki#include <dev/acpica/acpivar.h> 3985556Siwasaki#include <dev/acpica/acpiio.h> 4085556Siwasaki 4185556Siwasakistatic device_t acpi_dev; 4285556Siwasaki 4385556Siwasaki/* 4485556Siwasaki * APM driver emulation 4585556Siwasaki */ 4685556Siwasaki 47105276Sjhb#if __FreeBSD_version < 500000 48105276Sjhb#include <sys/select.h> 49105276Sjhb#else 5085556Siwasaki#include <sys/selinfo.h> 51105276Sjhb#endif 5285556Siwasaki 5385556Siwasaki#include <machine/apm_bios.h> 5485556Siwasaki#include <machine/pc/bios.h> 5585556Siwasaki 56114977Sjhb#if __FreeBSD_version < 500000 57114977Sjhb#include <i386/apm/apm.h> 58114977Sjhb#else 59112551Smdodd#include <i386/bios/apm.h> 60114977Sjhb#endif 6185556Siwasaki 6285556Siwasakistatic struct apm_softc apm_softc; 6385556Siwasaki 6485556Siwasakistatic d_open_t apmopen; 6585556Siwasakistatic d_close_t apmclose; 6685556Siwasakistatic d_write_t apmwrite; 6785556Siwasakistatic d_ioctl_t apmioctl; 6885556Siwasakistatic d_poll_t apmpoll; 6985556Siwasaki 7085556Siwasaki#define CDEV_MAJOR 39 7185556Siwasakistatic struct cdevsw apm_cdevsw = { 72111815Sphk .d_open = apmopen, 73111815Sphk .d_close = apmclose, 74111815Sphk .d_write = apmwrite, 75111815Sphk .d_ioctl = apmioctl, 76111815Sphk .d_poll = apmpoll, 77111815Sphk .d_name = "apm", 78111815Sphk .d_maj = CDEV_MAJOR, 7985556Siwasaki}; 8085556Siwasaki 81119944Sjhbstatic int intr_model = ACPI_INTR_PIC; 82119944Sjhb 8385556Siwasakistatic int 8485556Siwasakiacpi_capm_convert_battstate(struct acpi_battinfo *battp) 8585556Siwasaki{ 8685556Siwasaki int state; 8785556Siwasaki 8885556Siwasaki state = 0xff; /* XXX unknown */ 8985556Siwasaki 9085556Siwasaki if (battp->state & ACPI_BATT_STAT_DISCHARG) { 91119530Snjl if (battp->cap >= 50) 9285556Siwasaki state = 0; /* high */ 93119530Snjl else 9485556Siwasaki state = 1; /* low */ 9585556Siwasaki } 96119530Snjl if (battp->state & ACPI_BATT_STAT_CRITICAL) 9785556Siwasaki state = 2; /* critical */ 98119530Snjl if (battp->state & ACPI_BATT_STAT_CHARGING) 9985556Siwasaki state = 3; /* charging */ 100119530Snjl 10185556Siwasaki return (state); 10285556Siwasaki} 10385556Siwasaki 10485556Siwasakistatic int 10585556Siwasakiacpi_capm_convert_battflags(struct acpi_battinfo *battp) 10685556Siwasaki{ 10785556Siwasaki int flags; 10885556Siwasaki 10985556Siwasaki flags = 0; 11085556Siwasaki 11185556Siwasaki if (battp->cap >= 50) { 11285556Siwasaki flags |= APM_BATT_HIGH; 11385556Siwasaki } else { 114119530Snjl if (battp->state & ACPI_BATT_STAT_CRITICAL) 11585556Siwasaki flags |= APM_BATT_CRITICAL; 116119530Snjl else 11785556Siwasaki flags |= APM_BATT_LOW; 11885556Siwasaki } 119119530Snjl if (battp->state & ACPI_BATT_STAT_CHARGING) 12085556Siwasaki flags |= APM_BATT_CHARGING; 121119530Snjl if (battp->state == ACPI_BATT_STAT_NOT_PRESENT) 12285556Siwasaki flags = APM_BATT_NOT_PRESENT; 12385556Siwasaki 12485556Siwasaki return (flags); 12585556Siwasaki} 12685556Siwasaki 12785556Siwasakistatic int 12885556Siwasakiacpi_capm_get_info(apm_info_t aip) 12985556Siwasaki{ 13085556Siwasaki int acline; 13185556Siwasaki struct acpi_battinfo batt; 13285556Siwasaki 13385556Siwasaki aip->ai_infoversion = 1; 13485556Siwasaki aip->ai_major = 1; 13585556Siwasaki aip->ai_minor = 2; 13685556Siwasaki aip->ai_status = apm_softc.active; 13785556Siwasaki aip->ai_capabilities= 0xff00; /* XXX unknown */ 13885556Siwasaki 139119530Snjl if (acpi_acad_get_acline(&acline)) 14085556Siwasaki aip->ai_acline = 0xff; /* unknown */ 141119530Snjl else 14285556Siwasaki aip->ai_acline = acline; /* on/off */ 14385556Siwasaki 14485556Siwasaki if (acpi_battery_get_battinfo(-1, &batt)) { 14585556Siwasaki aip->ai_batt_stat = 0xff; /* unknown */ 14685556Siwasaki aip->ai_batt_life = 0xff; /* unknown */ 14785556Siwasaki aip->ai_batt_time = -1; /* unknown */ 14885556Siwasaki aip->ai_batteries = 0; 14985556Siwasaki } else { 15085556Siwasaki aip->ai_batt_stat = acpi_capm_convert_battstate(&batt); 15185556Siwasaki aip->ai_batt_life = batt.cap; 15285556Siwasaki aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60; 15385556Siwasaki aip->ai_batteries = acpi_battery_get_units(); 15485556Siwasaki } 15585556Siwasaki 15685556Siwasaki return (0); 15785556Siwasaki} 15885556Siwasaki 15985556Siwasakistatic int 16085556Siwasakiacpi_capm_get_pwstatus(apm_pwstatus_t app) 16185556Siwasaki{ 16285556Siwasaki int batt_unit; 16385556Siwasaki int acline; 16485556Siwasaki struct acpi_battinfo batt; 16585556Siwasaki 16685556Siwasaki if (app->ap_device != PMDV_ALLDEV && 16785556Siwasaki (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL)) { 16885556Siwasaki return (1); 16985556Siwasaki } 17085556Siwasaki 171119530Snjl if (app->ap_device == PMDV_ALLDEV) 17285556Siwasaki batt_unit = -1; /* all units */ 173119530Snjl else 17485556Siwasaki batt_unit = app->ap_device - PMDV_BATT0; 17585556Siwasaki 176119530Snjl if (acpi_battery_get_battinfo(batt_unit, &batt)) 17785556Siwasaki return (1); 17885556Siwasaki 17985556Siwasaki app->ap_batt_stat = acpi_capm_convert_battstate(&batt); 18085556Siwasaki app->ap_batt_flag = acpi_capm_convert_battflags(&batt); 18185556Siwasaki app->ap_batt_life = batt.cap; 18285556Siwasaki app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60; 18385556Siwasaki 184119530Snjl if (acpi_acad_get_acline(&acline)) 18585556Siwasaki app->ap_acline = 0xff; /* unknown */ 186119530Snjl else 18785556Siwasaki app->ap_acline = acline; /* on/off */ 18885556Siwasaki 18985556Siwasaki return (0); 19085556Siwasaki} 19185556Siwasaki 19285556Siwasakistatic int 193104727Sjhbapmopen(dev_t dev, int flag, int fmt, d_thread_t *td) 19485556Siwasaki{ 19585556Siwasaki return (0); 19685556Siwasaki} 19785556Siwasaki 19885556Siwasakistatic int 199104727Sjhbapmclose(dev_t dev, int flag, int fmt, d_thread_t *td) 20085556Siwasaki{ 20185556Siwasaki return (0); 20285556Siwasaki} 20385556Siwasaki 20485556Siwasakistatic int 205104727Sjhbapmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, d_thread_t *td) 20685556Siwasaki{ 20785556Siwasaki int error = 0; 20885556Siwasaki struct acpi_softc *acpi_sc; 20985556Siwasaki struct apm_info info; 21085556Siwasaki apm_info_old_t aiop; 21185556Siwasaki 212119530Snjl if ((acpi_sc = device_get_softc(acpi_dev)) == NULL) 21385556Siwasaki return (ENXIO); 21485556Siwasaki 21585556Siwasaki switch (cmd) { 21685556Siwasaki case APMIO_SUSPEND: 217119530Snjl if ((flag & FWRITE) == 0) 21885556Siwasaki return (EPERM); 21985556Siwasaki if (apm_softc.active) 22085556Siwasaki acpi_SetSleepState(acpi_sc, acpi_sc->acpi_suspend_sx); 22185556Siwasaki else 22285556Siwasaki error = EINVAL; 22385556Siwasaki break; 22485556Siwasaki case APMIO_STANDBY: 225119530Snjl if ((flag & FWRITE) == 0) 22685556Siwasaki return (EPERM); 22785556Siwasaki if (apm_softc.active) 22885556Siwasaki acpi_SetSleepState(acpi_sc, acpi_sc->acpi_standby_sx); 22985556Siwasaki else 23085556Siwasaki error = EINVAL; 23185556Siwasaki break; 23285556Siwasaki case APMIO_GETINFO_OLD: 23385556Siwasaki if (acpi_capm_get_info(&info)) 23485556Siwasaki error = ENXIO; 23585556Siwasaki aiop = (apm_info_old_t)addr; 23685556Siwasaki aiop->ai_major = info.ai_major; 23785556Siwasaki aiop->ai_minor = info.ai_minor; 23885556Siwasaki aiop->ai_acline = info.ai_acline; 23985556Siwasaki aiop->ai_batt_stat = info.ai_batt_stat; 24085556Siwasaki aiop->ai_batt_life = info.ai_batt_life; 24185556Siwasaki aiop->ai_status = info.ai_status; 24285556Siwasaki break; 24385556Siwasaki case APMIO_GETINFO: 24485556Siwasaki if (acpi_capm_get_info((apm_info_t)addr)) 24585556Siwasaki error = ENXIO; 24685556Siwasaki break; 24785556Siwasaki case APMIO_GETPWSTATUS: 24885556Siwasaki if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr)) 24985556Siwasaki error = ENXIO; 25085556Siwasaki break; 25185556Siwasaki case APMIO_ENABLE: 252119530Snjl if ((flag & FWRITE) == 0) 25385556Siwasaki return (EPERM); 25485556Siwasaki apm_softc.active = 1; 25585556Siwasaki break; 25685556Siwasaki case APMIO_DISABLE: 257119530Snjl if ((flag & FWRITE) == 0) 25885556Siwasaki return (EPERM); 25985556Siwasaki apm_softc.active = 0; 26085556Siwasaki break; 26185556Siwasaki case APMIO_HALTCPU: 26285556Siwasaki break; 26385556Siwasaki case APMIO_NOTHALTCPU: 26485556Siwasaki break; 26585556Siwasaki case APMIO_DISPLAY: 266119530Snjl if ((flag & FWRITE) == 0) 26785556Siwasaki return (EPERM); 26885556Siwasaki break; 26985556Siwasaki case APMIO_BIOS: 270119530Snjl if ((flag & FWRITE) == 0) 27185556Siwasaki return (EPERM); 27285556Siwasaki bzero(addr, sizeof(struct apm_bios_arg)); 27385556Siwasaki break; 27485556Siwasaki default: 27585556Siwasaki error = EINVAL; 27685556Siwasaki break; 27785556Siwasaki } 27885556Siwasaki 27985556Siwasaki return (error); 28085556Siwasaki} 28185556Siwasaki 28285556Siwasakistatic int 28385556Siwasakiapmwrite(dev_t dev, struct uio *uio, int ioflag) 28485556Siwasaki{ 28585556Siwasaki return (uio->uio_resid); 28685556Siwasaki} 28785556Siwasaki 28885556Siwasakistatic int 289104727Sjhbapmpoll(dev_t dev, int events, d_thread_t *td) 29085556Siwasaki{ 29185556Siwasaki return (0); 29285556Siwasaki} 29385556Siwasaki 29485556Siwasakistatic void 29585556Siwasakiacpi_capm_init(struct acpi_softc *sc) 29685556Siwasaki{ 29785556Siwasaki make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm"); 29885556Siwasaki} 29985556Siwasaki 30085556Siwasakiint 30185556Siwasakiacpi_machdep_init(device_t dev) 30285556Siwasaki{ 30385556Siwasaki struct acpi_softc *sc; 30485556Siwasaki 30585556Siwasaki acpi_dev = dev; 306119530Snjl if ((sc = device_get_softc(acpi_dev)) == NULL) 30785556Siwasaki return (ENXIO); 30885556Siwasaki 309104223Sjhb /* 310104223Sjhb * XXX: Prevent the PnP BIOS code from interfering with 311104223Sjhb * our own scan of ISA devices. 312104223Sjhb */ 313104223Sjhb PnPBIOStable = NULL; 314104223Sjhb 31585556Siwasaki acpi_capm_init(sc); 31685556Siwasaki 31785556Siwasaki acpi_install_wakeup_handler(sc); 31885556Siwasaki 319119944Sjhb if (intr_model != ACPI_INTR_PIC) 320119944Sjhb acpi_SetIntrModel(intr_model); 32185556Siwasaki return (0); 32285556Siwasaki} 323119944Sjhb 324119944Sjhbvoid 325119944Sjhbacpi_SetDefaultIntrModel(int model) 326119944Sjhb{ 327119944Sjhb 328119944Sjhb intr_model = model; 329119944Sjhb} 330