acpi_machdep.c revision 85556
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 * $FreeBSD: head/sys/amd64/acpica/acpi_machdep.c 85556 2001-10-26 17:43:05Z iwasaki $ 2785556Siwasaki */ 2885556Siwasaki 2985556Siwasaki#include <sys/param.h> 3085556Siwasaki#include <sys/bus.h> 3185556Siwasaki#include <sys/conf.h> 3285556Siwasaki#include <sys/fcntl.h> 3385556Siwasaki#include <sys/uio.h> 3485556Siwasaki 3585556Siwasaki#include "acpi.h" 3685556Siwasaki 3785556Siwasaki#include <dev/acpica/acpivar.h> 3885556Siwasaki#include <dev/acpica/acpiio.h> 3985556Siwasaki 4085556Siwasakistatic device_t acpi_dev; 4185556Siwasaki 4285556Siwasaki/* 4385556Siwasaki * APM driver emulation 4485556Siwasaki */ 4585556Siwasaki 4685556Siwasaki#include <sys/selinfo.h> 4785556Siwasaki 4885556Siwasaki#include <machine/apm_bios.h> 4985556Siwasaki#include <machine/pc/bios.h> 5085556Siwasaki 5185556Siwasaki#include <i386/apm/apm.h> 5285556Siwasaki 5385556Siwasakistatic struct apm_softc apm_softc; 5485556Siwasaki 5585556Siwasakistatic d_open_t apmopen; 5685556Siwasakistatic d_close_t apmclose; 5785556Siwasakistatic d_write_t apmwrite; 5885556Siwasakistatic d_ioctl_t apmioctl; 5985556Siwasakistatic d_poll_t apmpoll; 6085556Siwasaki 6185556Siwasaki#define CDEV_MAJOR 39 6285556Siwasakistatic struct cdevsw apm_cdevsw = { 6385556Siwasaki /* open */ apmopen, 6485556Siwasaki /* close */ apmclose, 6585556Siwasaki /* read */ noread, 6685556Siwasaki /* write */ apmwrite, 6785556Siwasaki /* ioctl */ apmioctl, 6885556Siwasaki /* poll */ apmpoll, 6985556Siwasaki /* mmap */ nommap, 7085556Siwasaki /* strategy */ nostrategy, 7185556Siwasaki /* name */ "apm", 7285556Siwasaki /* maj */ CDEV_MAJOR, 7385556Siwasaki /* dump */ nodump, 7485556Siwasaki /* psize */ nopsize, 7585556Siwasaki /* flags */ 0, 7685556Siwasaki}; 7785556Siwasaki 7885556Siwasakistatic int 7985556Siwasakiacpi_capm_convert_battstate(struct acpi_battinfo *battp) 8085556Siwasaki{ 8185556Siwasaki int state; 8285556Siwasaki 8385556Siwasaki state = 0xff; /* XXX unknown */ 8485556Siwasaki 8585556Siwasaki if (battp->state & ACPI_BATT_STAT_DISCHARG) { 8685556Siwasaki if (battp->cap >= 50) { 8785556Siwasaki state = 0; /* high */ 8885556Siwasaki } else { 8985556Siwasaki state = 1; /* low */ 9085556Siwasaki } 9185556Siwasaki } 9285556Siwasaki if (battp->state & ACPI_BATT_STAT_CRITICAL) { 9385556Siwasaki state = 2; /* critical */ 9485556Siwasaki } 9585556Siwasaki if (battp->state & ACPI_BATT_STAT_CHARGING) { 9685556Siwasaki state = 3; /* charging */ 9785556Siwasaki } 9885556Siwasaki return (state); 9985556Siwasaki} 10085556Siwasaki 10185556Siwasakistatic int 10285556Siwasakiacpi_capm_convert_battflags(struct acpi_battinfo *battp) 10385556Siwasaki{ 10485556Siwasaki int flags; 10585556Siwasaki 10685556Siwasaki flags = 0; 10785556Siwasaki 10885556Siwasaki if (battp->cap >= 50) { 10985556Siwasaki flags |= APM_BATT_HIGH; 11085556Siwasaki } else { 11185556Siwasaki if (battp->state & ACPI_BATT_STAT_CRITICAL) { 11285556Siwasaki flags |= APM_BATT_CRITICAL; 11385556Siwasaki } else { 11485556Siwasaki flags |= APM_BATT_LOW; 11585556Siwasaki } 11685556Siwasaki } 11785556Siwasaki if (battp->state & ACPI_BATT_STAT_CHARGING) { 11885556Siwasaki flags |= APM_BATT_CHARGING; 11985556Siwasaki } 12085556Siwasaki if (battp->state == ACPI_BATT_STAT_NOT_PRESENT) { 12185556Siwasaki flags = APM_BATT_NOT_PRESENT; 12285556Siwasaki } 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 13985556Siwasaki if (acpi_acad_get_acline(&acline)) { 14085556Siwasaki aip->ai_acline = 0xff; /* unknown */ 14185556Siwasaki } else { 14285556Siwasaki aip->ai_acline = acline; /* on/off */ 14385556Siwasaki } 14485556Siwasaki 14585556Siwasaki if (acpi_battery_get_battinfo(-1, &batt)) { 14685556Siwasaki aip->ai_batt_stat = 0xff; /* unknown */ 14785556Siwasaki aip->ai_batt_life = 0xff; /* unknown */ 14885556Siwasaki aip->ai_batt_time = -1; /* unknown */ 14985556Siwasaki aip->ai_batteries = 0; 15085556Siwasaki } else { 15185556Siwasaki aip->ai_batt_stat = acpi_capm_convert_battstate(&batt); 15285556Siwasaki aip->ai_batt_life = batt.cap; 15385556Siwasaki aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60; 15485556Siwasaki aip->ai_batteries = acpi_battery_get_units(); 15585556Siwasaki } 15685556Siwasaki 15785556Siwasaki return (0); 15885556Siwasaki} 15985556Siwasaki 16085556Siwasakistatic int 16185556Siwasakiacpi_capm_get_pwstatus(apm_pwstatus_t app) 16285556Siwasaki{ 16385556Siwasaki int batt_unit; 16485556Siwasaki int acline; 16585556Siwasaki struct acpi_battinfo batt; 16685556Siwasaki 16785556Siwasaki if (app->ap_device != PMDV_ALLDEV && 16885556Siwasaki (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL)) { 16985556Siwasaki return (1); 17085556Siwasaki } 17185556Siwasaki 17285556Siwasaki if (app->ap_device == PMDV_ALLDEV) { 17385556Siwasaki batt_unit = -1; /* all units */ 17485556Siwasaki } else { 17585556Siwasaki batt_unit = app->ap_device - PMDV_BATT0; 17685556Siwasaki } 17785556Siwasaki 17885556Siwasaki if (acpi_battery_get_battinfo(batt_unit, &batt)) { 17985556Siwasaki return (1); 18085556Siwasaki } 18185556Siwasaki 18285556Siwasaki app->ap_batt_stat = acpi_capm_convert_battstate(&batt); 18385556Siwasaki app->ap_batt_flag = acpi_capm_convert_battflags(&batt); 18485556Siwasaki app->ap_batt_life = batt.cap; 18585556Siwasaki app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60; 18685556Siwasaki 18785556Siwasaki if (acpi_acad_get_acline(&acline)) { 18885556Siwasaki app->ap_acline = 0xff; /* unknown */ 18985556Siwasaki } else { 19085556Siwasaki app->ap_acline = acline; /* on/off */ 19185556Siwasaki } 19285556Siwasaki 19385556Siwasaki return (0); 19485556Siwasaki} 19585556Siwasaki 19685556Siwasakistatic int 19785556Siwasakiapmopen(dev_t dev, int flag, int fmt, struct thread *td) 19885556Siwasaki{ 19985556Siwasaki return (0); 20085556Siwasaki} 20185556Siwasaki 20285556Siwasakistatic int 20385556Siwasakiapmclose(dev_t dev, int flag, int fmt, struct thread *td) 20485556Siwasaki{ 20585556Siwasaki return (0); 20685556Siwasaki} 20785556Siwasaki 20885556Siwasakistatic int 20985556Siwasakiapmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 21085556Siwasaki{ 21185556Siwasaki int error = 0; 21285556Siwasaki struct acpi_softc *acpi_sc; 21385556Siwasaki struct apm_info info; 21485556Siwasaki apm_info_old_t aiop; 21585556Siwasaki 21685556Siwasaki if ((acpi_sc = device_get_softc(acpi_dev)) == NULL) { 21785556Siwasaki return (ENXIO); 21885556Siwasaki } 21985556Siwasaki 22085556Siwasaki switch (cmd) { 22185556Siwasaki case APMIO_SUSPEND: 22285556Siwasaki if (!(flag & FWRITE)) 22385556Siwasaki return (EPERM); 22485556Siwasaki if (apm_softc.active) 22585556Siwasaki acpi_SetSleepState(acpi_sc, acpi_sc->acpi_suspend_sx); 22685556Siwasaki else 22785556Siwasaki error = EINVAL; 22885556Siwasaki break; 22985556Siwasaki 23085556Siwasaki case APMIO_STANDBY: 23185556Siwasaki if (!(flag & FWRITE)) 23285556Siwasaki return (EPERM); 23385556Siwasaki if (apm_softc.active) 23485556Siwasaki acpi_SetSleepState(acpi_sc, acpi_sc->acpi_standby_sx); 23585556Siwasaki else 23685556Siwasaki error = EINVAL; 23785556Siwasaki break; 23885556Siwasaki 23985556Siwasaki case APMIO_GETINFO_OLD: 24085556Siwasaki if (acpi_capm_get_info(&info)) 24185556Siwasaki error = ENXIO; 24285556Siwasaki aiop = (apm_info_old_t)addr; 24385556Siwasaki aiop->ai_major = info.ai_major; 24485556Siwasaki aiop->ai_minor = info.ai_minor; 24585556Siwasaki aiop->ai_acline = info.ai_acline; 24685556Siwasaki aiop->ai_batt_stat = info.ai_batt_stat; 24785556Siwasaki aiop->ai_batt_life = info.ai_batt_life; 24885556Siwasaki aiop->ai_status = info.ai_status; 24985556Siwasaki break; 25085556Siwasaki 25185556Siwasaki case APMIO_GETINFO: 25285556Siwasaki if (acpi_capm_get_info((apm_info_t)addr)) 25385556Siwasaki error = ENXIO; 25485556Siwasaki 25585556Siwasaki break; 25685556Siwasaki 25785556Siwasaki case APMIO_GETPWSTATUS: 25885556Siwasaki if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr)) 25985556Siwasaki error = ENXIO; 26085556Siwasaki break; 26185556Siwasaki 26285556Siwasaki case APMIO_ENABLE: 26385556Siwasaki if (!(flag & FWRITE)) 26485556Siwasaki return (EPERM); 26585556Siwasaki apm_softc.active = 1; 26685556Siwasaki break; 26785556Siwasaki 26885556Siwasaki case APMIO_DISABLE: 26985556Siwasaki if (!(flag & FWRITE)) 27085556Siwasaki return (EPERM); 27185556Siwasaki apm_softc.active = 0; 27285556Siwasaki break; 27385556Siwasaki 27485556Siwasaki case APMIO_HALTCPU: 27585556Siwasaki break; 27685556Siwasaki 27785556Siwasaki case APMIO_NOTHALTCPU: 27885556Siwasaki break; 27985556Siwasaki 28085556Siwasaki case APMIO_DISPLAY: 28185556Siwasaki if (!(flag & FWRITE)) 28285556Siwasaki return (EPERM); 28385556Siwasaki break; 28485556Siwasaki 28585556Siwasaki case APMIO_BIOS: 28685556Siwasaki if (!(flag & FWRITE)) 28785556Siwasaki return (EPERM); 28885556Siwasaki bzero(addr, sizeof(struct apm_bios_arg)); 28985556Siwasaki break; 29085556Siwasaki 29185556Siwasaki default: 29285556Siwasaki error = EINVAL; 29385556Siwasaki break; 29485556Siwasaki } 29585556Siwasaki 29685556Siwasaki return (error); 29785556Siwasaki} 29885556Siwasaki 29985556Siwasakistatic int 30085556Siwasakiapmwrite(dev_t dev, struct uio *uio, int ioflag) 30185556Siwasaki{ 30285556Siwasaki 30385556Siwasaki return (uio->uio_resid); 30485556Siwasaki} 30585556Siwasaki 30685556Siwasakistatic int 30785556Siwasakiapmpoll(dev_t dev, int events, struct thread *td) 30885556Siwasaki{ 30985556Siwasaki return (0); 31085556Siwasaki} 31185556Siwasaki 31285556Siwasakistatic void 31385556Siwasakiacpi_capm_init(struct acpi_softc *sc) 31485556Siwasaki{ 31585556Siwasaki 31685556Siwasaki make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm"); 31785556Siwasaki} 31885556Siwasaki 31985556Siwasakiint 32085556Siwasakiacpi_machdep_init(device_t dev) 32185556Siwasaki{ 32285556Siwasaki struct acpi_softc *sc; 32385556Siwasaki 32485556Siwasaki acpi_dev = dev; 32585556Siwasaki if ((sc = device_get_softc(acpi_dev)) == NULL) { 32685556Siwasaki return (ENXIO); 32785556Siwasaki } 32885556Siwasaki 32985556Siwasaki acpi_capm_init(sc); 33085556Siwasaki 33185556Siwasaki acpi_install_wakeup_handler(sc); 33285556Siwasaki 33385556Siwasaki return (0); 33485556Siwasaki} 33585556Siwasaki 336