acpi_apm.c revision 136367
17836SJohn.Forte@Sun.COM/*-
27836SJohn.Forte@Sun.COM * Copyright (c) 2001 Mitsuru IWASAKI
37836SJohn.Forte@Sun.COM * All rights reserved.
47836SJohn.Forte@Sun.COM *
57836SJohn.Forte@Sun.COM * Redistribution and use in source and binary forms, with or without
67836SJohn.Forte@Sun.COM * modification, are permitted provided that the following conditions
77836SJohn.Forte@Sun.COM * are met:
87836SJohn.Forte@Sun.COM * 1. Redistributions of source code must retain the above copyright
97836SJohn.Forte@Sun.COM *    notice, this list of conditions and the following disclaimer.
107836SJohn.Forte@Sun.COM * 2. Redistributions in binary form must reproduce the above copyright
117836SJohn.Forte@Sun.COM *    notice, this list of conditions and the following disclaimer in the
127836SJohn.Forte@Sun.COM *    documentation and/or other materials provided with the distribution.
137836SJohn.Forte@Sun.COM *
147836SJohn.Forte@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
157836SJohn.Forte@Sun.COM * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
167836SJohn.Forte@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
177836SJohn.Forte@Sun.COM * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
187836SJohn.Forte@Sun.COM * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
197836SJohn.Forte@Sun.COM * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
207836SJohn.Forte@Sun.COM * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
217836SJohn.Forte@Sun.COM * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
227836SJohn.Forte@Sun.COM * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
237836SJohn.Forte@Sun.COM * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
247836SJohn.Forte@Sun.COM * SUCH DAMAGE.
257836SJohn.Forte@Sun.COM */
267836SJohn.Forte@Sun.COM
277836SJohn.Forte@Sun.COM#include <sys/cdefs.h>
287836SJohn.Forte@Sun.COM__FBSDID("$FreeBSD: head/sys/i386/acpica/acpi_machdep.c 136367 2004-10-11 05:42:12Z njl $");
297836SJohn.Forte@Sun.COM
307836SJohn.Forte@Sun.COM#include <sys/param.h>
317836SJohn.Forte@Sun.COM#include <sys/bus.h>
327836SJohn.Forte@Sun.COM#include <sys/conf.h>
337836SJohn.Forte@Sun.COM#include <sys/fcntl.h>
347836SJohn.Forte@Sun.COM#include <sys/kernel.h>
357836SJohn.Forte@Sun.COM#include <sys/sysctl.h>
367836SJohn.Forte@Sun.COM#include <sys/uio.h>
377836SJohn.Forte@Sun.COM#include <vm/vm.h>
387836SJohn.Forte@Sun.COM#include <vm/pmap.h>
397836SJohn.Forte@Sun.COM
407836SJohn.Forte@Sun.COM#include "acpi.h"
417836SJohn.Forte@Sun.COM#include <dev/acpica/acpivar.h>
427836SJohn.Forte@Sun.COM#include <dev/acpica/acpiio.h>
437836SJohn.Forte@Sun.COM
447836SJohn.Forte@Sun.COM/*
457836SJohn.Forte@Sun.COM * APM driver emulation
467836SJohn.Forte@Sun.COM */
477836SJohn.Forte@Sun.COM
487836SJohn.Forte@Sun.COM#include <sys/selinfo.h>
497836SJohn.Forte@Sun.COM
507836SJohn.Forte@Sun.COM#include <machine/apm_bios.h>
517836SJohn.Forte@Sun.COM#include <machine/pc/bios.h>
527836SJohn.Forte@Sun.COM
537836SJohn.Forte@Sun.COM#include <i386/bios/apm.h>
547836SJohn.Forte@Sun.COM
557836SJohn.Forte@Sun.COMuint32_t acpi_reset_video = 1;
567836SJohn.Forte@Sun.COMTUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video);
577836SJohn.Forte@Sun.COM
587836SJohn.Forte@Sun.COMstatic int intr_model = ACPI_INTR_PIC;
597836SJohn.Forte@Sun.COMstatic int apm_active;
607836SJohn.Forte@Sun.COM
617836SJohn.Forte@Sun.COMstatic d_open_t apmopen;
627836SJohn.Forte@Sun.COMstatic d_close_t apmclose;
637836SJohn.Forte@Sun.COMstatic d_write_t apmwrite;
647836SJohn.Forte@Sun.COMstatic d_ioctl_t apmioctl;
657836SJohn.Forte@Sun.COMstatic d_poll_t apmpoll;
667836SJohn.Forte@Sun.COM
677836SJohn.Forte@Sun.COMstatic struct cdevsw apm_cdevsw = {
687836SJohn.Forte@Sun.COM	.d_version =	D_VERSION,
697836SJohn.Forte@Sun.COM	.d_flags =	D_NEEDGIANT,
707836SJohn.Forte@Sun.COM	.d_open =	apmopen,
717836SJohn.Forte@Sun.COM	.d_close =	apmclose,
727836SJohn.Forte@Sun.COM	.d_write =	apmwrite,
737836SJohn.Forte@Sun.COM	.d_ioctl =	apmioctl,
747836SJohn.Forte@Sun.COM	.d_poll =	apmpoll,
757836SJohn.Forte@Sun.COM	.d_name =	"apm",
767836SJohn.Forte@Sun.COM};
777836SJohn.Forte@Sun.COM
787836SJohn.Forte@Sun.COMstatic int
797836SJohn.Forte@Sun.COMacpi_capm_convert_battstate(struct  acpi_battinfo *battp)
807836SJohn.Forte@Sun.COM{
817836SJohn.Forte@Sun.COM	int	state;
827836SJohn.Forte@Sun.COM
837836SJohn.Forte@Sun.COM	state = APM_UNKNOWN;
847836SJohn.Forte@Sun.COM
857836SJohn.Forte@Sun.COM	if (battp->state & ACPI_BATT_STAT_DISCHARG) {
867836SJohn.Forte@Sun.COM		if (battp->cap >= 50)
877836SJohn.Forte@Sun.COM			state = 0;	/* high */
887836SJohn.Forte@Sun.COM		else
897836SJohn.Forte@Sun.COM			state = 1;	/* low */
907836SJohn.Forte@Sun.COM	}
917836SJohn.Forte@Sun.COM	if (battp->state & ACPI_BATT_STAT_CRITICAL)
927836SJohn.Forte@Sun.COM		state = 2;		/* critical */
937836SJohn.Forte@Sun.COM	if (battp->state & ACPI_BATT_STAT_CHARGING)
947836SJohn.Forte@Sun.COM		state = 3;		/* charging */
957836SJohn.Forte@Sun.COM
967836SJohn.Forte@Sun.COM	/* If still unknown, determine it based on the battery capacity. */
977836SJohn.Forte@Sun.COM	if (state == APM_UNKNOWN) {
987836SJohn.Forte@Sun.COM		if (battp->cap >= 50)
997836SJohn.Forte@Sun.COM			state = 0;	/* high */
1007836SJohn.Forte@Sun.COM		else
1017836SJohn.Forte@Sun.COM			state = 1;	/* low */
1027836SJohn.Forte@Sun.COM	}
1037836SJohn.Forte@Sun.COM
1047836SJohn.Forte@Sun.COM	return (state);
1057836SJohn.Forte@Sun.COM}
1067836SJohn.Forte@Sun.COM
1077836SJohn.Forte@Sun.COMstatic int
1087836SJohn.Forte@Sun.COMacpi_capm_convert_battflags(struct  acpi_battinfo *battp)
1097836SJohn.Forte@Sun.COM{
1107836SJohn.Forte@Sun.COM	int	flags;
1117836SJohn.Forte@Sun.COM
1127836SJohn.Forte@Sun.COM	flags = 0;
1137836SJohn.Forte@Sun.COM
1147836SJohn.Forte@Sun.COM	if (battp->cap >= 50)
1157836SJohn.Forte@Sun.COM		flags |= APM_BATT_HIGH;
1167836SJohn.Forte@Sun.COM	else {
1177836SJohn.Forte@Sun.COM		if (battp->state & ACPI_BATT_STAT_CRITICAL)
1187836SJohn.Forte@Sun.COM			flags |= APM_BATT_CRITICAL;
1197836SJohn.Forte@Sun.COM		else
1207836SJohn.Forte@Sun.COM			flags |= APM_BATT_LOW;
1217836SJohn.Forte@Sun.COM	}
1227836SJohn.Forte@Sun.COM	if (battp->state & ACPI_BATT_STAT_CHARGING)
1237836SJohn.Forte@Sun.COM		flags |= APM_BATT_CHARGING;
1247836SJohn.Forte@Sun.COM	if (battp->state == ACPI_BATT_STAT_NOT_PRESENT)
1257836SJohn.Forte@Sun.COM		flags = APM_BATT_NOT_PRESENT;
1267836SJohn.Forte@Sun.COM
1277836SJohn.Forte@Sun.COM	return (flags);
1287836SJohn.Forte@Sun.COM}
1297836SJohn.Forte@Sun.COM
1307836SJohn.Forte@Sun.COMstatic int
1317836SJohn.Forte@Sun.COMacpi_capm_get_info(apm_info_t aip)
1327836SJohn.Forte@Sun.COM{
1337836SJohn.Forte@Sun.COM	int	acline;
1347836SJohn.Forte@Sun.COM	struct	acpi_battinfo batt;
1357836SJohn.Forte@Sun.COM
1367836SJohn.Forte@Sun.COM	aip->ai_infoversion = 1;
1377836SJohn.Forte@Sun.COM	aip->ai_major       = 1;
1387836SJohn.Forte@Sun.COM	aip->ai_minor       = 2;
1397836SJohn.Forte@Sun.COM	aip->ai_status      = apm_active;
1407836SJohn.Forte@Sun.COM	aip->ai_capabilities= 0xff00;	/* unknown */
1417836SJohn.Forte@Sun.COM
1427836SJohn.Forte@Sun.COM	if (acpi_acad_get_acline(&acline))
1437836SJohn.Forte@Sun.COM		aip->ai_acline = APM_UNKNOWN;	/* unknown */
1447836SJohn.Forte@Sun.COM	else
1457836SJohn.Forte@Sun.COM		aip->ai_acline = acline;	/* on/off */
1467836SJohn.Forte@Sun.COM
1477836SJohn.Forte@Sun.COM	if (acpi_battery_get_battinfo(-1, &batt)) {
1487836SJohn.Forte@Sun.COM		aip->ai_batt_stat = APM_UNKNOWN;
1497836SJohn.Forte@Sun.COM		aip->ai_batt_life = APM_UNKNOWN;
1507836SJohn.Forte@Sun.COM		aip->ai_batt_time = -1;		 /* unknown */
1517836SJohn.Forte@Sun.COM		aip->ai_batteries = ~0U;	 /* unknown */
1527836SJohn.Forte@Sun.COM	} else {
1537836SJohn.Forte@Sun.COM		aip->ai_batt_stat = acpi_capm_convert_battstate(&batt);
1547836SJohn.Forte@Sun.COM		aip->ai_batt_life = batt.cap;
1557836SJohn.Forte@Sun.COM		aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
1567836SJohn.Forte@Sun.COM		aip->ai_batteries = acpi_battery_get_units();
1577836SJohn.Forte@Sun.COM	}
1587836SJohn.Forte@Sun.COM
1597836SJohn.Forte@Sun.COM	return (0);
1607836SJohn.Forte@Sun.COM}
1617836SJohn.Forte@Sun.COM
1627836SJohn.Forte@Sun.COMstatic int
1637836SJohn.Forte@Sun.COMacpi_capm_get_pwstatus(apm_pwstatus_t app)
1647836SJohn.Forte@Sun.COM{
1657836SJohn.Forte@Sun.COM	int	batt_unit;
1667836SJohn.Forte@Sun.COM	int	acline;
1677836SJohn.Forte@Sun.COM	struct	acpi_battinfo batt;
1687836SJohn.Forte@Sun.COM
1697836SJohn.Forte@Sun.COM	if (app->ap_device != PMDV_ALLDEV &&
1707836SJohn.Forte@Sun.COM	    (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL))
1717836SJohn.Forte@Sun.COM		return (1);
1727836SJohn.Forte@Sun.COM
1737836SJohn.Forte@Sun.COM	if (app->ap_device == PMDV_ALLDEV)
1747836SJohn.Forte@Sun.COM		batt_unit = -1;			/* all units */
1757836SJohn.Forte@Sun.COM	else
1767836SJohn.Forte@Sun.COM		batt_unit = app->ap_device - PMDV_BATT0;
1777836SJohn.Forte@Sun.COM
1787836SJohn.Forte@Sun.COM	if (acpi_battery_get_battinfo(batt_unit, &batt))
1797836SJohn.Forte@Sun.COM		return (1);
1807836SJohn.Forte@Sun.COM
1817836SJohn.Forte@Sun.COM	app->ap_batt_stat = acpi_capm_convert_battstate(&batt);
1827836SJohn.Forte@Sun.COM	app->ap_batt_flag = acpi_capm_convert_battflags(&batt);
1837836SJohn.Forte@Sun.COM	app->ap_batt_life = batt.cap;
1847836SJohn.Forte@Sun.COM	app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
1857836SJohn.Forte@Sun.COM
1867836SJohn.Forte@Sun.COM	if (acpi_acad_get_acline(&acline))
1877836SJohn.Forte@Sun.COM		app->ap_acline = APM_UNKNOWN;
1887836SJohn.Forte@Sun.COM	else
1897836SJohn.Forte@Sun.COM		app->ap_acline = acline;	/* on/off */
1907836SJohn.Forte@Sun.COM
1917836SJohn.Forte@Sun.COM	return (0);
1927836SJohn.Forte@Sun.COM}
1937836SJohn.Forte@Sun.COM
1947836SJohn.Forte@Sun.COMstatic int
1957836SJohn.Forte@Sun.COMapmopen(struct cdev *dev, int flag, int fmt, d_thread_t *td)
1967836SJohn.Forte@Sun.COM{
1977836SJohn.Forte@Sun.COM	return (0);
1987836SJohn.Forte@Sun.COM}
1997836SJohn.Forte@Sun.COM
2007836SJohn.Forte@Sun.COMstatic int
2017836SJohn.Forte@Sun.COMapmclose(struct cdev *dev, int flag, int fmt, d_thread_t *td)
2027836SJohn.Forte@Sun.COM{
2037836SJohn.Forte@Sun.COM	return (0);
2047836SJohn.Forte@Sun.COM}
2057836SJohn.Forte@Sun.COM
2067836SJohn.Forte@Sun.COMstatic int
2077836SJohn.Forte@Sun.COMapmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, d_thread_t *td)
2087836SJohn.Forte@Sun.COM{
2097836SJohn.Forte@Sun.COM	int	error = 0;
2107836SJohn.Forte@Sun.COM	struct	acpi_softc *acpi_sc;
2117836SJohn.Forte@Sun.COM	struct apm_info info;
2127836SJohn.Forte@Sun.COM	apm_info_old_t aiop;
2137836SJohn.Forte@Sun.COM
2147836SJohn.Forte@Sun.COM	acpi_sc = devclass_get_softc(devclass_find("acpi"), 0);
2157836SJohn.Forte@Sun.COM
2167836SJohn.Forte@Sun.COM	switch (cmd) {
2177836SJohn.Forte@Sun.COM	case APMIO_SUSPEND:
2187836SJohn.Forte@Sun.COM		if ((flag & FWRITE) == 0)
2197836SJohn.Forte@Sun.COM			return (EPERM);
2207836SJohn.Forte@Sun.COM		if (apm_active)
2217836SJohn.Forte@Sun.COM			acpi_SetSleepState(acpi_sc, acpi_sc->acpi_suspend_sx);
2227836SJohn.Forte@Sun.COM		else
2237836SJohn.Forte@Sun.COM			error = EINVAL;
2247836SJohn.Forte@Sun.COM		break;
2257836SJohn.Forte@Sun.COM	case APMIO_STANDBY:
2267836SJohn.Forte@Sun.COM		if ((flag & FWRITE) == 0)
2277836SJohn.Forte@Sun.COM			return (EPERM);
2287836SJohn.Forte@Sun.COM		if (apm_active)
2297836SJohn.Forte@Sun.COM			acpi_SetSleepState(acpi_sc, acpi_sc->acpi_standby_sx);
2307836SJohn.Forte@Sun.COM		else
2317836SJohn.Forte@Sun.COM			error = EINVAL;
2327836SJohn.Forte@Sun.COM		break;
2337836SJohn.Forte@Sun.COM	case APMIO_GETINFO_OLD:
2347836SJohn.Forte@Sun.COM		if (acpi_capm_get_info(&info))
2357836SJohn.Forte@Sun.COM			error = ENXIO;
2367836SJohn.Forte@Sun.COM		aiop = (apm_info_old_t)addr;
2377836SJohn.Forte@Sun.COM		aiop->ai_major = info.ai_major;
2387836SJohn.Forte@Sun.COM		aiop->ai_minor = info.ai_minor;
2397836SJohn.Forte@Sun.COM		aiop->ai_acline = info.ai_acline;
2407836SJohn.Forte@Sun.COM		aiop->ai_batt_stat = info.ai_batt_stat;
2417836SJohn.Forte@Sun.COM		aiop->ai_batt_life = info.ai_batt_life;
2427836SJohn.Forte@Sun.COM		aiop->ai_status = info.ai_status;
2437836SJohn.Forte@Sun.COM		break;
2447836SJohn.Forte@Sun.COM	case APMIO_GETINFO:
2457836SJohn.Forte@Sun.COM		if (acpi_capm_get_info((apm_info_t)addr))
2467836SJohn.Forte@Sun.COM			error = ENXIO;
2477836SJohn.Forte@Sun.COM		break;
2487836SJohn.Forte@Sun.COM	case APMIO_GETPWSTATUS:
2497836SJohn.Forte@Sun.COM		if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr))
2507836SJohn.Forte@Sun.COM			error = ENXIO;
2517836SJohn.Forte@Sun.COM		break;
2527836SJohn.Forte@Sun.COM	case APMIO_ENABLE:
2537836SJohn.Forte@Sun.COM		if ((flag & FWRITE) == 0)
2547836SJohn.Forte@Sun.COM			return (EPERM);
2557836SJohn.Forte@Sun.COM		apm_active = 1;
2567836SJohn.Forte@Sun.COM		break;
2577836SJohn.Forte@Sun.COM	case APMIO_DISABLE:
2587836SJohn.Forte@Sun.COM		if ((flag & FWRITE) == 0)
2597836SJohn.Forte@Sun.COM			return (EPERM);
2607836SJohn.Forte@Sun.COM		apm_active = 0;
2617836SJohn.Forte@Sun.COM		break;
2627836SJohn.Forte@Sun.COM	case APMIO_HALTCPU:
2637836SJohn.Forte@Sun.COM		break;
2647836SJohn.Forte@Sun.COM	case APMIO_NOTHALTCPU:
2657836SJohn.Forte@Sun.COM		break;
2667836SJohn.Forte@Sun.COM	case APMIO_DISPLAY:
2677836SJohn.Forte@Sun.COM		if ((flag & FWRITE) == 0)
2687836SJohn.Forte@Sun.COM			return (EPERM);
2697836SJohn.Forte@Sun.COM		break;
2707836SJohn.Forte@Sun.COM	case APMIO_BIOS:
2717836SJohn.Forte@Sun.COM		if ((flag & FWRITE) == 0)
2727836SJohn.Forte@Sun.COM			return (EPERM);
2737836SJohn.Forte@Sun.COM		bzero(addr, sizeof(struct apm_bios_arg));
2747836SJohn.Forte@Sun.COM		break;
2757836SJohn.Forte@Sun.COM	default:
2767836SJohn.Forte@Sun.COM		error = EINVAL;
2777836SJohn.Forte@Sun.COM		break;
2787836SJohn.Forte@Sun.COM	}
2797836SJohn.Forte@Sun.COM
2807836SJohn.Forte@Sun.COM	return (error);
2817836SJohn.Forte@Sun.COM}
2827836SJohn.Forte@Sun.COM
2837836SJohn.Forte@Sun.COMstatic int
2847836SJohn.Forte@Sun.COMapmwrite(struct cdev *dev, struct uio *uio, int ioflag)
2857836SJohn.Forte@Sun.COM{
2867836SJohn.Forte@Sun.COM	return (uio->uio_resid);
2877836SJohn.Forte@Sun.COM}
2887836SJohn.Forte@Sun.COM
2897836SJohn.Forte@Sun.COMstatic int
2907836SJohn.Forte@Sun.COMapmpoll(struct cdev *dev, int events, d_thread_t *td)
2917836SJohn.Forte@Sun.COM{
2927836SJohn.Forte@Sun.COM	return (0);
2937836SJohn.Forte@Sun.COM}
2947836SJohn.Forte@Sun.COM
2957836SJohn.Forte@Sun.COMstatic void
2967836SJohn.Forte@Sun.COMacpi_capm_init(struct acpi_softc *sc)
2977836SJohn.Forte@Sun.COM{
2987836SJohn.Forte@Sun.COM        make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm");
2997836SJohn.Forte@Sun.COM}
3007836SJohn.Forte@Sun.COM
3017836SJohn.Forte@Sun.COMint
3027836SJohn.Forte@Sun.COMacpi_machdep_init(device_t dev)
3037836SJohn.Forte@Sun.COM{
3047836SJohn.Forte@Sun.COM	struct	acpi_softc *sc;
3057836SJohn.Forte@Sun.COM
3067836SJohn.Forte@Sun.COM	sc = devclass_get_softc(devclass_find("acpi"), 0);
3077836SJohn.Forte@Sun.COM	acpi_capm_init(sc);
3087836SJohn.Forte@Sun.COM
3097836SJohn.Forte@Sun.COM	acpi_install_wakeup_handler(sc);
3107836SJohn.Forte@Sun.COM
3117836SJohn.Forte@Sun.COM	if (intr_model == ACPI_INTR_PIC)
3127836SJohn.Forte@Sun.COM		BUS_CONFIG_INTR(dev, AcpiGbl_FADT->SciInt, INTR_TRIGGER_LEVEL,
3137836SJohn.Forte@Sun.COM		    INTR_POLARITY_LOW);
3147836SJohn.Forte@Sun.COM	else
3157836SJohn.Forte@Sun.COM		acpi_SetIntrModel(intr_model);
3167836SJohn.Forte@Sun.COM
3177836SJohn.Forte@Sun.COM	SYSCTL_ADD_UINT(&sc->acpi_sysctl_ctx,
3187836SJohn.Forte@Sun.COM	    SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO,
3197836SJohn.Forte@Sun.COM	    "reset_video", CTLFLAG_RD | CTLFLAG_RW, &acpi_reset_video, 0,
3207836SJohn.Forte@Sun.COM	    "Call the VESA reset BIOS vector on the resume path");
3217836SJohn.Forte@Sun.COM
3227836SJohn.Forte@Sun.COM	return (0);
3237836SJohn.Forte@Sun.COM}
3247836SJohn.Forte@Sun.COM
3257836SJohn.Forte@Sun.COMvoid
3267836SJohn.Forte@Sun.COMacpi_SetDefaultIntrModel(int model)
3277836SJohn.Forte@Sun.COM{
3287836SJohn.Forte@Sun.COM
3297836SJohn.Forte@Sun.COM	intr_model = model;
3307836SJohn.Forte@Sun.COM}
3317836SJohn.Forte@Sun.COM
3327836SJohn.Forte@Sun.COM/* Check BIOS date.  If 1998 or older, disable ACPI. */
3337836SJohn.Forte@Sun.COMint
3347836SJohn.Forte@Sun.COMacpi_machdep_quirks(int *quirks)
3357836SJohn.Forte@Sun.COM{
3367836SJohn.Forte@Sun.COM	char *va;
3377836SJohn.Forte@Sun.COM	int year;
3387836SJohn.Forte@Sun.COM
3397836SJohn.Forte@Sun.COM	/* BIOS address 0xffff5 contains the date in the format mm/dd/yy. */
3407836SJohn.Forte@Sun.COM	va = pmap_mapdev(0xffff0, 16);
3417836SJohn.Forte@Sun.COM	sscanf(va + 11, "%2d", &year);
3427836SJohn.Forte@Sun.COM	pmap_unmapdev((vm_offset_t)va, 16);
3437836SJohn.Forte@Sun.COM
3447836SJohn.Forte@Sun.COM	/*
3457836SJohn.Forte@Sun.COM	 * Date must be >= 1/1/1999 or we don't trust ACPI.  Note that this
3467836SJohn.Forte@Sun.COM	 * check must be changed by my 114th birthday.
3477836SJohn.Forte@Sun.COM	 */
3487836SJohn.Forte@Sun.COM	if (year > 90 && year < 99)
3497836SJohn.Forte@Sun.COM		*quirks = ACPI_Q_BROKEN;
3507836SJohn.Forte@Sun.COM
3517836SJohn.Forte@Sun.COM	return (0);
3527836SJohn.Forte@Sun.COM}
3537836SJohn.Forte@Sun.COM
3547836SJohn.Forte@Sun.COMvoid
3557836SJohn.Forte@Sun.COMacpi_cpu_c1()
3567836SJohn.Forte@Sun.COM{
3577836SJohn.Forte@Sun.COM	__asm __volatile("sti; hlt");
3587836SJohn.Forte@Sun.COM}
3597836SJohn.Forte@Sun.COM