File:  [DragonFly] / src / sys / i386 / acpica5 / Attic / acpi_machdep.c
Revision 1.2: download - view: text, annotated - select for diffs
Thu May 13 23:49:23 2004 UTC (10 years, 5 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*-
    2:  * Copyright (c) 2001 Mitsuru IWASAKI
    3:  * All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer.
   10:  * 2. Redistributions in binary form must reproduce the above copyright
   11:  *    notice, this list of conditions and the following disclaimer in the
   12:  *    documentation and/or other materials provided with the distribution.
   13:  *
   14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24:  * SUCH DAMAGE.
   25:  *
   26:  * $FreeBSD: src/sys/i386/acpica/acpi_machdep.c,v 1.15 2003/11/01 00:18:29 njl Exp $
   27:  * $DragonFly: src/sys/i386/acpica5/acpi_machdep.c,v 1.2 2004/05/13 23:49:23 dillon Exp $
   28:  */
   29: 
   30: #include <sys/param.h>
   31: #include <sys/bus.h>
   32: #include <sys/conf.h>
   33: #include <sys/fcntl.h>
   34: #include <sys/kernel.h>
   35: #include <sys/sysctl.h>
   36: #include <sys/uio.h>
   37: 
   38: #include "acpi.h"
   39: 
   40: #include <dev/acpica/acpivar.h>
   41: #include <dev/acpica/acpiio.h>
   42: 
   43: static device_t	acpi_dev;
   44: 
   45: /*
   46:  * APM driver emulation 
   47:  */
   48: 
   49: #include <sys/select.h>
   50: 
   51: #include <machine/apm_bios.h>
   52: #include <machine/pc/bios.h>
   53: 
   54: #include <i386/apm/apm.h>
   55: 
   56: u_int32_t acpi_reset_video = 1;
   57: TUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video);
   58: 
   59: static struct apm_softc	apm_softc;
   60: 
   61: static d_open_t apmopen;
   62: static d_close_t apmclose;
   63: static d_write_t apmwrite;
   64: static d_ioctl_t apmioctl;
   65: static d_poll_t apmpoll;
   66: 
   67: #define CDEV_MAJOR 39
   68: static struct cdevsw apm_cdevsw = {
   69:         .d_name = "apm",
   70:         .d_maj  = CDEV_MAJOR,
   71:         .d_flags = 0,
   72:         .d_port = NULL,
   73:         .d_clone = NULL,
   74:         .old_open = apmopen,
   75:         .old_close = apmclose,
   76: 	.old_write = apmwrite,
   77:         .old_ioctl = apmioctl,
   78: 	.old_poll = apmpoll
   79: };
   80: 
   81: static int intr_model = ACPI_INTR_PIC;
   82: 
   83: static int
   84: acpi_capm_convert_battstate(struct  acpi_battinfo *battp)
   85: {
   86: 	int	state;
   87: 
   88: 	state = 0xff;	/* XXX unknown */
   89: 
   90: 	if (battp->state & ACPI_BATT_STAT_DISCHARG) {
   91: 		if (battp->cap >= 50)
   92: 			state = 0;	/* high */
   93: 		else
   94: 			state = 1;	/* low */
   95: 	}
   96: 	if (battp->state & ACPI_BATT_STAT_CRITICAL)
   97: 		state = 2;		/* critical */
   98: 	if (battp->state & ACPI_BATT_STAT_CHARGING)
   99: 		state = 3;		/* charging */
  100: 
  101: 	/* If still unknown, determine it based on the battery capacity. */
  102: 	if (state == 0xff) {
  103: 		if (battp->cap >= 50) {
  104: 			state = 0;	/* high */
  105: 		} else {
  106: 			state = 1;	/* low */
  107: 		}
  108: 	}
  109: 
  110: 	return (state);
  111: }
  112: 
  113: static int
  114: acpi_capm_convert_battflags(struct  acpi_battinfo *battp)
  115: {
  116: 	int	flags;
  117: 
  118: 	flags = 0;
  119: 
  120: 	if (battp->cap >= 50) {
  121: 		flags |= APM_BATT_HIGH;
  122: 	} else {
  123: 		if (battp->state & ACPI_BATT_STAT_CRITICAL)
  124: 			flags |= APM_BATT_CRITICAL;
  125: 		else
  126: 			flags |= APM_BATT_LOW;
  127: 	}
  128: 	if (battp->state & ACPI_BATT_STAT_CHARGING)
  129: 		flags |= APM_BATT_CHARGING;
  130: 	if (battp->state == ACPI_BATT_STAT_NOT_PRESENT)
  131: 		flags = APM_BATT_NOT_PRESENT;
  132: 
  133: 	return (flags);
  134: }
  135: 
  136: static int
  137: acpi_capm_get_info(apm_info_t aip)
  138: {
  139: 	int	acline;
  140: 	struct	acpi_battinfo batt;
  141: 
  142: 	aip->ai_infoversion = 1;
  143: 	aip->ai_major       = 1;
  144: 	aip->ai_minor       = 2;
  145: 	aip->ai_status      = apm_softc.active;
  146: 	aip->ai_capabilities= 0xff00;	/* XXX unknown */
  147: 
  148: 	if (acpi_acad_get_acline(&acline))
  149: 		aip->ai_acline = 0xff;		/* unknown */
  150: 	else
  151: 		aip->ai_acline = acline;	/* on/off */
  152: 
  153: 	if (acpi_battery_get_battinfo(-1, &batt)) {
  154: 		aip->ai_batt_stat = 0xff;	/* unknown */
  155: 		aip->ai_batt_life = 0xff;	/* unknown */
  156: 		aip->ai_batt_time = -1;		/* unknown */
  157: 		aip->ai_batteries = 0;
  158: 	} else {
  159: 		aip->ai_batt_stat = acpi_capm_convert_battstate(&batt);
  160: 		aip->ai_batt_life = batt.cap;
  161: 		aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
  162: 		aip->ai_batteries = acpi_battery_get_units();
  163: 	}
  164: 
  165: 	return (0);
  166: }
  167: 
  168: static int
  169: acpi_capm_get_pwstatus(apm_pwstatus_t app)
  170: {
  171: 	int	batt_unit;
  172: 	int	acline;
  173: 	struct	acpi_battinfo batt;
  174: 
  175: 	if (app->ap_device != PMDV_ALLDEV &&
  176: 	    (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL)) {
  177: 		return (1);
  178: 	}
  179: 
  180: 	if (app->ap_device == PMDV_ALLDEV)
  181: 		batt_unit = -1;			/* all units */
  182: 	else
  183: 		batt_unit = app->ap_device - PMDV_BATT0;
  184: 
  185: 	if (acpi_battery_get_battinfo(batt_unit, &batt))
  186: 		return (1);
  187: 
  188: 	app->ap_batt_stat = acpi_capm_convert_battstate(&batt);
  189: 	app->ap_batt_flag = acpi_capm_convert_battflags(&batt);
  190: 	app->ap_batt_life = batt.cap;
  191: 	app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
  192: 
  193: 	if (acpi_acad_get_acline(&acline))
  194: 		app->ap_acline = 0xff;		/* unknown */
  195: 	else
  196: 		app->ap_acline = acline;	/* on/off */
  197: 
  198: 	return (0);
  199: }
  200: 
  201: static int
  202: apmopen(dev_t dev, int flag, int fmt, d_thread_t *td)
  203: {
  204: 	return (0);
  205: }
  206: 
  207: static int
  208: apmclose(dev_t dev, int flag, int fmt, d_thread_t *td)
  209: {
  210: 	return (0);
  211: }
  212: 
  213: static int
  214: apmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, d_thread_t *td)
  215: {
  216: 	int	error = 0;
  217: 	struct	acpi_softc *acpi_sc;
  218: 	struct apm_info info;
  219: 	apm_info_old_t aiop;
  220: 
  221: 	if ((acpi_sc = device_get_softc(acpi_dev)) == NULL)
  222: 		return (ENXIO);
  223: 
  224: 	switch (cmd) {
  225: 	case APMIO_SUSPEND:
  226: 		if ((flag & FWRITE) == 0)
  227: 			return (EPERM);
  228: 		if (apm_softc.active)
  229: 			acpi_SetSleepState(acpi_sc, acpi_sc->acpi_suspend_sx);
  230: 		else
  231: 			error = EINVAL;
  232: 		break;
  233: 	case APMIO_STANDBY:
  234: 		if ((flag & FWRITE) == 0)
  235: 			return (EPERM);
  236: 		if (apm_softc.active)
  237: 			acpi_SetSleepState(acpi_sc, acpi_sc->acpi_standby_sx);
  238: 		else
  239: 			error = EINVAL;
  240: 		break;
  241: 	case APMIO_GETINFO_OLD:
  242: 		if (acpi_capm_get_info(&info))
  243: 			error = ENXIO;
  244: 		aiop = (apm_info_old_t)addr;
  245: 		aiop->ai_major = info.ai_major;
  246: 		aiop->ai_minor = info.ai_minor;
  247: 		aiop->ai_acline = info.ai_acline;
  248: 		aiop->ai_batt_stat = info.ai_batt_stat;
  249: 		aiop->ai_batt_life = info.ai_batt_life;
  250: 		aiop->ai_status = info.ai_status;
  251: 		break;
  252: 	case APMIO_GETINFO:
  253: 		if (acpi_capm_get_info((apm_info_t)addr))
  254: 			error = ENXIO;
  255: 		break;
  256: 	case APMIO_GETPWSTATUS:
  257: 		if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr))
  258: 			error = ENXIO;
  259: 		break;
  260: 	case APMIO_ENABLE:
  261: 		if ((flag & FWRITE) == 0)
  262: 			return (EPERM);
  263: 		apm_softc.active = 1;
  264: 		break;
  265: 	case APMIO_DISABLE:
  266: 		if ((flag & FWRITE) == 0)
  267: 			return (EPERM);
  268: 		apm_softc.active = 0;
  269: 		break;
  270: 	case APMIO_HALTCPU:
  271: 		break;
  272: 	case APMIO_NOTHALTCPU:
  273: 		break;
  274: 	case APMIO_DISPLAY:
  275: 		if ((flag & FWRITE) == 0)
  276: 			return (EPERM);
  277: 		break;
  278: 	case APMIO_BIOS:
  279: 		if ((flag & FWRITE) == 0)
  280: 			return (EPERM);
  281: 		bzero(addr, sizeof(struct apm_bios_arg));
  282: 		break;
  283: 	default:
  284: 		error = EINVAL;
  285: 		break;
  286: 	}
  287: 
  288: 	return (error);
  289: }
  290: 
  291: static int
  292: apmwrite(dev_t dev, struct uio *uio, int ioflag)
  293: {
  294: 	return (uio->uio_resid);
  295: }
  296: 
  297: static int
  298: apmpoll(dev_t dev, int events, d_thread_t *td)
  299: {
  300: 	return (0);
  301: }
  302: 
  303: static void
  304: acpi_capm_init(struct acpi_softc *sc)
  305: {
  306:         make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm");
  307: }
  308: 
  309: int
  310: acpi_machdep_init(device_t dev)
  311: {
  312: 	struct	acpi_softc *sc;
  313: 
  314: 	acpi_dev = dev;
  315: 	if ((sc = device_get_softc(acpi_dev)) == NULL)
  316: 		return (ENXIO);
  317: 
  318: 	/*
  319: 	 * XXX: Prevent the PnP BIOS code from interfering with
  320: 	 * our own scan of ISA devices.
  321: 	 */
  322: 	PnPBIOStable = NULL;
  323: 
  324: 	acpi_capm_init(sc);
  325: 
  326: 	acpi_install_wakeup_handler(sc);
  327: 
  328: 	if (intr_model != ACPI_INTR_PIC)
  329: 		acpi_SetIntrModel(intr_model);
  330: 
  331: 	SYSCTL_ADD_UINT(&sc->acpi_sysctl_ctx,
  332: 	    SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO,
  333: 	    "reset_video", CTLFLAG_RD | CTLFLAG_RW, &acpi_reset_video, 0,
  334: 	    "Call the VESA reset BIOS vector on the resume path");
  335: 
  336: 	return (0);
  337: }
  338: 
  339: void
  340: acpi_SetDefaultIntrModel(int model)
  341: {
  342: 
  343: 	intr_model = model;
  344: }