/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include </386/include/ureg.h>typedef struct Ureg Ureg;#include <auth.h>#include <fcall.h>#include <thread.h>#include <9p.h> enum { /* power mgmt event codes */ NotifyStandbyRequest = 0x0001, NotifySuspendRequest = 0x0002, NotifyNormalResume = 0x0003, NotifyCriticalResume = 0x0004, NotifyBatteryLow = 0x0005, NotifyPowerStatusChange = 0x0006, NotifyUpdateTime = 0x0007, NotifyCriticalSuspend = 0x0008, NotifyUserStandbyRequest = 0x0009, NotifyUserSuspendRequest = 0x000A, NotifyStandbyResume = 0x000B, NotifyCapabilitiesChange = 0x000C, /* power device ids: add device number or All */ DevBios = 0x0000, DevAll = 0x0001, DevDisplay = 0x0100, DevStorage = 0x0200, DevLpt = 0x0300, DevEia = 0x0400, DevNetwork = 0x0500, DevPCMCIA = 0x0600, DevBattery = 0x8000, All = 0x00FF, DevMask = 0xFF00, /* power states */ PowerEnabled = 0x0000, PowerStandby = 0x0001, PowerSuspend = 0x0002, PowerOff = 0x0003, /* apm commands */ CmdInstallationCheck = 0x5300, CmdRealModeConnect = 0x5301, CmdProtMode16Connect = 0x5302, CmdProtMode32Connect = 0x5303, CmdDisconnect = 0x5304, CmdCpuIdle = 0x5305, CmdCpuBusy = 0x5306, CmdSetPowerState = 0x5307, CmdSetPowerMgmt = 0x5308, DisablePowerMgmt = 0x0000, /* CX */ EnablePowerMgmt = 0x0001, CmdRestoreDefaults = 0x5309, CmdGetPowerStatus = 0x530A, CmdGetPMEvent = 0x530B, CmdGetPowerState = 0x530C, CmdGetPowerMgmt = 0x530D, CmdDriverVersion = 0x530E, /* like CmdDisconnect but doesn't lose the interface */ CmdGagePowerMgmt = 0x530F, DisengagePowerMgmt = 0x0000, /* CX */ EngagePowerManagemenet = 0x0001, CmdGetCapabilities = 0x5310, CapStandby = 0x0001, CapSuspend = 0x0002, CapTimerResumeStandby = 0x0004, CapTimerResumeSuspend = 0x0008, CapRingResumeStandby = 0x0010, CapRingResumeSuspend = 0x0020, CapPcmciaResumeStandby = 0x0040, CapPcmciaResumeSuspend = 0x0080, CapSlowCpu = 0x0100, CmdResumeTimer = 0x5311, DisableResumeTimer = 0x00, /* CL */ GetResumeTimer = 0x01, SetResumeTimer = 0x02, CmdResumeOnRing = 0x5312, DisableResumeOnRing = 0x0000, /* CX */ EnableResumeOnRing = 0x0001, GetResumeOnRing = 0x0002, CmdTimerRequests = 0x5313, DisableTimerRequests = 0x0000, /* CX */ EnableTimerRequests = 0x0001, GetTimerRequests = 0x0002,}; static char* eventstr[] = {[NotifyStandbyRequest] "system standby request",[NotifySuspendRequest] "system suspend request",[NotifyNormalResume] "normal resume",[NotifyCriticalResume] "critical resume",[NotifyBatteryLow] "battery low",[NotifyPowerStatusChange] "power status change",[NotifyUpdateTime] "update time",[NotifyCriticalSuspend] "critical suspend",[NotifyUserStandbyRequest] "user standby request",[NotifyUserSuspendRequest] "user suspend request",[NotifyCapabilitiesChange] "capabilities change",}; static char*apmevent(int e){ static char buf[32]; if(0 <= e && e < nelem(eventstr) && eventstr[e]) return eventstr[e]; sprint(buf, "event 0x%ux", (uint)e); return buf;} static char *error[256] = {[0x01] "power mgmt disabled",[0x02] "real mode connection already established",[0x03] "interface not connected",[0x05] "16-bit protected mode connection already established",[0x06] "16-bit protected mode interface not supported",[0x07] "32-bit protected mode interface already established",[0x08] "32-bit protected mode interface not supported",[0x09] "unrecognized device id",[0x0A] "parameter value out of range",[0x0B] "interface not engaged",[0x0C] "function not supported",[0x0D] "resume timer disabled",[0x60] "unable to enter requested state",[0x80] "no power mgmt events pending",[0x86] "apm not present",}; static char*apmerror(int id){ char *e; static char buf[64]; if(e = error[id&0xFF]) return e; sprint(buf, "unknown error %x", id); return buf;} QLock apmlock;int apmdebug; static int_apmcall(int fd, Ureg *u){if(apmdebug) fprint(2, "call ax 0x%lux bx 0x%lux cx 0x%lux\n", u->ax&0xFFFF, u->bx&0xFFFF, u->cx&0xFFFF); seek(fd, 0, 0); if(write(fd, u, sizeof *u) != sizeof *u) return -1; seek(fd, 0, 0); if(read(fd, u, sizeof *u) != sizeof *u) return -1; if(apmdebug) fprint(2, "flags 0x%lux ax 0x%lux bx 0x%lux cx 0x%lux\n", u->flags&0xFFFF, u->ax&0xFFFF, u->bx&0xFFFF, u->cx&0xFFFF); if(u->flags & 1) { /* carry flag */ werrstr("%s", apmerror(u->ax>>8)); return -1; } return 0;} static intapmcall(int fd, Ureg *u){ int r; qlock(&apmlock); r = _apmcall(fd, u); qunlock(&apmlock); return r;} typedef struct Apm Apm;typedef struct Battery Battery; struct Battery { int status; int percent; int time;}; enum { Mbattery = 4,};struct Apm { int fd; int verhi; int verlo; int acstatus; int nbattery; int capabilities; Battery battery[Mbattery];};enum { AcUnknown = 0, /* Apm.acstatus */ AcOffline, AcOnline, AcBackup, BatteryUnknown = 0, /* Battery.status */ BatteryHigh, BatteryLow, BatteryCritical, BatteryCharging,}; static char*acstatusstr[] = {[AcUnknown] "unknown",[AcOffline] "offline",[AcOnline] "online",[AcBackup] "backup",}; static char*batterystatusstr[] = {[BatteryUnknown] "unknown",[BatteryHigh] "high",[BatteryLow] "low",[BatteryCritical] "critical",[BatteryCharging] "charging",}; static char*powerstatestr[] = {[PowerOff] "off",[PowerSuspend] "suspend",[PowerStandby] "standby",[PowerEnabled] "on",}; static char*xstatus(char **str, int nstr, int x){ if(0 <= x && x < nstr && str[x]) return str[x]; return "unknown";} static char*batterystatus(int b){ return xstatus(batterystatusstr, nelem(batterystatusstr), b);} static char*powerstate(int s){ return xstatus(powerstatestr, nelem(powerstatestr), s);} static char*acstatus(int a){ return xstatus(acstatusstr, nelem(acstatusstr), a);} static intapmversion(Apm *apm){ Ureg u; u.ax = CmdDriverVersion; u.bx = 0x0000; u.cx = 0x0102; if(apmcall(apm->fd, &u) < 0) return -1; apm->verhi = u.cx>>8; apm->verlo = u.cx & 0xFF; return u.cx;} static intapmcpuidle(Apm *apm){ Ureg u; u.ax = CmdCpuIdle; return apmcall(apm->fd, &u);} static intapmcpubusy(Apm *apm){ Ureg u; u.ax = CmdCpuBusy; return apmcall(apm->fd, &u);} static intapmsetpowerstate(Apm *apm, int dev, int state){ Ureg u; u.ax = CmdSetPowerState; u.bx = dev; u.cx = state; return apmcall(apm->fd, &u);} static intapmsetpowermgmt(Apm *apm, int dev, int state){ Ureg u; u.ax = CmdSetPowerMgmt; u.bx = dev; u.cx = state; return apmcall(apm->fd, &u);} static intapmrestoredefaults(Apm *apm, int dev){ Ureg u; u.ax = CmdRestoreDefaults; u.bx = dev; return apmcall(apm->fd, &u);} static intapmgetpowerstatus(Apm *apm, int dev){ Battery *b; Ureg u; if(dev == DevAll) b = &apm->battery[0]; else if((dev & DevMask) == DevBattery) { if(dev - DevBattery < nelem(apm->battery)) b = &apm->battery[dev - DevBattery]; else b = nil; } else { werrstr("bad device number"); return -1; } u.ax = CmdGetPowerStatus; u.bx = dev; if(apmcall(apm->fd, &u) < 0) return -1; if((dev & DevMask) == DevBattery) apm->nbattery = u.si; switch(u.bx>>8) { case 0x00: apm->acstatus = AcOffline; break; case 0x01: apm->acstatus = AcOnline; break; case 0x02: apm->acstatus = AcBackup; break; default: apm->acstatus = AcUnknown; break; } if(b != nil) { switch(u.bx&0xFF) { case 0x00: b->status = BatteryHigh; break; case 0x01: b->status = BatteryLow; break; case 0x02: b->status = BatteryCritical; break; case 0x03: b->status = BatteryCharging; break; default: b->status = BatteryUnknown; break; } if((u.cx & 0xFF) == 0xFF) b->percent = -1; else b->percent = u.cx & 0xFF; if((u.dx&0xFFFF) == 0xFFFF) b->time = -1; else if(u.dx & 0x8000) b->time = 60*(u.dx & 0x7FFF); else b->time = u.dx & 0x7FFF; } return 0;} static intapmgetevent(Apm *apm){ Ureg u; u.ax = CmdGetPMEvent; u.bx = 0; u.cx = 0; //when u.bx == NotifyNormalResume or NotifyCriticalResume, //u.cx & 1 indicates PCMCIA socket was on while suspended, //u.cx & 1 == 0 indicates was off. if(apmcall(apm->fd, &u) < 0) return -1; return u.bx;} static intapmgetpowerstate(Apm *apm, int dev){ Ureg u; u.ax = CmdGetPowerState; u.bx = dev; u.cx = 0; if(apmcall(apm->fd, &u) < 0) return -1; return u.cx;} static intapmgetpowermgmt(Apm *apm, int dev){ Ureg u; u.ax = CmdGetPowerMgmt; u.bx = dev; if(apmcall(apm->fd, &u) < 0) return -1; return u.cx;} static intapmgetcapabilities(Apm *apm){ Ureg u; u.ax = CmdGetCapabilities; u.bx = DevBios; if(apmcall(apm->fd, &u) < 0) return -1; apm->nbattery = u.bx & 0xFF; apm->capabilities &= ~0xFFFF; apm->capabilities |= u.cx; return 0;} static intapminstallationcheck(Apm *apm){ Ureg u; u.ax = CmdInstallationCheck; u.bx = DevBios;Lines 1–500 of 1163. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h> #include <libc.h> #include </386/include/ureg.h> typedef struct Ureg Ureg; #include <auth.h> #include <fcall.h> #include <thread.h> #include <9p.h> enum { /* power mgmt event codes */ NotifyStandbyRequest = 0x0001, NotifySuspendRequest = 0x0002, NotifyNormalResume = 0x0003, NotifyCriticalResume = 0x0004, NotifyBatteryLow = 0x0005, NotifyPowerStatusChange = 0x0006, NotifyUpdateTime = 0x0007, NotifyCriticalSuspend = 0x0008, NotifyUserStandbyRequest = 0x0009, NotifyUserSuspendRequest = 0x000A, NotifyStandbyResume = 0x000B, NotifyCapabilitiesChange = 0x000C, /* power device ids: add device number or All */ DevBios = 0x0000, DevAll = 0x0001, DevDisplay = 0x0100, DevStorage = 0x0200, DevLpt = 0x0300, DevEia = 0x0400, DevNetwork = 0x0500, DevPCMCIA = 0x0600, DevBattery = 0x8000, All = 0x00FF, DevMask = 0xFF00, /* power states */ PowerEnabled = 0x0000, PowerStandby = 0x0001, PowerSuspend = 0x0002, PowerOff = 0x0003, /* apm commands */ CmdInstallationCheck = 0x5300, CmdRealModeConnect = 0x5301, CmdProtMode16Connect = 0x5302, CmdProtMode32Connect = 0x5303, CmdDisconnect = 0x5304, CmdCpuIdle = 0x5305, CmdCpuBusy = 0x5306, CmdSetPowerState = 0x5307, CmdSetPowerMgmt = 0x5308, DisablePowerMgmt = 0x0000, /* CX */ EnablePowerMgmt = 0x0001, CmdRestoreDefaults = 0x5309, CmdGetPowerStatus = 0x530A, CmdGetPMEvent = 0x530B, CmdGetPowerState = 0x530C, CmdGetPowerMgmt = 0x530D, CmdDriverVersion = 0x530E, /* like CmdDisconnect but doesn't lose the interface */ CmdGagePowerMgmt = 0x530F, DisengagePowerMgmt = 0x0000, /* CX */ EngagePowerManagemenet = 0x0001, CmdGetCapabilities = 0x5310, CapStandby = 0x0001, CapSuspend = 0x0002, CapTimerResumeStandby = 0x0004, CapTimerResumeSuspend = 0x0008, CapRingResumeStandby = 0x0010, CapRingResumeSuspend = 0x0020, CapPcmciaResumeStandby = 0x0040, CapPcmciaResumeSuspend = 0x0080, CapSlowCpu = 0x0100, CmdResumeTimer = 0x5311, DisableResumeTimer = 0x00, /* CL */ GetResumeTimer = 0x01, SetResumeTimer = 0x02, CmdResumeOnRing = 0x5312, DisableResumeOnRing = 0x0000, /* CX */ EnableResumeOnRing = 0x0001, GetResumeOnRing = 0x0002, CmdTimerRequests = 0x5313, DisableTimerRequests = 0x0000, /* CX */ EnableTimerRequests = 0x0001, GetTimerRequests = 0x0002, }; static char* eventstr[] = { [NotifyStandbyRequest] "system standby request", [NotifySuspendRequest] "system suspend request", [NotifyNormalResume] "normal resume", [NotifyCriticalResume] "critical resume", [NotifyBatteryLow] "battery low", [NotifyPowerStatusChange] "power status change", [NotifyUpdateTime] "update time", [NotifyCriticalSuspend] "critical suspend", [NotifyUserStandbyRequest] "user standby request", [NotifyUserSuspendRequest] "user suspend request", [NotifyCapabilitiesChange] "capabilities change", }; static char* apmevent(int e) { static char buf[32]; if(0 <= e && e < nelem(eventstr) && eventstr[e]) return eventstr[e]; sprint(buf, "event 0x%ux", (uint)e); return buf; } static char *error[256] = { [0x01] "power mgmt disabled", [0x02] "real mode connection already established", [0x03] "interface not connected", [0x05] "16-bit protected mode connection already established", [0x06] "16-bit protected mode interface not supported", [0x07] "32-bit protected mode interface already established", [0x08] "32-bit protected mode interface not supported", [0x09] "unrecognized device id", [0x0A] "parameter value out of range", [0x0B] "interface not engaged", [0x0C] "function not supported", [0x0D] "resume timer disabled", [0x60] "unable to enter requested state", [0x80] "no power mgmt events pending", [0x86] "apm not present", }; static char* apmerror(int id) { char *e; static char buf[64]; if(e = error[id&0xFF]) return e; sprint(buf, "unknown error %x", id); return buf; } QLock apmlock; int apmdebug; static int _apmcall(int fd, Ureg *u) { if(apmdebug) fprint(2, "call ax 0x%lux bx 0x%lux cx 0x%lux\n", u->ax&0xFFFF, u->bx&0xFFFF, u->cx&0xFFFF); seek(fd, 0, 0); if(write(fd, u, sizeof *u) != sizeof *u) return -1; seek(fd, 0, 0); if(read(fd, u, sizeof *u) != sizeof *u) return -1; if(apmdebug) fprint(2, "flags 0x%lux ax 0x%lux bx 0x%lux cx 0x%lux\n", u->flags&0xFFFF, u->ax&0xFFFF, u->bx&0xFFFF, u->cx&0xFFFF); if(u->flags & 1) { /* carry flag */ werrstr("%s", apmerror(u->ax>>8)); return -1; } return 0; } static int apmcall(int fd, Ureg *u) { int r; qlock(&apmlock); r = _apmcall(fd, u); qunlock(&apmlock); return r; } typedef struct Apm Apm; typedef struct Battery Battery; struct Battery { int status; int percent; int time; }; enum { Mbattery = 4, }; struct Apm { int fd; int verhi; int verlo; int acstatus; int nbattery; int capabilities; Battery battery[Mbattery]; }; enum { AcUnknown = 0, /* Apm.acstatus */ AcOffline, AcOnline, AcBackup, BatteryUnknown = 0, /* Battery.status */ BatteryHigh, BatteryLow, BatteryCritical, BatteryCharging, }; static char* acstatusstr[] = { [AcUnknown] "unknown", [AcOffline] "offline", [AcOnline] "online", [AcBackup] "backup", }; static char* batterystatusstr[] = { [BatteryUnknown] "unknown", [BatteryHigh] "high", [BatteryLow] "low", [BatteryCritical] "critical", [BatteryCharging] "charging", }; static char* powerstatestr[] = { [PowerOff] "off", [PowerSuspend] "suspend", [PowerStandby] "standby", [PowerEnabled] "on", }; static char* xstatus(char **str, int nstr, int x) { if(0 <= x && x < nstr && str[x]) return str[x]; return "unknown"; } static char* batterystatus(int b) { return xstatus(batterystatusstr, nelem(batterystatusstr), b); } static char* powerstate(int s) { return xstatus(powerstatestr, nelem(powerstatestr), s); } static char* acstatus(int a) { return xstatus(acstatusstr, nelem(acstatusstr), a); } static int apmversion(Apm *apm) { Ureg u; u.ax = CmdDriverVersion; u.bx = 0x0000; u.cx = 0x0102; if(apmcall(apm->fd, &u) < 0) return -1; apm->verhi = u.cx>>8; apm->verlo = u.cx & 0xFF; return u.cx; } static int apmcpuidle(Apm *apm) { Ureg u; u.ax = CmdCpuIdle; return apmcall(apm->fd, &u); } static int apmcpubusy(Apm *apm) { Ureg u; u.ax = CmdCpuBusy; return apmcall(apm->fd, &u); } static int apmsetpowerstate(Apm *apm, int dev, int state) { Ureg u; u.ax = CmdSetPowerState; u.bx = dev; u.cx = state; return apmcall(apm->fd, &u); } static int apmsetpowermgmt(Apm *apm, int dev, int state) { Ureg u; u.ax = CmdSetPowerMgmt; u.bx = dev; u.cx = state; return apmcall(apm->fd, &u); } static int apmrestoredefaults(Apm *apm, int dev) { Ureg u; u.ax = CmdRestoreDefaults; u.bx = dev; return apmcall(apm->fd, &u); } static int apmgetpowerstatus(Apm *apm, int dev) { Battery *b; Ureg u; if(dev == DevAll) b = &apm->battery[0]; else if((dev & DevMask) == DevBattery) { if(dev - DevBattery < nelem(apm->battery)) b = &apm->battery[dev - DevBattery]; else b = nil; } else { werrstr("bad device number"); return -1; } u.ax = CmdGetPowerStatus; u.bx = dev; if(apmcall(apm->fd, &u) < 0) return -1; if((dev & DevMask) == DevBattery) apm->nbattery = u.si; switch(u.bx>>8) { case 0x00: apm->acstatus = AcOffline; break; case 0x01: apm->acstatus = AcOnline; break; case 0x02: apm->acstatus = AcBackup; break; default: apm->acstatus = AcUnknown; break; } if(b != nil) { switch(u.bx&0xFF) { case 0x00: b->status = BatteryHigh; break; case 0x01: b->status = BatteryLow; break; case 0x02: b->status = BatteryCritical; break; case 0x03: b->status = BatteryCharging; break; default: b->status = BatteryUnknown; break; } if((u.cx & 0xFF) == 0xFF) b->percent = -1; else b->percent = u.cx & 0xFF; if((u.dx&0xFFFF) == 0xFFFF) b->time = -1; else if(u.dx & 0x8000) b->time = 60*(u.dx & 0x7FFF); else b->time = u.dx & 0x7FFF; } return 0; } static int apmgetevent(Apm *apm) { Ureg u; u.ax = CmdGetPMEvent; u.bx = 0; u.cx = 0; //when u.bx == NotifyNormalResume or NotifyCriticalResume, //u.cx & 1 indicates PCMCIA socket was on while suspended, //u.cx & 1 == 0 indicates was off. if(apmcall(apm->fd, &u) < 0) return -1; return u.bx; } static int apmgetpowerstate(Apm *apm, int dev) { Ureg u; u.ax = CmdGetPowerState; u.bx = dev; u.cx = 0; if(apmcall(apm->fd, &u) < 0) return -1; return u.cx; } static int apmgetpowermgmt(Apm *apm, int dev) { Ureg u; u.ax = CmdGetPowerMgmt; u.bx = dev; if(apmcall(apm->fd, &u) < 0) return -1; return u.cx; } static int apmgetcapabilities(Apm *apm) { Ureg u; u.ax = CmdGetCapabilities; u.bx = DevBios; if(apmcall(apm->fd, &u) < 0) return -1; apm->nbattery = u.bx & 0xFF; apm->capabilities &= ~0xFFFF; apm->capabilities |= u.cx; return 0; } static int apminstallationcheck(Apm *apm) { Ureg u; u.ax = CmdInstallationCheck; u.bx = DevBios;