handle bios requests differently: mark them in progress while waiting
for user input, or until the driver is ready to handle them itself. Also, try to turn on power management if the BIOS says it's disabled at connect time.
This commit is contained in:
parent
93da79de2b
commit
76ea50410b
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: apm.c,v 1.19 1997/01/04 03:04:25 jtk Exp $ */
|
/* $NetBSD: apm.c,v 1.20 1997/04/15 01:45:11 jtk Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||||
|
@ -137,9 +137,7 @@ STATIC void apm_disconnect __P((void *));
|
||||||
#endif
|
#endif
|
||||||
STATIC void apm_perror __P((const char *, struct apmregs *, ...))
|
STATIC void apm_perror __P((const char *, struct apmregs *, ...))
|
||||||
__kprintf_attribute__((__format__(__printf__,1,3)));
|
__kprintf_attribute__((__format__(__printf__,1,3)));
|
||||||
#if 0
|
|
||||||
STATIC void apm_powmgt_enable __P((int));
|
STATIC void apm_powmgt_enable __P((int));
|
||||||
#endif
|
|
||||||
STATIC void apm_powmgt_engage __P((int, u_int));
|
STATIC void apm_powmgt_engage __P((int, u_int));
|
||||||
#if 0
|
#if 0
|
||||||
STATIC void apm_devpowmgt_enable __P((int, u_int));
|
STATIC void apm_devpowmgt_enable __P((int, u_int));
|
||||||
|
@ -293,6 +291,7 @@ int apm_userstandbys = 0;
|
||||||
int apm_suspends = 0;
|
int apm_suspends = 0;
|
||||||
int apm_battlow = 0;
|
int apm_battlow = 0;
|
||||||
int apm_damn_fool_bios = 0;
|
int apm_damn_fool_bios = 0;
|
||||||
|
int apm_op_inprog = 0;
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
apm_get_powstate(dev)
|
apm_get_powstate(dev)
|
||||||
|
@ -321,6 +320,10 @@ apm_standby()
|
||||||
|
|
||||||
static int apm_evindex = 0;
|
static int apm_evindex = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return 0 if the user will notice and handle the event,
|
||||||
|
* return 1 if the kernel driver should do so.
|
||||||
|
*/
|
||||||
STATIC int
|
STATIC int
|
||||||
apm_record_event(sc, event_type)
|
apm_record_event(sc, event_type)
|
||||||
struct apm_softc *sc;
|
struct apm_softc *sc;
|
||||||
|
@ -352,33 +355,42 @@ struct apmregs *regs;
|
||||||
|
|
||||||
switch(regs->bx) {
|
switch(regs->bx) {
|
||||||
case APM_USER_STANDBY_REQ:
|
case APM_USER_STANDBY_REQ:
|
||||||
DPRINTF(("user wants STANDBY--fat chance\n"));
|
DPRINTF(("user standby requested\n"));
|
||||||
(void) apm_set_powstate(APM_DEV_ALLDEVS, APM_LASTREQ_REJECTED);
|
#ifdef APM_NO_STANDBY
|
||||||
#ifndef APM_NO_STANDBY
|
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
||||||
|
APM_LASTREQ_REJECTED);
|
||||||
|
apm_powmgt_enable(1); /* in case BIOS hates being spurned */
|
||||||
|
#else
|
||||||
if (apm_record_event(sc, regs->bx))
|
if (apm_record_event(sc, regs->bx))
|
||||||
apm_userstandbys++;
|
apm_userstandbys++;
|
||||||
|
apm_op_inprog++;
|
||||||
|
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
||||||
|
APM_LASTREQ_INPROG);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case APM_STANDBY_REQ:
|
case APM_STANDBY_REQ:
|
||||||
DPRINTF(("standby requested\n"));
|
DPRINTF(("standby requested\n"));
|
||||||
if (apm_standbys || apm_suspends)
|
if (apm_standbys || apm_suspends)
|
||||||
DPRINTF(("damn fool BIOS did not wait for answer\n"));
|
DPRINTF(("damn fool BIOS did not wait for answer\n"));
|
||||||
#ifndef APM_NO_STANDBY
|
#ifdef APM_NO_STANDBY
|
||||||
if (apm_record_event(sc, regs->bx)) {
|
|
||||||
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
|
||||||
APM_LASTREQ_INPROG);
|
|
||||||
apm_standbys++;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
|
||||||
APM_LASTREQ_REJECTED);
|
|
||||||
break;
|
|
||||||
case APM_USER_SUSPEND_REQ:
|
|
||||||
DPRINTF(("user wants suspend--fat chance!\n"));
|
|
||||||
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
||||||
APM_LASTREQ_REJECTED);
|
APM_LASTREQ_REJECTED);
|
||||||
|
apm_powmgt_enable(1); /* in case BIOS hates being spurned */
|
||||||
|
#else
|
||||||
|
if (apm_record_event(sc, regs->bx))
|
||||||
|
apm_standbys++;
|
||||||
|
apm_op_inprog++;
|
||||||
|
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
||||||
|
APM_LASTREQ_INPROG);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case APM_USER_SUSPEND_REQ:
|
||||||
|
DPRINTF(("user wants suspend\n"));
|
||||||
if (apm_record_event(sc, regs->bx))
|
if (apm_record_event(sc, regs->bx))
|
||||||
apm_suspends++;
|
apm_suspends++;
|
||||||
|
apm_op_inprog++;
|
||||||
|
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
||||||
|
APM_LASTREQ_INPROG);
|
||||||
break;
|
break;
|
||||||
case APM_SUSPEND_REQ:
|
case APM_SUSPEND_REQ:
|
||||||
DPRINTF(("suspend requested\n"));
|
DPRINTF(("suspend requested\n"));
|
||||||
|
@ -387,13 +399,11 @@ struct apmregs *regs;
|
||||||
/* just give up the fight */
|
/* just give up the fight */
|
||||||
apm_damn_fool_bios = 1;
|
apm_damn_fool_bios = 1;
|
||||||
}
|
}
|
||||||
if (apm_record_event(sc, regs->bx)) {
|
if (apm_record_event(sc, regs->bx))
|
||||||
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
|
||||||
APM_LASTREQ_INPROG);
|
|
||||||
apm_suspends++;
|
apm_suspends++;
|
||||||
} else
|
apm_op_inprog++;
|
||||||
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
(void) apm_set_powstate(APM_DEV_ALLDEVS,
|
||||||
APM_LASTREQ_REJECTED);
|
APM_LASTREQ_INPROG);
|
||||||
break;
|
break;
|
||||||
case APM_POWER_CHANGE:
|
case APM_POWER_CHANGE:
|
||||||
DPRINTF(("power status change\n"));
|
DPRINTF(("power status change\n"));
|
||||||
|
@ -409,7 +419,7 @@ struct apmregs *regs;
|
||||||
apm_record_event(sc, regs->bx);
|
apm_record_event(sc, regs->bx);
|
||||||
break;
|
break;
|
||||||
case APM_CRIT_RESUME:
|
case APM_CRIT_RESUME:
|
||||||
DPRINTF(("system resumed without us!\n"));
|
DPRINTF(("resume from critical system suspend!\n"));
|
||||||
inittodr(time.tv_sec);
|
inittodr(time.tv_sec);
|
||||||
apm_record_event(sc, regs->bx);
|
apm_record_event(sc, regs->bx);
|
||||||
break;
|
break;
|
||||||
|
@ -452,14 +462,23 @@ void *arg;
|
||||||
struct apmregs regs;
|
struct apmregs regs;
|
||||||
struct apm_softc *sc = arg;
|
struct apm_softc *sc = arg;
|
||||||
|
|
||||||
while (apm_get_event(®s) == 0 && !apm_damn_fool_bios) {
|
/*
|
||||||
|
* tell the BIOS we're working on it, if asked to do a
|
||||||
|
* suspend/standby
|
||||||
|
*/
|
||||||
|
if (apm_op_inprog)
|
||||||
|
apm_set_powstate(APM_DEV_ALLDEVS, APM_LASTREQ_INPROG);
|
||||||
|
|
||||||
|
while (apm_get_event(®s) == 0 && !apm_damn_fool_bios)
|
||||||
apm_event_handle(sc, ®s);
|
apm_event_handle(sc, ®s);
|
||||||
};
|
|
||||||
if (APM_ERR_CODE(®s) != APM_ERR_NOEVENTS)
|
if (APM_ERR_CODE(®s) != APM_ERR_NOEVENTS)
|
||||||
apm_perror("get event", ®s);
|
apm_perror("get event", ®s);
|
||||||
if (apm_suspends) {
|
if (apm_suspends) {
|
||||||
|
apm_op_inprog = 0;
|
||||||
apm_suspend();
|
apm_suspend();
|
||||||
} else if (apm_standbys || apm_userstandbys) {
|
} else if (apm_standbys || apm_userstandbys) {
|
||||||
|
apm_op_inprog = 0;
|
||||||
apm_standby();
|
apm_standby();
|
||||||
}
|
}
|
||||||
apm_suspends = apm_standbys = apm_battlow = apm_userstandbys = 0;
|
apm_suspends = apm_standbys = apm_battlow = apm_userstandbys = 0;
|
||||||
|
@ -467,20 +486,17 @@ void *arg;
|
||||||
timeout(apm_periodic_check, sc, hz);
|
timeout(apm_periodic_check, sc, hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
STATIC void
|
STATIC void
|
||||||
apm_powmgt_enable(onoff)
|
apm_powmgt_enable(onoff)
|
||||||
int onoff;
|
int onoff;
|
||||||
{
|
{
|
||||||
struct apmregs regs;
|
struct apmregs regs;
|
||||||
regs.bx = apm_minver == 0 ? APM_MGT_ALL : APM_DEV_APM_BIOS;
|
regs.bx = apm_minver == 0 ? APM_MGT_ALL : APM_DEV_ALLDEVS;
|
||||||
regs.cx = onoff ? APM_MGT_ENABLE : APM_MGT_DISABLE;
|
regs.cx = onoff ? APM_MGT_ENABLE : APM_MGT_DISABLE;
|
||||||
if (APMCALL(APM_PWR_MGT_ENABLE, ®s) != 0)
|
if (APMCALL(APM_PWR_MGT_ENABLE, ®s) != 0)
|
||||||
apm_perror("power management enable <%s %s>", ®s,
|
apm_perror("power management enable all <%s>", ®s,
|
||||||
apm_minver == 0 ? "all" : "apmbios",
|
|
||||||
onoff ? "enable" : "disable");
|
onoff ? "enable" : "disable");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
apm_powmgt_engage(onoff, dev)
|
apm_powmgt_engage(onoff, dev)
|
||||||
|
@ -939,6 +955,14 @@ apmattach(parent, self, aux)
|
||||||
&apminfo.apm_segsel,
|
&apminfo.apm_segsel,
|
||||||
apmsc->sc_dev.dv_xname));
|
apmsc->sc_dev.dv_xname));
|
||||||
apm_set_ver(apmsc);
|
apm_set_ver(apmsc);
|
||||||
|
/*
|
||||||
|
* enable power management if it's disabled.
|
||||||
|
*/
|
||||||
|
/* XXX some bogus APM BIOSes don't set the disabled bit in
|
||||||
|
the connect state, yet still complain about the functions
|
||||||
|
being disabled when other calls are made. sigh. */
|
||||||
|
if (apminfo.apm_detail & APM_BIOS_PM_DISABLED)
|
||||||
|
apm_powmgt_enable(1);
|
||||||
/*
|
/*
|
||||||
* Engage cooperative power mgt (we get to do it)
|
* Engage cooperative power mgt (we get to do it)
|
||||||
* on all devices (v1.1).
|
* on all devices (v1.1).
|
||||||
|
|
Loading…
Reference in New Issue