acpi_apm.c revision 193951
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 193951 2009-06-10 20:59:32Z kib $"); 29115681Sobrien 3085556Siwasaki#include <sys/param.h> 3185556Siwasaki#include <sys/bus.h> 32168191Sjhb#include <sys/condvar.h> 3385556Siwasaki#include <sys/conf.h> 3485556Siwasaki#include <sys/fcntl.h> 35121743Siwasaki#include <sys/kernel.h> 36170976Snjl#include <sys/malloc.h> 37177157Sjhb#include <sys/module.h> 38170976Snjl#include <sys/poll.h> 39121743Siwasaki#include <sys/sysctl.h> 4085556Siwasaki#include <sys/uio.h> 41131312Snjl#include <vm/vm.h> 42131312Snjl#include <vm/pmap.h> 4385556Siwasaki 44193530Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193530Sjkim 4685556Siwasaki#include <dev/acpica/acpivar.h> 4785556Siwasaki#include <dev/acpica/acpiio.h> 4885556Siwasaki 49177157Sjhb#include <machine/nexusvar.h> 50177157Sjhb 5185556Siwasaki/* 5285556Siwasaki * APM driver emulation 5385556Siwasaki */ 5485556Siwasaki 5585556Siwasaki#include <machine/apm_bios.h> 5685556Siwasaki#include <machine/pc/bios.h> 5785556Siwasaki 58112551Smdodd#include <i386/bios/apm.h> 5985556Siwasaki 60159477SnjlSYSCTL_DECL(_debug_acpi); 61159477Snjl 62159409Snjluint32_t acpi_resume_beep; 63159477SnjlTUNABLE_INT("debug.acpi.resume_beep", &acpi_resume_beep); 64159477SnjlSYSCTL_UINT(_debug_acpi, OID_AUTO, resume_beep, CTLFLAG_RW, &acpi_resume_beep, 65159477Snjl 0, "Beep the PC speaker when resuming"); 66159409Snjluint32_t acpi_reset_video; 67121830SnjlTUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video); 68121743Siwasaki 69128975Snjlstatic int intr_model = ACPI_INTR_PIC; 70132619Snjlstatic int apm_active; 71170976Snjlstatic struct clonedevs *apm_clones; 7285556Siwasaki 73170976SnjlMALLOC_DEFINE(M_APMDEV, "apmdev", "APM device emulation"); 7485556Siwasaki 75170976Snjlstatic d_open_t apmopen; 76170976Snjlstatic d_close_t apmclose; 77170976Snjlstatic d_write_t apmwrite; 78170976Snjlstatic d_ioctl_t apmioctl; 79170976Snjlstatic d_poll_t apmpoll; 80170976Snjlstatic d_kqfilter_t apmkqfilter; 81170976Snjlstatic void apmreadfiltdetach(struct knote *kn); 82170976Snjlstatic int apmreadfilt(struct knote *kn, long hint); 83170976Snjlstatic struct filterops apm_readfiltops = 84170976Snjl { 1, NULL, apmreadfiltdetach, apmreadfilt }; 85170976Snjl 8685556Siwasakistatic struct cdevsw apm_cdevsw = { 87126080Sphk .d_version = D_VERSION, 88179726Sed .d_flags = D_TRACKCLOSE | D_NEEDMINOR, 89111815Sphk .d_open = apmopen, 90111815Sphk .d_close = apmclose, 91111815Sphk .d_write = apmwrite, 92111815Sphk .d_ioctl = apmioctl, 93111815Sphk .d_poll = apmpoll, 94111815Sphk .d_name = "apm", 95170976Snjl .d_kqfilter = apmkqfilter 9685556Siwasaki}; 9785556Siwasaki 9885556Siwasakistatic int 9985556Siwasakiacpi_capm_convert_battstate(struct acpi_battinfo *battp) 10085556Siwasaki{ 10185556Siwasaki int state; 10285556Siwasaki 103131218Simp state = APM_UNKNOWN; 10485556Siwasaki 10585556Siwasaki if (battp->state & ACPI_BATT_STAT_DISCHARG) { 106119530Snjl if (battp->cap >= 50) 10785556Siwasaki state = 0; /* high */ 108119530Snjl else 10985556Siwasaki state = 1; /* low */ 11085556Siwasaki } 111119530Snjl if (battp->state & ACPI_BATT_STAT_CRITICAL) 11285556Siwasaki state = 2; /* critical */ 113119530Snjl if (battp->state & ACPI_BATT_STAT_CHARGING) 11485556Siwasaki state = 3; /* charging */ 115119530Snjl 116120156Siwasaki /* If still unknown, determine it based on the battery capacity. */ 117131218Simp if (state == APM_UNKNOWN) { 118128975Snjl if (battp->cap >= 50) 119120156Siwasaki state = 0; /* high */ 120128975Snjl else 121120156Siwasaki state = 1; /* low */ 122120156Siwasaki } 123120156Siwasaki 12485556Siwasaki return (state); 12585556Siwasaki} 12685556Siwasaki 12785556Siwasakistatic int 12885556Siwasakiacpi_capm_convert_battflags(struct acpi_battinfo *battp) 12985556Siwasaki{ 13085556Siwasaki int flags; 13185556Siwasaki 13285556Siwasaki flags = 0; 13385556Siwasaki 134128975Snjl if (battp->cap >= 50) 13585556Siwasaki flags |= APM_BATT_HIGH; 136128975Snjl else { 137119530Snjl if (battp->state & ACPI_BATT_STAT_CRITICAL) 13885556Siwasaki flags |= APM_BATT_CRITICAL; 139119530Snjl else 14085556Siwasaki flags |= APM_BATT_LOW; 14185556Siwasaki } 142119530Snjl if (battp->state & ACPI_BATT_STAT_CHARGING) 14385556Siwasaki flags |= APM_BATT_CHARGING; 144119530Snjl if (battp->state == ACPI_BATT_STAT_NOT_PRESENT) 14585556Siwasaki flags = APM_BATT_NOT_PRESENT; 14685556Siwasaki 14785556Siwasaki return (flags); 14885556Siwasaki} 14985556Siwasaki 15085556Siwasakistatic int 15185556Siwasakiacpi_capm_get_info(apm_info_t aip) 15285556Siwasaki{ 15385556Siwasaki int acline; 15485556Siwasaki struct acpi_battinfo batt; 15585556Siwasaki 15685556Siwasaki aip->ai_infoversion = 1; 15785556Siwasaki aip->ai_major = 1; 15885556Siwasaki aip->ai_minor = 2; 159132619Snjl aip->ai_status = apm_active; 160131218Simp aip->ai_capabilities= 0xff00; /* unknown */ 16185556Siwasaki 162119530Snjl if (acpi_acad_get_acline(&acline)) 163131218Simp aip->ai_acline = APM_UNKNOWN; /* unknown */ 164119530Snjl else 16585556Siwasaki aip->ai_acline = acline; /* on/off */ 16685556Siwasaki 167148352Snjl if (acpi_battery_get_battinfo(NULL, &batt) != 0) { 168131218Simp aip->ai_batt_stat = APM_UNKNOWN; 169131218Simp aip->ai_batt_life = APM_UNKNOWN; 170131218Simp aip->ai_batt_time = -1; /* unknown */ 171131218Simp aip->ai_batteries = ~0U; /* unknown */ 17285556Siwasaki } else { 17385556Siwasaki aip->ai_batt_stat = acpi_capm_convert_battstate(&batt); 17485556Siwasaki aip->ai_batt_life = batt.cap; 17585556Siwasaki aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60; 17685556Siwasaki aip->ai_batteries = acpi_battery_get_units(); 17785556Siwasaki } 17885556Siwasaki 17985556Siwasaki return (0); 18085556Siwasaki} 18185556Siwasaki 18285556Siwasakistatic int 18385556Siwasakiacpi_capm_get_pwstatus(apm_pwstatus_t app) 18485556Siwasaki{ 185148352Snjl device_t dev; 186148352Snjl int acline, unit, error; 18785556Siwasaki struct acpi_battinfo batt; 18885556Siwasaki 18985556Siwasaki if (app->ap_device != PMDV_ALLDEV && 190128975Snjl (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL)) 19185556Siwasaki return (1); 19285556Siwasaki 193119530Snjl if (app->ap_device == PMDV_ALLDEV) 194148352Snjl error = acpi_battery_get_battinfo(NULL, &batt); 195148352Snjl else { 196148352Snjl unit = app->ap_device - PMDV_BATT0; 197148352Snjl dev = devclass_get_device(devclass_find("battery"), unit); 198148352Snjl if (dev != NULL) 199148352Snjl error = acpi_battery_get_battinfo(dev, &batt); 200148352Snjl else 201148352Snjl error = ENXIO; 202148352Snjl } 203148352Snjl if (error) 20485556Siwasaki return (1); 20585556Siwasaki 20685556Siwasaki app->ap_batt_stat = acpi_capm_convert_battstate(&batt); 20785556Siwasaki app->ap_batt_flag = acpi_capm_convert_battflags(&batt); 20885556Siwasaki app->ap_batt_life = batt.cap; 20985556Siwasaki app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60; 21085556Siwasaki 211119530Snjl if (acpi_acad_get_acline(&acline)) 212131218Simp app->ap_acline = APM_UNKNOWN; 213119530Snjl else 21485556Siwasaki app->ap_acline = acline; /* on/off */ 21585556Siwasaki 21685556Siwasaki return (0); 21785556Siwasaki} 21885556Siwasaki 219170976Snjl/* Create single-use devices for /dev/apm and /dev/apmctl. */ 220170976Snjlstatic void 221170976Snjlapm_clone(void *arg, struct ucred *cred, char *name, int namelen, 222170976Snjl struct cdev **dev) 223170976Snjl{ 224170976Snjl int ctl_dev, unit; 225170976Snjl 226170976Snjl if (*dev != NULL) 227170976Snjl return; 228170976Snjl if (strcmp(name, "apmctl") == 0) 229170976Snjl ctl_dev = TRUE; 230170976Snjl else if (strcmp(name, "apm") == 0) 231170976Snjl ctl_dev = FALSE; 232170976Snjl else 233170976Snjl return; 234170976Snjl 235170976Snjl /* Always create a new device and unit number. */ 236170976Snjl unit = -1; 237170976Snjl if (clone_create(&apm_clones, &apm_cdevsw, &unit, dev, 0)) { 238170976Snjl if (ctl_dev) { 239183381Sed *dev = make_dev(&apm_cdevsw, unit, 240170976Snjl UID_ROOT, GID_OPERATOR, 0660, "apmctl%d", unit); 241170976Snjl } else { 242183381Sed *dev = make_dev(&apm_cdevsw, unit, 243170976Snjl UID_ROOT, GID_OPERATOR, 0664, "apm%d", unit); 244170976Snjl } 245170976Snjl if (*dev != NULL) { 246170976Snjl dev_ref(*dev); 247170976Snjl (*dev)->si_flags |= SI_CHEAPCLONE; 248170976Snjl } 249170976Snjl } 250170976Snjl} 251170976Snjl 252170976Snjl/* Create a struct for tracking per-device suspend notification. */ 253170976Snjlstatic struct apm_clone_data * 254170976Snjlapm_create_clone(struct cdev *dev, struct acpi_softc *acpi_sc) 255170976Snjl{ 256170976Snjl struct apm_clone_data *clone; 257170976Snjl 258170976Snjl clone = malloc(sizeof(*clone), M_APMDEV, M_WAITOK); 259170976Snjl clone->cdev = dev; 260170976Snjl clone->acpi_sc = acpi_sc; 261170976Snjl clone->notify_status = APM_EV_NONE; 262170976Snjl bzero(&clone->sel_read, sizeof(clone->sel_read)); 263193951Skib knlist_init_mtx(&clone->sel_read.si_note, &acpi_mutex); 264170976Snjl 265170976Snjl /* 266170976Snjl * The acpi device is always managed by devd(8) and is considered 267170976Snjl * writable (i.e., ack is required to allow suspend to proceed.) 268170976Snjl */ 269170976Snjl if (strcmp("acpi", devtoname(dev)) == 0) 270170976Snjl clone->flags = ACPI_EVF_DEVD | ACPI_EVF_WRITE; 271170976Snjl else 272170976Snjl clone->flags = ACPI_EVF_NONE; 273170976Snjl 274170976Snjl ACPI_LOCK(acpi); 275170976Snjl STAILQ_INSERT_TAIL(&acpi_sc->apm_cdevs, clone, entries); 276170976Snjl ACPI_UNLOCK(acpi); 277170976Snjl return (clone); 278170976Snjl} 279170976Snjl 28085556Siwasakistatic int 281192442Simpapmopen(struct cdev *dev, int flag, int fmt, struct thread *td) 28285556Siwasaki{ 283170976Snjl struct acpi_softc *acpi_sc; 284170976Snjl struct apm_clone_data *clone; 285170976Snjl 286170976Snjl acpi_sc = devclass_get_softc(devclass_find("acpi"), 0); 287170976Snjl clone = apm_create_clone(dev, acpi_sc); 288170976Snjl dev->si_drv1 = clone; 289170976Snjl 290170976Snjl /* If the device is opened for write, record that. */ 291170976Snjl if ((flag & FWRITE) != 0) 292170976Snjl clone->flags |= ACPI_EVF_WRITE; 293170976Snjl 29485556Siwasaki return (0); 29585556Siwasaki} 29685556Siwasaki 29785556Siwasakistatic int 298192442Simpapmclose(struct cdev *dev, int flag, int fmt, struct thread *td) 29985556Siwasaki{ 300170976Snjl struct apm_clone_data *clone; 301170976Snjl struct acpi_softc *acpi_sc; 302170976Snjl 303170976Snjl clone = dev->si_drv1; 304170976Snjl acpi_sc = clone->acpi_sc; 305170976Snjl 306170976Snjl /* We are about to lose a reference so check if suspend should occur */ 307170976Snjl if (acpi_sc->acpi_next_sstate != 0 && 308170976Snjl clone->notify_status != APM_EV_ACKED) 309170976Snjl acpi_AckSleepState(clone, 0); 310170976Snjl 311170976Snjl /* Remove this clone's data from the list and free it. */ 312170976Snjl ACPI_LOCK(acpi); 313170976Snjl STAILQ_REMOVE(&acpi_sc->apm_cdevs, clone, apm_clone_data, entries); 314170976Snjl knlist_destroy(&clone->sel_read.si_note); 315170976Snjl ACPI_UNLOCK(acpi); 316170976Snjl free(clone, M_APMDEV); 317171297Snjl destroy_dev_sched(dev); 31885556Siwasaki return (0); 31985556Siwasaki} 32085556Siwasaki 32185556Siwasakistatic int 322192442Simpapmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 32385556Siwasaki{ 324170976Snjl int error; 325170976Snjl struct apm_clone_data *clone; 32685556Siwasaki struct acpi_softc *acpi_sc; 327170976Snjl struct apm_info info; 328170976Snjl struct apm_event_info *ev_info; 32985556Siwasaki apm_info_old_t aiop; 33085556Siwasaki 331170976Snjl error = 0; 332170976Snjl clone = dev->si_drv1; 333170976Snjl acpi_sc = clone->acpi_sc; 33485556Siwasaki 33585556Siwasaki switch (cmd) { 33685556Siwasaki case APMIO_SUSPEND: 337119530Snjl if ((flag & FWRITE) == 0) 33885556Siwasaki return (EPERM); 339170976Snjl if (acpi_sc->acpi_next_sstate == 0) { 340170976Snjl if (acpi_sc->acpi_suspend_sx != ACPI_STATE_S5) { 341170976Snjl error = acpi_ReqSleepState(acpi_sc, 342170976Snjl acpi_sc->acpi_suspend_sx); 343170976Snjl } else { 344170976Snjl printf( 345170976Snjl "power off via apm suspend not supported\n"); 346170976Snjl error = ENXIO; 347170976Snjl } 348170976Snjl } else 349170976Snjl error = acpi_AckSleepState(clone, 0); 35085556Siwasaki break; 35185556Siwasaki case APMIO_STANDBY: 352119530Snjl if ((flag & FWRITE) == 0) 35385556Siwasaki return (EPERM); 354170976Snjl if (acpi_sc->acpi_next_sstate == 0) { 355170976Snjl if (acpi_sc->acpi_standby_sx != ACPI_STATE_S5) { 356170976Snjl error = acpi_ReqSleepState(acpi_sc, 357170976Snjl acpi_sc->acpi_standby_sx); 358170976Snjl } else { 359170976Snjl printf( 360170976Snjl "power off via apm standby not supported\n"); 361170976Snjl error = ENXIO; 362170976Snjl } 363170976Snjl } else 364170976Snjl error = acpi_AckSleepState(clone, 0); 36585556Siwasaki break; 366170976Snjl case APMIO_NEXTEVENT: 367170976Snjl printf("apm nextevent start\n"); 368170976Snjl ACPI_LOCK(acpi); 369170976Snjl if (acpi_sc->acpi_next_sstate != 0 && clone->notify_status == 370170976Snjl APM_EV_NONE) { 371170976Snjl ev_info = (struct apm_event_info *)addr; 372170976Snjl if (acpi_sc->acpi_next_sstate <= ACPI_STATE_S3) 373170976Snjl ev_info->type = PMEV_STANDBYREQ; 374170976Snjl else 375170976Snjl ev_info->type = PMEV_SUSPENDREQ; 376170976Snjl ev_info->index = 0; 377170976Snjl clone->notify_status = APM_EV_NOTIFIED; 378170976Snjl printf("apm event returning %d\n", ev_info->type); 379170976Snjl } else 380170976Snjl error = EAGAIN; 381170976Snjl ACPI_UNLOCK(acpi); 382170976Snjl break; 38385556Siwasaki case APMIO_GETINFO_OLD: 38485556Siwasaki if (acpi_capm_get_info(&info)) 38585556Siwasaki error = ENXIO; 38685556Siwasaki aiop = (apm_info_old_t)addr; 38785556Siwasaki aiop->ai_major = info.ai_major; 38885556Siwasaki aiop->ai_minor = info.ai_minor; 38985556Siwasaki aiop->ai_acline = info.ai_acline; 39085556Siwasaki aiop->ai_batt_stat = info.ai_batt_stat; 39185556Siwasaki aiop->ai_batt_life = info.ai_batt_life; 39285556Siwasaki aiop->ai_status = info.ai_status; 39385556Siwasaki break; 39485556Siwasaki case APMIO_GETINFO: 39585556Siwasaki if (acpi_capm_get_info((apm_info_t)addr)) 39685556Siwasaki error = ENXIO; 39785556Siwasaki break; 39885556Siwasaki case APMIO_GETPWSTATUS: 39985556Siwasaki if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr)) 40085556Siwasaki error = ENXIO; 40185556Siwasaki break; 40285556Siwasaki case APMIO_ENABLE: 403119530Snjl if ((flag & FWRITE) == 0) 40485556Siwasaki return (EPERM); 405132619Snjl apm_active = 1; 40685556Siwasaki break; 40785556Siwasaki case APMIO_DISABLE: 408119530Snjl if ((flag & FWRITE) == 0) 40985556Siwasaki return (EPERM); 410132619Snjl apm_active = 0; 41185556Siwasaki break; 41285556Siwasaki case APMIO_HALTCPU: 41385556Siwasaki break; 41485556Siwasaki case APMIO_NOTHALTCPU: 41585556Siwasaki break; 41685556Siwasaki case APMIO_DISPLAY: 417119530Snjl if ((flag & FWRITE) == 0) 41885556Siwasaki return (EPERM); 41985556Siwasaki break; 42085556Siwasaki case APMIO_BIOS: 421119530Snjl if ((flag & FWRITE) == 0) 42285556Siwasaki return (EPERM); 42385556Siwasaki bzero(addr, sizeof(struct apm_bios_arg)); 42485556Siwasaki break; 42585556Siwasaki default: 42685556Siwasaki error = EINVAL; 42785556Siwasaki break; 42885556Siwasaki } 42985556Siwasaki 43085556Siwasaki return (error); 43185556Siwasaki} 43285556Siwasaki 43385556Siwasakistatic int 434130585Sphkapmwrite(struct cdev *dev, struct uio *uio, int ioflag) 43585556Siwasaki{ 43685556Siwasaki return (uio->uio_resid); 43785556Siwasaki} 43885556Siwasaki 43985556Siwasakistatic int 440192442Simpapmpoll(struct cdev *dev, int events, struct thread *td) 44185556Siwasaki{ 442170976Snjl struct apm_clone_data *clone; 443170976Snjl int revents; 444170976Snjl 445170976Snjl revents = 0; 446170976Snjl ACPI_LOCK(acpi); 447170976Snjl clone = dev->si_drv1; 448170976Snjl if (clone->acpi_sc->acpi_next_sstate) 449170976Snjl revents |= events & (POLLIN | POLLRDNORM); 450170976Snjl else 451170976Snjl selrecord(td, &clone->sel_read); 452170976Snjl ACPI_UNLOCK(acpi); 453170976Snjl return (revents); 454170976Snjl} 455170976Snjl 456170976Snjlstatic int 457170976Snjlapmkqfilter(struct cdev *dev, struct knote *kn) 458170976Snjl{ 459170976Snjl struct apm_clone_data *clone; 460170976Snjl 461170976Snjl ACPI_LOCK(acpi); 462170976Snjl clone = dev->si_drv1; 463170976Snjl kn->kn_hook = clone; 464170976Snjl kn->kn_fop = &apm_readfiltops; 465170976Snjl knlist_add(&clone->sel_read.si_note, kn, 0); 466170976Snjl ACPI_UNLOCK(acpi); 46785556Siwasaki return (0); 46885556Siwasaki} 46985556Siwasaki 47085556Siwasakistatic void 471170976Snjlapmreadfiltdetach(struct knote *kn) 47285556Siwasaki{ 473170976Snjl struct apm_clone_data *clone; 474170976Snjl 475170976Snjl ACPI_LOCK(acpi); 476170976Snjl clone = kn->kn_hook; 477170976Snjl knlist_remove(&clone->sel_read.si_note, kn, 0); 478170976Snjl ACPI_UNLOCK(acpi); 47985556Siwasaki} 48085556Siwasaki 481170976Snjlstatic int 482170976Snjlapmreadfilt(struct knote *kn, long hint) 483170976Snjl{ 484170976Snjl struct apm_clone_data *clone; 485170976Snjl int sleeping; 486170976Snjl 487170976Snjl ACPI_LOCK(acpi); 488170976Snjl clone = kn->kn_hook; 489170976Snjl sleeping = clone->acpi_sc->acpi_next_sstate ? 1 : 0; 490170976Snjl ACPI_UNLOCK(acpi); 491170976Snjl return (sleeping); 492170976Snjl} 493170976Snjl 49485556Siwasakiint 49585556Siwasakiacpi_machdep_init(device_t dev) 49685556Siwasaki{ 497170976Snjl struct acpi_softc *acpi_sc; 49885556Siwasaki 499170976Snjl acpi_sc = devclass_get_softc(devclass_find("acpi"), 0); 50085556Siwasaki 501170976Snjl /* Create a clone for /dev/acpi also. */ 502170976Snjl STAILQ_INIT(&acpi_sc->apm_cdevs); 503170976Snjl acpi_sc->acpi_clone = apm_create_clone(acpi_sc->acpi_dev_t, acpi_sc); 504170976Snjl clone_setup(&apm_clones); 505170976Snjl EVENTHANDLER_REGISTER(dev_clone, apm_clone, 0, 1000); 506170976Snjl acpi_install_wakeup_handler(acpi_sc); 50785556Siwasaki 508128932Sjhb if (intr_model == ACPI_INTR_PIC) 509167814Sjkim BUS_CONFIG_INTR(dev, AcpiGbl_FADT.SciInterrupt, 510167814Sjkim INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); 511128932Sjhb else 512119944Sjhb acpi_SetIntrModel(intr_model); 513121743Siwasaki 514170976Snjl SYSCTL_ADD_UINT(&acpi_sc->acpi_sysctl_ctx, 515170976Snjl SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, 516159477Snjl "reset_video", CTLFLAG_RW, &acpi_reset_video, 0, 517121830Snjl "Call the VESA reset BIOS vector on the resume path"); 518121743Siwasaki 51985556Siwasaki return (0); 52085556Siwasaki} 521119944Sjhb 522119944Sjhbvoid 523119944Sjhbacpi_SetDefaultIntrModel(int model) 524119944Sjhb{ 525119944Sjhb 526119944Sjhb intr_model = model; 527119944Sjhb} 528131312Snjl 529131312Snjl/* Check BIOS date. If 1998 or older, disable ACPI. */ 530131312Snjlint 531131312Snjlacpi_machdep_quirks(int *quirks) 532131312Snjl{ 533136367Snjl char *va; 534136367Snjl int year; 535131312Snjl 536136367Snjl /* BIOS address 0xffff5 contains the date in the format mm/dd/yy. */ 537161223Sjhb va = pmap_mapbios(0xffff0, 16); 538136367Snjl sscanf(va + 11, "%2d", &year); 539161223Sjhb pmap_unmapbios((vm_offset_t)va, 16); 540131312Snjl 541136367Snjl /* 542136367Snjl * Date must be >= 1/1/1999 or we don't trust ACPI. Note that this 543136367Snjl * check must be changed by my 114th birthday. 544136367Snjl */ 545136367Snjl if (year > 90 && year < 99) 546136367Snjl *quirks = ACPI_Q_BROKEN; 547131312Snjl 548136367Snjl return (0); 549131312Snjl} 550136366Snjl 551136366Snjlvoid 552136366Snjlacpi_cpu_c1() 553136366Snjl{ 554136366Snjl __asm __volatile("sti; hlt"); 555136366Snjl} 556177157Sjhb 557177157Sjhb/* 558177157Sjhb * ACPI nexus(4) driver. 559177157Sjhb */ 560177157Sjhbstatic int 561177157Sjhbnexus_acpi_probe(device_t dev) 562177157Sjhb{ 563177157Sjhb int error; 564177157Sjhb 565177157Sjhb error = acpi_identify(); 566177157Sjhb if (error) 567177157Sjhb return (error); 568177157Sjhb 569177157Sjhb return (BUS_PROBE_DEFAULT); 570177157Sjhb} 571177157Sjhb 572177157Sjhbstatic int 573177157Sjhbnexus_acpi_attach(device_t dev) 574177157Sjhb{ 575177157Sjhb 576177157Sjhb nexus_init_resources(); 577177157Sjhb bus_generic_probe(dev); 578177157Sjhb if (BUS_ADD_CHILD(dev, 10, "acpi", 0) == NULL) 579177157Sjhb panic("failed to add acpi0 device"); 580177157Sjhb 581177157Sjhb return (bus_generic_attach(dev)); 582177157Sjhb} 583177157Sjhb 584177157Sjhbstatic device_method_t nexus_acpi_methods[] = { 585177157Sjhb /* Device interface */ 586177157Sjhb DEVMETHOD(device_probe, nexus_acpi_probe), 587177157Sjhb DEVMETHOD(device_attach, nexus_acpi_attach), 588177157Sjhb 589177157Sjhb { 0, 0 } 590177157Sjhb}; 591177157Sjhb 592177157SjhbDEFINE_CLASS_1(nexus, nexus_acpi_driver, nexus_acpi_methods, 1, nexus_driver); 593177157Sjhbstatic devclass_t nexus_devclass; 594177157Sjhb 595177157SjhbDRIVER_MODULE(nexus_acpi, root, nexus_acpi_driver, nexus_devclass, 0, 0); 596