static void apm_standby(struct apm_softc *sc) { int error; if (sc->sc_power_state == PWR_STANDBY) { #ifdef APMDEBUG aprint_debug_dev(sc->sc_dev, "apm_standby: already standing by?\n"); #endif return; } sc->sc_power_state = PWR_STANDBY; if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) { pmf_system_suspend(PMF_Q_NONE); apm_spl = splhigh(); } error = (*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS, APM_SYS_STANDBY); if (error) apm_resume(sc, 0, 0); else apm_resume(sc, APM_SYS_STANDBY_RESUME, 0); }
void apm_thread(void *v) { struct pxa2x0_apm_softc *sc = v; u_int type; for (;;) { APM_LOCK(sc); while (1) { if (apm_get_event(sc, &type) != 0) break; if (apm_handle_event(sc, type) != 0) break; } if (apm_suspends || apm_userstandbys /* || apm_battlow*/) { apm_suspend(sc); apm_resume(sc); } apm_battlow = apm_suspends = apm_userstandbys = 0; APM_UNLOCK(sc); tsleep(&lbolt, PWAIT, "apmev", 0); } }
static void apm_event_handle(struct apm_softc *sc, u_int event_code, u_int event_info) { int error; const char *code; struct apm_power_info pi; switch (event_code) { case APM_USER_STANDBY_REQ: DPRINTF(APMDEBUG_EVENTS, ("apmev: user standby request\n")); if (apm_do_standby) { if (apm_op_inprog == 0 && apm_record_event(sc, event_code)) apm_userstandbys++; apm_op_inprog++; (void)(*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS, APM_LASTREQ_INPROG); } else { (void)(*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS, APM_LASTREQ_REJECTED); /* in case BIOS hates being spurned */ (*sc->sc_ops->aa_enable)(sc->sc_cookie, 1); } break; case APM_STANDBY_REQ: DPRINTF(APMDEBUG_EVENTS, ("apmev: system standby request\n")); if (apm_op_inprog) { DPRINTF(APMDEBUG_EVENTS | APMDEBUG_ANOM, ("damn fool BIOS did not wait for answer\n")); /* just give up the fight */ apm_damn_fool_bios = 1; } if (apm_do_standby) { if (apm_op_inprog == 0 && apm_record_event(sc, event_code)) apm_standbys++; apm_op_inprog++; (void)(*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS, APM_LASTREQ_INPROG); } else { (void)(*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS, APM_LASTREQ_REJECTED); /* in case BIOS hates being spurned */ (*sc->sc_ops->aa_enable)(sc->sc_cookie, 1); } break; case APM_USER_SUSPEND_REQ: DPRINTF(APMDEBUG_EVENTS, ("apmev: user suspend request\n")); if (apm_op_inprog == 0 && apm_record_event(sc, event_code)) apm_suspends++; apm_op_inprog++; (void)(*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS, APM_LASTREQ_INPROG); break; case APM_SUSPEND_REQ: DPRINTF(APMDEBUG_EVENTS, ("apmev: system suspend request\n")); if (apm_op_inprog) { DPRINTF(APMDEBUG_EVENTS | APMDEBUG_ANOM, ("damn fool BIOS did not wait for answer\n")); /* just give up the fight */ apm_damn_fool_bios = 1; } if (apm_op_inprog == 0 && apm_record_event(sc, event_code)) apm_suspends++; apm_op_inprog++; (void)(*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS, APM_LASTREQ_INPROG); break; case APM_POWER_CHANGE: DPRINTF(APMDEBUG_EVENTS, ("apmev: power status change\n")); error = (*sc->sc_ops->aa_get_powstat)(sc->sc_cookie, 0, &pi); #ifdef APM_POWER_PRINT /* only print if nobody is catching events. */ if (error == 0 && (sc->sc_flags & (SCFLAG_OREAD|SCFLAG_OWRITE)) == 0) apm_power_print(sc, &pi); #else __USE(error); #endif apm_record_event(sc, event_code); break; case APM_NORMAL_RESUME: DPRINTF(APMDEBUG_EVENTS, ("apmev: resume system\n")); apm_resume(sc, event_code, event_info); break; case APM_CRIT_RESUME: DPRINTF(APMDEBUG_EVENTS, ("apmev: critical resume system")); apm_resume(sc, event_code, event_info); break; case APM_SYS_STANDBY_RESUME: DPRINTF(APMDEBUG_EVENTS, ("apmev: system standby resume\n")); apm_resume(sc, event_code, event_info); break; case APM_UPDATE_TIME: DPRINTF(APMDEBUG_EVENTS, ("apmev: update time\n")); apm_resume(sc, event_code, event_info); break; case APM_CRIT_SUSPEND_REQ: DPRINTF(APMDEBUG_EVENTS, ("apmev: critical system suspend\n")); apm_record_event(sc, event_code); apm_suspend(sc); break; case APM_BATTERY_LOW: DPRINTF(APMDEBUG_EVENTS, ("apmev: battery low\n")); apm_battlow++; apm_record_event(sc, event_code); break; case APM_CAP_CHANGE: DPRINTF(APMDEBUG_EVENTS, ("apmev: capability change\n")); if (apm_minver < 2) { DPRINTF(APMDEBUG_EVENTS, ("apm: unexpected event\n")); } else { u_int numbatts, capflags; (*sc->sc_ops->aa_get_capabilities)(sc->sc_cookie, &numbatts, &capflags); (*sc->sc_ops->aa_get_powstat)(sc->sc_cookie, 0, &pi); } break; default: switch (event_code >> 8) { case 0: code = "reserved system"; break; case 1: code = "reserved device"; break; case 2: code = "OEM defined"; break; default: code = "reserved"; break; } printf("APM: %s event code %x\n", code, event_code); } }
int apm_handle_event(struct apm_softc *sc, struct apmregs *regs) { struct apmregs nregs; int ret = 0; switch (regs->bx) { case APM_NOEVENT: ret++; break; case APM_USER_STANDBY_REQ: if (apm_resumes || apm_op_inprog) break; DPRINTF(("user wants STANDBY--fat chance\n")); apm_op_inprog++; if (apm_record_event(sc, regs->bx)) { DPRINTF(("standby ourselves\n")); apm_userstandbys++; } break; case APM_STANDBY_REQ: if (apm_resumes || apm_op_inprog) break; DPRINTF(("standby requested\n")); if (apm_standbys || apm_suspends) { DPRINTF(("premature standby\n")); apm_error++; ret++; } apm_op_inprog++; if (apm_record_event(sc, regs->bx)) { DPRINTF(("standby ourselves\n")); apm_standbys++; } break; case APM_USER_SUSPEND_REQ: if (apm_resumes || apm_op_inprog) break; DPRINTF(("user wants suspend--fat chance!\n")); apm_op_inprog++; if (apm_record_event(sc, regs->bx)) { DPRINTF(("suspend ourselves\n")); apm_suspends++; } break; case APM_SUSPEND_REQ: if (apm_resumes || apm_op_inprog) break; DPRINTF(("suspend requested\n")); if (apm_standbys || apm_suspends) { DPRINTF(("premature suspend\n")); apm_error++; ret++; } apm_op_inprog++; if (apm_record_event(sc, regs->bx)) { DPRINTF(("suspend ourselves\n")); apm_suspends++; } break; case APM_POWER_CHANGE: DPRINTF(("power status change\n")); apm_get_powstat(&nregs); apm_record_event(sc, regs->bx); break; case APM_NORMAL_RESUME: DPRINTF(("system resumed\n")); apm_resume(sc, regs); break; case APM_CRIT_RESUME: DPRINTF(("system resumed without us!\n")); apm_resume(sc, regs); break; case APM_SYS_STANDBY_RESUME: DPRINTF(("system standby resume\n")); apm_resume(sc, regs); break; case APM_UPDATE_TIME: DPRINTF(("update time, please\n")); inittodr(time_second); apm_record_event(sc, regs->bx); break; case APM_CRIT_SUSPEND_REQ: DPRINTF(("suspend required immediately\n")); apm_record_event(sc, regs->bx); apm_suspend(APM_SYS_SUSPEND); break; case APM_BATTERY_LOW: DPRINTF(("Battery low!\n")); apm_battlow++; apm_record_event(sc, regs->bx); break; case APM_CAPABILITY_CHANGE: DPRINTF(("capability change\n")); if (apm_minver < 2) { DPRINTF(("adult event\n")); } else { if (apmcall(APM_GET_CAPABILITIES, APM_DEV_APM_BIOS, &nregs) != 0) { apm_perror("get capabilities", &nregs); } else { apm_get_powstat(&nregs); } } break; default: { #ifdef APMDEBUG char *p; switch (regs->bx >> 8) { case 0: p = "reserved system"; break; case 1: p = "reserved device"; break; case 2: p = "OEM defined"; break; default:p = "reserved"; break; } #endif DPRINTF(("apm_handle_event: %s event, code %d\n", p, regs->bx)); } } return ret; }