180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include </386/include/ureg.h>
480ee5cbfSDavid du Colombier typedef struct Ureg Ureg;
580ee5cbfSDavid du Colombier #include <auth.h>
680ee5cbfSDavid du Colombier #include <fcall.h>
780ee5cbfSDavid du Colombier #include <thread.h>
880ee5cbfSDavid du Colombier #include <9p.h>
980ee5cbfSDavid du Colombier
1080ee5cbfSDavid du Colombier enum {
1180ee5cbfSDavid du Colombier /* power mgmt event codes */
1280ee5cbfSDavid du Colombier NotifyStandbyRequest = 0x0001,
1380ee5cbfSDavid du Colombier NotifySuspendRequest = 0x0002,
1480ee5cbfSDavid du Colombier NotifyNormalResume = 0x0003,
1580ee5cbfSDavid du Colombier NotifyCriticalResume = 0x0004,
1680ee5cbfSDavid du Colombier NotifyBatteryLow = 0x0005,
1780ee5cbfSDavid du Colombier NotifyPowerStatusChange = 0x0006,
1880ee5cbfSDavid du Colombier NotifyUpdateTime = 0x0007,
1980ee5cbfSDavid du Colombier NotifyCriticalSuspend = 0x0008,
2080ee5cbfSDavid du Colombier NotifyUserStandbyRequest = 0x0009,
2180ee5cbfSDavid du Colombier NotifyUserSuspendRequest = 0x000A,
2280ee5cbfSDavid du Colombier NotifyStandbyResume = 0x000B,
2380ee5cbfSDavid du Colombier NotifyCapabilitiesChange = 0x000C,
2480ee5cbfSDavid du Colombier
2580ee5cbfSDavid du Colombier /* power device ids: add device number or All */
2680ee5cbfSDavid du Colombier DevBios = 0x0000,
2780ee5cbfSDavid du Colombier DevAll = 0x0001,
2880ee5cbfSDavid du Colombier DevDisplay = 0x0100,
2980ee5cbfSDavid du Colombier DevStorage = 0x0200,
3080ee5cbfSDavid du Colombier DevLpt = 0x0300,
3180ee5cbfSDavid du Colombier DevEia = 0x0400,
3280ee5cbfSDavid du Colombier DevNetwork = 0x0500,
3380ee5cbfSDavid du Colombier DevPCMCIA = 0x0600,
3480ee5cbfSDavid du Colombier DevBattery = 0x8000,
3580ee5cbfSDavid du Colombier All = 0x00FF,
3680ee5cbfSDavid du Colombier DevMask = 0xFF00,
3780ee5cbfSDavid du Colombier
3880ee5cbfSDavid du Colombier /* power states */
3980ee5cbfSDavid du Colombier PowerEnabled = 0x0000,
4080ee5cbfSDavid du Colombier PowerStandby = 0x0001,
4180ee5cbfSDavid du Colombier PowerSuspend = 0x0002,
4280ee5cbfSDavid du Colombier PowerOff = 0x0003,
4380ee5cbfSDavid du Colombier
4480ee5cbfSDavid du Colombier /* apm commands */
4580ee5cbfSDavid du Colombier CmdInstallationCheck = 0x5300,
4680ee5cbfSDavid du Colombier CmdRealModeConnect = 0x5301,
4780ee5cbfSDavid du Colombier CmdProtMode16Connect = 0x5302,
4880ee5cbfSDavid du Colombier CmdProtMode32Connect = 0x5303,
4980ee5cbfSDavid du Colombier CmdDisconnect = 0x5304,
5080ee5cbfSDavid du Colombier CmdCpuIdle = 0x5305,
5180ee5cbfSDavid du Colombier CmdCpuBusy = 0x5306,
5280ee5cbfSDavid du Colombier CmdSetPowerState = 0x5307,
5380ee5cbfSDavid du Colombier CmdSetPowerMgmt = 0x5308,
5480ee5cbfSDavid du Colombier DisablePowerMgmt = 0x0000, /* CX */
5580ee5cbfSDavid du Colombier EnablePowerMgmt = 0x0001,
5680ee5cbfSDavid du Colombier CmdRestoreDefaults = 0x5309,
5780ee5cbfSDavid du Colombier CmdGetPowerStatus = 0x530A,
5880ee5cbfSDavid du Colombier CmdGetPMEvent = 0x530B,
5980ee5cbfSDavid du Colombier CmdGetPowerState = 0x530C,
6080ee5cbfSDavid du Colombier CmdGetPowerMgmt = 0x530D,
6180ee5cbfSDavid du Colombier CmdDriverVersion = 0x530E,
6280ee5cbfSDavid du Colombier
6380ee5cbfSDavid du Colombier /* like CmdDisconnect but doesn't lose the interface */
6480ee5cbfSDavid du Colombier CmdGagePowerMgmt = 0x530F,
6580ee5cbfSDavid du Colombier DisengagePowerMgmt = 0x0000, /* CX */
6680ee5cbfSDavid du Colombier EngagePowerManagemenet = 0x0001,
6780ee5cbfSDavid du Colombier
6880ee5cbfSDavid du Colombier CmdGetCapabilities = 0x5310,
6980ee5cbfSDavid du Colombier CapStandby = 0x0001,
7080ee5cbfSDavid du Colombier CapSuspend = 0x0002,
7180ee5cbfSDavid du Colombier CapTimerResumeStandby = 0x0004,
7280ee5cbfSDavid du Colombier CapTimerResumeSuspend = 0x0008,
7380ee5cbfSDavid du Colombier CapRingResumeStandby = 0x0010,
7480ee5cbfSDavid du Colombier CapRingResumeSuspend = 0x0020,
7580ee5cbfSDavid du Colombier CapPcmciaResumeStandby = 0x0040,
7680ee5cbfSDavid du Colombier CapPcmciaResumeSuspend = 0x0080,
7780ee5cbfSDavid du Colombier CapSlowCpu = 0x0100,
7880ee5cbfSDavid du Colombier CmdResumeTimer = 0x5311,
7980ee5cbfSDavid du Colombier DisableResumeTimer = 0x00, /* CL */
8080ee5cbfSDavid du Colombier GetResumeTimer = 0x01,
8180ee5cbfSDavid du Colombier SetResumeTimer = 0x02,
8280ee5cbfSDavid du Colombier CmdResumeOnRing = 0x5312,
8380ee5cbfSDavid du Colombier DisableResumeOnRing = 0x0000, /* CX */
8480ee5cbfSDavid du Colombier EnableResumeOnRing = 0x0001,
8580ee5cbfSDavid du Colombier GetResumeOnRing = 0x0002,
8680ee5cbfSDavid du Colombier CmdTimerRequests = 0x5313,
8780ee5cbfSDavid du Colombier DisableTimerRequests = 0x0000, /* CX */
8880ee5cbfSDavid du Colombier EnableTimerRequests = 0x0001,
8980ee5cbfSDavid du Colombier GetTimerRequests = 0x0002,
9080ee5cbfSDavid du Colombier };
9180ee5cbfSDavid du Colombier
9280ee5cbfSDavid du Colombier static char* eventstr[] = {
9380ee5cbfSDavid du Colombier [NotifyStandbyRequest] "system standby request",
9480ee5cbfSDavid du Colombier [NotifySuspendRequest] "system suspend request",
9580ee5cbfSDavid du Colombier [NotifyNormalResume] "normal resume",
9680ee5cbfSDavid du Colombier [NotifyCriticalResume] "critical resume",
9780ee5cbfSDavid du Colombier [NotifyBatteryLow] "battery low",
9880ee5cbfSDavid du Colombier [NotifyPowerStatusChange] "power status change",
9980ee5cbfSDavid du Colombier [NotifyUpdateTime] "update time",
10080ee5cbfSDavid du Colombier [NotifyCriticalSuspend] "critical suspend",
10180ee5cbfSDavid du Colombier [NotifyUserStandbyRequest] "user standby request",
10280ee5cbfSDavid du Colombier [NotifyUserSuspendRequest] "user suspend request",
10380ee5cbfSDavid du Colombier [NotifyCapabilitiesChange] "capabilities change",
10480ee5cbfSDavid du Colombier };
10580ee5cbfSDavid du Colombier
10680ee5cbfSDavid du Colombier static char*
apmevent(int e)10780ee5cbfSDavid du Colombier apmevent(int e)
10880ee5cbfSDavid du Colombier {
10980ee5cbfSDavid du Colombier static char buf[32];
11080ee5cbfSDavid du Colombier
11180ee5cbfSDavid du Colombier if(0 <= e && e < nelem(eventstr) && eventstr[e])
11280ee5cbfSDavid du Colombier return eventstr[e];
11380ee5cbfSDavid du Colombier
11480ee5cbfSDavid du Colombier sprint(buf, "event 0x%ux", (uint)e);
11580ee5cbfSDavid du Colombier return buf;
11680ee5cbfSDavid du Colombier }
11780ee5cbfSDavid du Colombier
11880ee5cbfSDavid du Colombier static char *error[256] = {
11980ee5cbfSDavid du Colombier [0x01] "power mgmt disabled",
12080ee5cbfSDavid du Colombier [0x02] "real mode connection already established",
12180ee5cbfSDavid du Colombier [0x03] "interface not connected",
12280ee5cbfSDavid du Colombier [0x05] "16-bit protected mode connection already established",
12380ee5cbfSDavid du Colombier [0x06] "16-bit protected mode interface not supported",
12480ee5cbfSDavid du Colombier [0x07] "32-bit protected mode interface already established",
12580ee5cbfSDavid du Colombier [0x08] "32-bit protected mode interface not supported",
12680ee5cbfSDavid du Colombier [0x09] "unrecognized device id",
12780ee5cbfSDavid du Colombier [0x0A] "parameter value out of range",
12880ee5cbfSDavid du Colombier [0x0B] "interface not engaged",
12980ee5cbfSDavid du Colombier [0x0C] "function not supported",
13080ee5cbfSDavid du Colombier [0x0D] "resume timer disabled",
131d3c05884SDavid du Colombier [0x60] "unable to enter requested state",
13280ee5cbfSDavid du Colombier [0x80] "no power mgmt events pending",
13380ee5cbfSDavid du Colombier [0x86] "apm not present",
13480ee5cbfSDavid du Colombier };
13580ee5cbfSDavid du Colombier
13680ee5cbfSDavid du Colombier static char*
apmerror(int id)13780ee5cbfSDavid du Colombier apmerror(int id)
13880ee5cbfSDavid du Colombier {
13980ee5cbfSDavid du Colombier char *e;
14080ee5cbfSDavid du Colombier static char buf[64];
14180ee5cbfSDavid du Colombier
14280ee5cbfSDavid du Colombier if(e = error[id&0xFF])
14380ee5cbfSDavid du Colombier return e;
14480ee5cbfSDavid du Colombier
14580ee5cbfSDavid du Colombier sprint(buf, "unknown error %x", id);
14680ee5cbfSDavid du Colombier return buf;
14780ee5cbfSDavid du Colombier }
14880ee5cbfSDavid du Colombier
14980ee5cbfSDavid du Colombier QLock apmlock;
15080ee5cbfSDavid du Colombier int apmdebug;
15180ee5cbfSDavid du Colombier
15280ee5cbfSDavid du Colombier static int
_apmcall(int fd,Ureg * u)15380ee5cbfSDavid du Colombier _apmcall(int fd, Ureg *u)
15480ee5cbfSDavid du Colombier {
1559a747e4fSDavid du Colombier if(apmdebug) fprint(2, "call ax 0x%lux bx 0x%lux cx 0x%lux\n",
15680ee5cbfSDavid du Colombier u->ax&0xFFFF, u->bx&0xFFFF, u->cx&0xFFFF);
15780ee5cbfSDavid du Colombier
15880ee5cbfSDavid du Colombier seek(fd, 0, 0);
15980ee5cbfSDavid du Colombier if(write(fd, u, sizeof *u) != sizeof *u)
16080ee5cbfSDavid du Colombier return -1;
16180ee5cbfSDavid du Colombier
16280ee5cbfSDavid du Colombier seek(fd, 0, 0);
16380ee5cbfSDavid du Colombier if(read(fd, u, sizeof *u) != sizeof *u)
16480ee5cbfSDavid du Colombier return -1;
16580ee5cbfSDavid du Colombier
1669a747e4fSDavid du Colombier if(apmdebug) fprint(2, "flags 0x%lux ax 0x%lux bx 0x%lux cx 0x%lux\n",
16780ee5cbfSDavid du Colombier u->flags&0xFFFF, u->ax&0xFFFF, u->bx&0xFFFF, u->cx&0xFFFF);
16880ee5cbfSDavid du Colombier
16980ee5cbfSDavid du Colombier if(u->flags & 1) { /* carry flag */
17080ee5cbfSDavid du Colombier werrstr("%s", apmerror(u->ax>>8));
17180ee5cbfSDavid du Colombier return -1;
17280ee5cbfSDavid du Colombier }
17380ee5cbfSDavid du Colombier return 0;
17480ee5cbfSDavid du Colombier }
17580ee5cbfSDavid du Colombier
17680ee5cbfSDavid du Colombier static int
apmcall(int fd,Ureg * u)17780ee5cbfSDavid du Colombier apmcall(int fd, Ureg *u)
17880ee5cbfSDavid du Colombier {
17980ee5cbfSDavid du Colombier int r;
18080ee5cbfSDavid du Colombier
18180ee5cbfSDavid du Colombier qlock(&apmlock);
18280ee5cbfSDavid du Colombier r = _apmcall(fd, u);
18380ee5cbfSDavid du Colombier qunlock(&apmlock);
18480ee5cbfSDavid du Colombier return r;
18580ee5cbfSDavid du Colombier }
18680ee5cbfSDavid du Colombier
18780ee5cbfSDavid du Colombier typedef struct Apm Apm;
18880ee5cbfSDavid du Colombier typedef struct Battery Battery;
18980ee5cbfSDavid du Colombier
19080ee5cbfSDavid du Colombier struct Battery {
19180ee5cbfSDavid du Colombier int status;
19280ee5cbfSDavid du Colombier int percent;
19380ee5cbfSDavid du Colombier int time;
19480ee5cbfSDavid du Colombier };
19580ee5cbfSDavid du Colombier
19680ee5cbfSDavid du Colombier enum {
19780ee5cbfSDavid du Colombier Mbattery = 4,
19880ee5cbfSDavid du Colombier };
19980ee5cbfSDavid du Colombier struct Apm {
20080ee5cbfSDavid du Colombier int fd;
20180ee5cbfSDavid du Colombier
20280ee5cbfSDavid du Colombier int verhi;
20380ee5cbfSDavid du Colombier int verlo;
20480ee5cbfSDavid du Colombier
20580ee5cbfSDavid du Colombier int acstatus;
20680ee5cbfSDavid du Colombier int nbattery;
20780ee5cbfSDavid du Colombier
20880ee5cbfSDavid du Colombier int capabilities;
20980ee5cbfSDavid du Colombier
21080ee5cbfSDavid du Colombier Battery battery[Mbattery];
21180ee5cbfSDavid du Colombier };
21280ee5cbfSDavid du Colombier enum {
21380ee5cbfSDavid du Colombier AcUnknown = 0, /* Apm.acstatus */
21480ee5cbfSDavid du Colombier AcOffline,
21580ee5cbfSDavid du Colombier AcOnline,
21680ee5cbfSDavid du Colombier AcBackup,
21780ee5cbfSDavid du Colombier
21880ee5cbfSDavid du Colombier BatteryUnknown = 0, /* Battery.status */
21980ee5cbfSDavid du Colombier BatteryHigh,
22080ee5cbfSDavid du Colombier BatteryLow,
22180ee5cbfSDavid du Colombier BatteryCritical,
22280ee5cbfSDavid du Colombier BatteryCharging,
22380ee5cbfSDavid du Colombier };
22480ee5cbfSDavid du Colombier
22580ee5cbfSDavid du Colombier static char*
22680ee5cbfSDavid du Colombier acstatusstr[] = {
22780ee5cbfSDavid du Colombier [AcUnknown] "unknown",
22880ee5cbfSDavid du Colombier [AcOffline] "offline",
22980ee5cbfSDavid du Colombier [AcOnline] "online",
23080ee5cbfSDavid du Colombier [AcBackup] "backup",
23180ee5cbfSDavid du Colombier };
23280ee5cbfSDavid du Colombier
23380ee5cbfSDavid du Colombier static char*
23480ee5cbfSDavid du Colombier batterystatusstr[] = {
23580ee5cbfSDavid du Colombier [BatteryUnknown] "unknown",
23680ee5cbfSDavid du Colombier [BatteryHigh] "high",
23780ee5cbfSDavid du Colombier [BatteryLow] "low",
23880ee5cbfSDavid du Colombier [BatteryCritical] "critical",
23980ee5cbfSDavid du Colombier [BatteryCharging] "charging",
24080ee5cbfSDavid du Colombier };
24180ee5cbfSDavid du Colombier
24280ee5cbfSDavid du Colombier static char*
24380ee5cbfSDavid du Colombier powerstatestr[] = {
24480ee5cbfSDavid du Colombier [PowerOff] "off",
24580ee5cbfSDavid du Colombier [PowerSuspend] "suspend",
24680ee5cbfSDavid du Colombier [PowerStandby] "standby",
24780ee5cbfSDavid du Colombier [PowerEnabled] "on",
24880ee5cbfSDavid du Colombier };
24980ee5cbfSDavid du Colombier
25080ee5cbfSDavid du Colombier static char*
xstatus(char ** str,int nstr,int x)25180ee5cbfSDavid du Colombier xstatus(char **str, int nstr, int x)
25280ee5cbfSDavid du Colombier {
25380ee5cbfSDavid du Colombier if(0 <= x && x < nstr && str[x])
25480ee5cbfSDavid du Colombier return str[x];
25580ee5cbfSDavid du Colombier return "unknown";
25680ee5cbfSDavid du Colombier }
25780ee5cbfSDavid du Colombier
25880ee5cbfSDavid du Colombier static char*
batterystatus(int b)25980ee5cbfSDavid du Colombier batterystatus(int b)
26080ee5cbfSDavid du Colombier {
26180ee5cbfSDavid du Colombier return xstatus(batterystatusstr, nelem(batterystatusstr), b);
26280ee5cbfSDavid du Colombier }
26380ee5cbfSDavid du Colombier
26480ee5cbfSDavid du Colombier static char*
powerstate(int s)26580ee5cbfSDavid du Colombier powerstate(int s)
26680ee5cbfSDavid du Colombier {
26780ee5cbfSDavid du Colombier return xstatus(powerstatestr, nelem(powerstatestr), s);
26880ee5cbfSDavid du Colombier }
26980ee5cbfSDavid du Colombier
27080ee5cbfSDavid du Colombier static char*
acstatus(int a)27180ee5cbfSDavid du Colombier acstatus(int a)
27280ee5cbfSDavid du Colombier {
27380ee5cbfSDavid du Colombier return xstatus(acstatusstr, nelem(acstatusstr), a);
27480ee5cbfSDavid du Colombier }
27580ee5cbfSDavid du Colombier
27680ee5cbfSDavid du Colombier static int
apmversion(Apm * apm)27780ee5cbfSDavid du Colombier apmversion(Apm *apm)
27880ee5cbfSDavid du Colombier {
27980ee5cbfSDavid du Colombier Ureg u;
28080ee5cbfSDavid du Colombier
28180ee5cbfSDavid du Colombier u.ax = CmdDriverVersion;
28280ee5cbfSDavid du Colombier u.bx = 0x0000;
28380ee5cbfSDavid du Colombier u.cx = 0x0102;
28480ee5cbfSDavid du Colombier if(apmcall(apm->fd, &u) < 0)
28580ee5cbfSDavid du Colombier return -1;
28680ee5cbfSDavid du Colombier
28780ee5cbfSDavid du Colombier apm->verhi = u.cx>>8;
28880ee5cbfSDavid du Colombier apm->verlo = u.cx & 0xFF;
28980ee5cbfSDavid du Colombier
29080ee5cbfSDavid du Colombier return u.cx;
29180ee5cbfSDavid du Colombier }
29280ee5cbfSDavid du Colombier
29380ee5cbfSDavid du Colombier static int
apmcpuidle(Apm * apm)29480ee5cbfSDavid du Colombier apmcpuidle(Apm *apm)
29580ee5cbfSDavid du Colombier {
29680ee5cbfSDavid du Colombier Ureg u;
29780ee5cbfSDavid du Colombier
29880ee5cbfSDavid du Colombier u.ax = CmdCpuIdle;
29980ee5cbfSDavid du Colombier return apmcall(apm->fd, &u);
30080ee5cbfSDavid du Colombier }
30180ee5cbfSDavid du Colombier
30280ee5cbfSDavid du Colombier static int
apmcpubusy(Apm * apm)30380ee5cbfSDavid du Colombier apmcpubusy(Apm *apm)
30480ee5cbfSDavid du Colombier {
30580ee5cbfSDavid du Colombier Ureg u;
30680ee5cbfSDavid du Colombier
30780ee5cbfSDavid du Colombier u.ax = CmdCpuBusy;
30880ee5cbfSDavid du Colombier return apmcall(apm->fd, &u);
30980ee5cbfSDavid du Colombier }
31080ee5cbfSDavid du Colombier
31180ee5cbfSDavid du Colombier static int
apmsetpowerstate(Apm * apm,int dev,int state)31280ee5cbfSDavid du Colombier apmsetpowerstate(Apm *apm, int dev, int state)
31380ee5cbfSDavid du Colombier {
31480ee5cbfSDavid du Colombier Ureg u;
31580ee5cbfSDavid du Colombier
31680ee5cbfSDavid du Colombier u.ax = CmdSetPowerState;
31780ee5cbfSDavid du Colombier u.bx = dev;
31880ee5cbfSDavid du Colombier u.cx = state;
31980ee5cbfSDavid du Colombier return apmcall(apm->fd, &u);
32080ee5cbfSDavid du Colombier }
32180ee5cbfSDavid du Colombier
32280ee5cbfSDavid du Colombier static int
apmsetpowermgmt(Apm * apm,int dev,int state)32380ee5cbfSDavid du Colombier apmsetpowermgmt(Apm *apm, int dev, int state)
32480ee5cbfSDavid du Colombier {
32580ee5cbfSDavid du Colombier Ureg u;
32680ee5cbfSDavid du Colombier
32780ee5cbfSDavid du Colombier u.ax = CmdSetPowerMgmt;
32880ee5cbfSDavid du Colombier u.bx = dev;
32980ee5cbfSDavid du Colombier u.cx = state;
33080ee5cbfSDavid du Colombier return apmcall(apm->fd, &u);
33180ee5cbfSDavid du Colombier }
33280ee5cbfSDavid du Colombier
33380ee5cbfSDavid du Colombier static int
apmrestoredefaults(Apm * apm,int dev)33480ee5cbfSDavid du Colombier apmrestoredefaults(Apm *apm, int dev)
33580ee5cbfSDavid du Colombier {
33680ee5cbfSDavid du Colombier Ureg u;
33780ee5cbfSDavid du Colombier
33880ee5cbfSDavid du Colombier u.ax = CmdRestoreDefaults;
33980ee5cbfSDavid du Colombier u.bx = dev;
34080ee5cbfSDavid du Colombier return apmcall(apm->fd, &u);
34180ee5cbfSDavid du Colombier }
34280ee5cbfSDavid du Colombier
34380ee5cbfSDavid du Colombier static int
apmgetpowerstatus(Apm * apm,int dev)34480ee5cbfSDavid du Colombier apmgetpowerstatus(Apm *apm, int dev)
34580ee5cbfSDavid du Colombier {
34680ee5cbfSDavid du Colombier Battery *b;
34780ee5cbfSDavid du Colombier Ureg u;
34880ee5cbfSDavid du Colombier
34980ee5cbfSDavid du Colombier if(dev == DevAll)
35080ee5cbfSDavid du Colombier b = &apm->battery[0];
35180ee5cbfSDavid du Colombier else if((dev & DevMask) == DevBattery) {
35280ee5cbfSDavid du Colombier if(dev - DevBattery < nelem(apm->battery))
35380ee5cbfSDavid du Colombier b = &apm->battery[dev - DevBattery];
35480ee5cbfSDavid du Colombier else
35580ee5cbfSDavid du Colombier b = nil;
35680ee5cbfSDavid du Colombier } else {
35780ee5cbfSDavid du Colombier werrstr("bad device number");
35880ee5cbfSDavid du Colombier return -1;
35980ee5cbfSDavid du Colombier }
36080ee5cbfSDavid du Colombier
36180ee5cbfSDavid du Colombier u.ax = CmdGetPowerStatus;
36280ee5cbfSDavid du Colombier u.bx = dev;
36380ee5cbfSDavid du Colombier
36480ee5cbfSDavid du Colombier if(apmcall(apm->fd, &u) < 0)
36580ee5cbfSDavid du Colombier return -1;
36680ee5cbfSDavid du Colombier
36780ee5cbfSDavid du Colombier if((dev & DevMask) == DevBattery)
36880ee5cbfSDavid du Colombier apm->nbattery = u.si;
36980ee5cbfSDavid du Colombier
37080ee5cbfSDavid du Colombier switch(u.bx>>8) {
37180ee5cbfSDavid du Colombier case 0x00:
37280ee5cbfSDavid du Colombier apm->acstatus = AcOffline;
37380ee5cbfSDavid du Colombier break;
37480ee5cbfSDavid du Colombier case 0x01:
37580ee5cbfSDavid du Colombier apm->acstatus = AcOnline;
37680ee5cbfSDavid du Colombier break;
37780ee5cbfSDavid du Colombier case 0x02:
37880ee5cbfSDavid du Colombier apm->acstatus = AcBackup;
37980ee5cbfSDavid du Colombier break;
38080ee5cbfSDavid du Colombier default:
38180ee5cbfSDavid du Colombier apm->acstatus = AcUnknown;
38280ee5cbfSDavid du Colombier break;
38380ee5cbfSDavid du Colombier }
38480ee5cbfSDavid du Colombier
38580ee5cbfSDavid du Colombier if(b != nil) {
38680ee5cbfSDavid du Colombier switch(u.bx&0xFF) {
38780ee5cbfSDavid du Colombier case 0x00:
38880ee5cbfSDavid du Colombier b->status = BatteryHigh;
38980ee5cbfSDavid du Colombier break;
39080ee5cbfSDavid du Colombier case 0x01:
39180ee5cbfSDavid du Colombier b->status = BatteryLow;
39280ee5cbfSDavid du Colombier break;
39380ee5cbfSDavid du Colombier case 0x02:
39480ee5cbfSDavid du Colombier b->status = BatteryCritical;
39580ee5cbfSDavid du Colombier break;
39680ee5cbfSDavid du Colombier case 0x03:
39780ee5cbfSDavid du Colombier b->status = BatteryCharging;
39880ee5cbfSDavid du Colombier break;
39980ee5cbfSDavid du Colombier default:
40080ee5cbfSDavid du Colombier b->status = BatteryUnknown;
40180ee5cbfSDavid du Colombier break;
40280ee5cbfSDavid du Colombier }
40380ee5cbfSDavid du Colombier
40480ee5cbfSDavid du Colombier if((u.cx & 0xFF) == 0xFF)
40580ee5cbfSDavid du Colombier b->percent = -1;
40680ee5cbfSDavid du Colombier else
40780ee5cbfSDavid du Colombier b->percent = u.cx & 0xFF;
40880ee5cbfSDavid du Colombier
40980ee5cbfSDavid du Colombier if((u.dx&0xFFFF) == 0xFFFF)
41080ee5cbfSDavid du Colombier b->time = -1;
41180ee5cbfSDavid du Colombier else if(u.dx & 0x8000)
41280ee5cbfSDavid du Colombier b->time = 60*(u.dx & 0x7FFF);
41380ee5cbfSDavid du Colombier else
41480ee5cbfSDavid du Colombier b->time = u.dx & 0x7FFF;
41580ee5cbfSDavid du Colombier }
41680ee5cbfSDavid du Colombier
41780ee5cbfSDavid du Colombier return 0;
41880ee5cbfSDavid du Colombier }
41980ee5cbfSDavid du Colombier
42080ee5cbfSDavid du Colombier static int
apmgetevent(Apm * apm)42180ee5cbfSDavid du Colombier apmgetevent(Apm *apm)
42280ee5cbfSDavid du Colombier {
42380ee5cbfSDavid du Colombier Ureg u;
42480ee5cbfSDavid du Colombier
42580ee5cbfSDavid du Colombier u.ax = CmdGetPMEvent;
42680ee5cbfSDavid du Colombier u.bx = 0;
42780ee5cbfSDavid du Colombier u.cx = 0;
42880ee5cbfSDavid du Colombier
42980ee5cbfSDavid du Colombier //when u.bx == NotifyNormalResume or NotifyCriticalResume,
43080ee5cbfSDavid du Colombier //u.cx & 1 indicates PCMCIA socket was on while suspended,
43180ee5cbfSDavid du Colombier //u.cx & 1 == 0 indicates was off.
43280ee5cbfSDavid du Colombier
43380ee5cbfSDavid du Colombier if(apmcall(apm->fd, &u) < 0)
43480ee5cbfSDavid du Colombier return -1;
43580ee5cbfSDavid du Colombier
43680ee5cbfSDavid du Colombier return u.bx;
43780ee5cbfSDavid du Colombier }
43880ee5cbfSDavid du Colombier
43980ee5cbfSDavid du Colombier static int
apmgetpowerstate(Apm * apm,int dev)44080ee5cbfSDavid du Colombier apmgetpowerstate(Apm *apm, int dev)
44180ee5cbfSDavid du Colombier {
44280ee5cbfSDavid du Colombier Ureg u;
44380ee5cbfSDavid du Colombier
44480ee5cbfSDavid du Colombier u.ax = CmdGetPowerState;
44580ee5cbfSDavid du Colombier u.bx = dev;
44680ee5cbfSDavid du Colombier u.cx = 0;
44780ee5cbfSDavid du Colombier
44880ee5cbfSDavid du Colombier if(apmcall(apm->fd, &u) < 0)
44980ee5cbfSDavid du Colombier return -1;
45080ee5cbfSDavid du Colombier
45180ee5cbfSDavid du Colombier return u.cx;
45280ee5cbfSDavid du Colombier }
45380ee5cbfSDavid du Colombier
45480ee5cbfSDavid du Colombier static int
apmgetpowermgmt(Apm * apm,int dev)45580ee5cbfSDavid du Colombier apmgetpowermgmt(Apm *apm, int dev)
45680ee5cbfSDavid du Colombier {
45780ee5cbfSDavid du Colombier Ureg u;
45880ee5cbfSDavid du Colombier
45980ee5cbfSDavid du Colombier u.ax = CmdGetPowerMgmt;
46080ee5cbfSDavid du Colombier u.bx = dev;
46180ee5cbfSDavid du Colombier
46280ee5cbfSDavid du Colombier if(apmcall(apm->fd, &u) < 0)
46380ee5cbfSDavid du Colombier return -1;
46480ee5cbfSDavid du Colombier
46580ee5cbfSDavid du Colombier return u.cx;
46680ee5cbfSDavid du Colombier }
46780ee5cbfSDavid du Colombier
46880ee5cbfSDavid du Colombier static int
apmgetcapabilities(Apm * apm)46980ee5cbfSDavid du Colombier apmgetcapabilities(Apm *apm)
47080ee5cbfSDavid du Colombier {
47180ee5cbfSDavid du Colombier Ureg u;
47280ee5cbfSDavid du Colombier
47380ee5cbfSDavid du Colombier u.ax = CmdGetCapabilities;
47480ee5cbfSDavid du Colombier u.bx = DevBios;
47580ee5cbfSDavid du Colombier
47680ee5cbfSDavid du Colombier if(apmcall(apm->fd, &u) < 0)
47780ee5cbfSDavid du Colombier return -1;
47880ee5cbfSDavid du Colombier
47980ee5cbfSDavid du Colombier apm->nbattery = u.bx & 0xFF;
48080ee5cbfSDavid du Colombier apm->capabilities &= ~0xFFFF;
48180ee5cbfSDavid du Colombier apm->capabilities |= u.cx;
48280ee5cbfSDavid du Colombier return 0;
48380ee5cbfSDavid du Colombier }
48480ee5cbfSDavid du Colombier
48580ee5cbfSDavid du Colombier static int
apminstallationcheck(Apm * apm)48680ee5cbfSDavid du Colombier apminstallationcheck(Apm *apm)
48780ee5cbfSDavid du Colombier {
48880ee5cbfSDavid du Colombier Ureg u;
48980ee5cbfSDavid du Colombier
49080ee5cbfSDavid du Colombier u.ax = CmdInstallationCheck;
49180ee5cbfSDavid du Colombier u.bx = DevBios;
49280ee5cbfSDavid du Colombier if(apmcall(apm->fd, &u) < 0)
49380ee5cbfSDavid du Colombier return -1;
49480ee5cbfSDavid du Colombier
49580ee5cbfSDavid du Colombier if(u.cx & 0x0004)
49680ee5cbfSDavid du Colombier apm->capabilities |= CapSlowCpu;
49780ee5cbfSDavid du Colombier else
49880ee5cbfSDavid du Colombier apm->capabilities &= ~CapSlowCpu;
49980ee5cbfSDavid du Colombier return 0;
50080ee5cbfSDavid du Colombier }
50180ee5cbfSDavid du Colombier
50280ee5cbfSDavid du Colombier void
apmsetdisplaystate(Apm * apm,int s)50380ee5cbfSDavid du Colombier apmsetdisplaystate(Apm *apm, int s)
50480ee5cbfSDavid du Colombier {
50580ee5cbfSDavid du Colombier apmsetpowerstate(apm, DevDisplay, s);
50680ee5cbfSDavid du Colombier }
50780ee5cbfSDavid du Colombier
50880ee5cbfSDavid du Colombier void
apmblank(Apm * apm)50980ee5cbfSDavid du Colombier apmblank(Apm *apm)
51080ee5cbfSDavid du Colombier {
51180ee5cbfSDavid du Colombier apmsetdisplaystate(apm, PowerStandby);
51280ee5cbfSDavid du Colombier }
51380ee5cbfSDavid du Colombier
51480ee5cbfSDavid du Colombier void
apmunblank(Apm * apm)51580ee5cbfSDavid du Colombier apmunblank(Apm *apm)
51680ee5cbfSDavid du Colombier {
51780ee5cbfSDavid du Colombier apmsetdisplaystate(apm, PowerEnabled);
51880ee5cbfSDavid du Colombier }
51980ee5cbfSDavid du Colombier
52080ee5cbfSDavid du Colombier void
apmsuspend(Apm * apm)52180ee5cbfSDavid du Colombier apmsuspend(Apm *apm)
52280ee5cbfSDavid du Colombier {
52380ee5cbfSDavid du Colombier apmsetpowerstate(apm, DevAll, PowerSuspend);
52480ee5cbfSDavid du Colombier }
52580ee5cbfSDavid du Colombier
52680ee5cbfSDavid du Colombier Apm apm;
52780ee5cbfSDavid du Colombier
52880ee5cbfSDavid du Colombier void
powerprint(void)52980ee5cbfSDavid du Colombier powerprint(void)
53080ee5cbfSDavid du Colombier {
53180ee5cbfSDavid du Colombier print("%s", ctime(time(0)));
53280ee5cbfSDavid du Colombier if(apmgetpowerstatus(&apm, DevAll) == 0) {
53380ee5cbfSDavid du Colombier print("%d batteries\n", apm.nbattery);
53480ee5cbfSDavid du Colombier print("battery 0: status %s percent %d time %d:%.2d\n",
53580ee5cbfSDavid du Colombier batterystatus(apm.battery[0].status), apm.battery[0].percent,
53680ee5cbfSDavid du Colombier apm.battery[0].time/60, apm.battery[0].time%60);
53780ee5cbfSDavid du Colombier }
53880ee5cbfSDavid du Colombier }
53980ee5cbfSDavid du Colombier
54080ee5cbfSDavid du Colombier void*
erealloc(void * v,ulong n)54180ee5cbfSDavid du Colombier erealloc(void *v, ulong n)
54280ee5cbfSDavid du Colombier {
54380ee5cbfSDavid du Colombier v = realloc(v, n);
54480ee5cbfSDavid du Colombier if(v == nil)
54580ee5cbfSDavid du Colombier sysfatal("out of memory reallocating %lud", n);
54680ee5cbfSDavid du Colombier setmalloctag(v, getcallerpc(&v));
54780ee5cbfSDavid du Colombier return v;
54880ee5cbfSDavid du Colombier }
54980ee5cbfSDavid du Colombier
55080ee5cbfSDavid du Colombier void*
emalloc(ulong n)55180ee5cbfSDavid du Colombier emalloc(ulong n)
55280ee5cbfSDavid du Colombier {
55380ee5cbfSDavid du Colombier void *v;
55480ee5cbfSDavid du Colombier
55580ee5cbfSDavid du Colombier v = malloc(n);
55680ee5cbfSDavid du Colombier if(v == nil)
55780ee5cbfSDavid du Colombier sysfatal("out of memory allocating %lud", n);
55880ee5cbfSDavid du Colombier memset(v, 0, n);
55980ee5cbfSDavid du Colombier setmalloctag(v, getcallerpc(&n));
56080ee5cbfSDavid du Colombier return v;
56180ee5cbfSDavid du Colombier }
56280ee5cbfSDavid du Colombier
56380ee5cbfSDavid du Colombier char*
estrdup(char * s)56480ee5cbfSDavid du Colombier estrdup(char *s)
56580ee5cbfSDavid du Colombier {
56680ee5cbfSDavid du Colombier int l;
56780ee5cbfSDavid du Colombier char *t;
56880ee5cbfSDavid du Colombier
56980ee5cbfSDavid du Colombier if (s == nil)
57080ee5cbfSDavid du Colombier return nil;
57180ee5cbfSDavid du Colombier l = strlen(s)+1;
57280ee5cbfSDavid du Colombier t = emalloc(l);
57380ee5cbfSDavid du Colombier memcpy(t, s, l);
57480ee5cbfSDavid du Colombier setmalloctag(t, getcallerpc(&s));
57580ee5cbfSDavid du Colombier return t;
57680ee5cbfSDavid du Colombier }
57780ee5cbfSDavid du Colombier
57880ee5cbfSDavid du Colombier char*
estrdupn(char * s,int n)57980ee5cbfSDavid du Colombier estrdupn(char *s, int n)
58080ee5cbfSDavid du Colombier {
58180ee5cbfSDavid du Colombier int l;
58280ee5cbfSDavid du Colombier char *t;
58380ee5cbfSDavid du Colombier
58480ee5cbfSDavid du Colombier l = strlen(s);
58580ee5cbfSDavid du Colombier if(l > n)
58680ee5cbfSDavid du Colombier l = n;
58780ee5cbfSDavid du Colombier t = emalloc(l+1);
58880ee5cbfSDavid du Colombier memmove(t, s, l);
58980ee5cbfSDavid du Colombier t[l] = '\0';
59080ee5cbfSDavid du Colombier setmalloctag(t, getcallerpc(&s));
59180ee5cbfSDavid du Colombier return t;
59280ee5cbfSDavid du Colombier }
59380ee5cbfSDavid du Colombier
59480ee5cbfSDavid du Colombier enum {
5959a747e4fSDavid du Colombier Qroot = 0,
5969a747e4fSDavid du Colombier Qevent,
59780ee5cbfSDavid du Colombier Qbattery,
59880ee5cbfSDavid du Colombier Qctl,
59980ee5cbfSDavid du Colombier };
60080ee5cbfSDavid du Colombier
6019a747e4fSDavid du Colombier static void rootread(Req*);
6029a747e4fSDavid du Colombier static void eventread(Req*);
6039a747e4fSDavid du Colombier static void ctlread(Req*);
6049a747e4fSDavid du Colombier static void ctlwrite(Req*);
6059a747e4fSDavid du Colombier static void batteryread(Req*);
60680ee5cbfSDavid du Colombier
60780ee5cbfSDavid du Colombier typedef struct Dfile Dfile;
60880ee5cbfSDavid du Colombier struct Dfile {
6099a747e4fSDavid du Colombier Qid qid;
61080ee5cbfSDavid du Colombier char *name;
61180ee5cbfSDavid du Colombier ulong mode;
6129a747e4fSDavid du Colombier void (*read)(Req*);
6139a747e4fSDavid du Colombier void (*write)(Req*);
61480ee5cbfSDavid du Colombier };
61580ee5cbfSDavid du Colombier
61680ee5cbfSDavid du Colombier Dfile dfile[] = {
6179a747e4fSDavid du Colombier { {Qroot,0,QTDIR}, "/", DMDIR|0555, rootread, nil, },
6189a747e4fSDavid du Colombier { {Qevent}, "event", 0444, eventread, nil, },
6199a747e4fSDavid du Colombier { {Qbattery}, "battery", 0444, batteryread, nil, },
6209a747e4fSDavid du Colombier { {Qctl}, "ctl", 0666, ctlread, ctlwrite, },
62180ee5cbfSDavid du Colombier };
62280ee5cbfSDavid du Colombier
62380ee5cbfSDavid du Colombier static int
fillstat(uvlong path,Dir * d,int doalloc)624*5e91980fSDavid du Colombier fillstat(uvlong path, Dir *d, int doalloc)
62580ee5cbfSDavid du Colombier {
62680ee5cbfSDavid du Colombier int i;
62780ee5cbfSDavid du Colombier
62880ee5cbfSDavid du Colombier for(i=0; i<nelem(dfile); i++)
6299a747e4fSDavid du Colombier if(path==dfile[i].qid.path)
63080ee5cbfSDavid du Colombier break;
63180ee5cbfSDavid du Colombier if(i==nelem(dfile))
63280ee5cbfSDavid du Colombier return -1;
63380ee5cbfSDavid du Colombier
63480ee5cbfSDavid du Colombier memset(d, 0, sizeof *d);
6359a747e4fSDavid du Colombier d->uid = doalloc ? estrdup("apm") : "apm";
6369a747e4fSDavid du Colombier d->gid = doalloc ? estrdup("apm") : "apm";
63780ee5cbfSDavid du Colombier d->length = 0;
6389a747e4fSDavid du Colombier d->name = doalloc ? estrdup(dfile[i].name) : dfile[i].name;
63980ee5cbfSDavid du Colombier d->mode = dfile[i].mode;
64080ee5cbfSDavid du Colombier d->atime = d->mtime = time(0);
6419a747e4fSDavid du Colombier d->qid = dfile[i].qid;
64280ee5cbfSDavid du Colombier return 0;
64380ee5cbfSDavid du Colombier }
64480ee5cbfSDavid du Colombier
6459a747e4fSDavid du Colombier static char*
fswalk1(Fid * fid,char * name,Qid * qid)6469a747e4fSDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid)
64780ee5cbfSDavid du Colombier {
64880ee5cbfSDavid du Colombier int i;
64980ee5cbfSDavid du Colombier
65080ee5cbfSDavid du Colombier if(strcmp(name, "..")==0){
6519a747e4fSDavid du Colombier *qid = dfile[0].qid;
6529a747e4fSDavid du Colombier fid->qid = *qid;
6539a747e4fSDavid du Colombier return nil;
65480ee5cbfSDavid du Colombier }
65580ee5cbfSDavid du Colombier
65680ee5cbfSDavid du Colombier for(i=1; i<nelem(dfile); i++){ /* i=1: 0 is root dir */
65780ee5cbfSDavid du Colombier if(strcmp(dfile[i].name, name)==0){
6589a747e4fSDavid du Colombier *qid = dfile[i].qid;
6599a747e4fSDavid du Colombier fid->qid = *qid;
6609a747e4fSDavid du Colombier return nil;
66180ee5cbfSDavid du Colombier }
66280ee5cbfSDavid du Colombier }
6639a747e4fSDavid du Colombier return "file does not exist";
66480ee5cbfSDavid du Colombier }
66580ee5cbfSDavid du Colombier
66680ee5cbfSDavid du Colombier static void
fsopen(Req * r)6679a747e4fSDavid du Colombier fsopen(Req *r)
66880ee5cbfSDavid du Colombier {
6699a747e4fSDavid du Colombier switch((ulong)r->fid->qid.path){
67080ee5cbfSDavid du Colombier case Qroot:
6719a747e4fSDavid du Colombier r->fid->aux = (void*)0;
6729a747e4fSDavid du Colombier respond(r, nil);
6739a747e4fSDavid du Colombier return;
6749a747e4fSDavid du Colombier
67580ee5cbfSDavid du Colombier case Qevent:
67680ee5cbfSDavid du Colombier case Qbattery:
6779a747e4fSDavid du Colombier if(r->ifcall.mode == OREAD){
67880ee5cbfSDavid du Colombier respond(r, nil);
67980ee5cbfSDavid du Colombier return;
68080ee5cbfSDavid du Colombier }
68180ee5cbfSDavid du Colombier break;
68280ee5cbfSDavid du Colombier
68380ee5cbfSDavid du Colombier case Qctl:
6849a747e4fSDavid du Colombier if((r->ifcall.mode&~(OTRUNC|OREAD|OWRITE|ORDWR)) == 0){
68580ee5cbfSDavid du Colombier respond(r, nil);
68680ee5cbfSDavid du Colombier return;
68780ee5cbfSDavid du Colombier }
68880ee5cbfSDavid du Colombier break;
68980ee5cbfSDavid du Colombier }
69080ee5cbfSDavid du Colombier respond(r, "permission denied");
69180ee5cbfSDavid du Colombier return;
69280ee5cbfSDavid du Colombier }
69380ee5cbfSDavid du Colombier
69480ee5cbfSDavid du Colombier static void
fsstat(Req * r)6959a747e4fSDavid du Colombier fsstat(Req *r)
69680ee5cbfSDavid du Colombier {
6979a747e4fSDavid du Colombier fillstat(r->fid->qid.path, &r->d, 1);
69880ee5cbfSDavid du Colombier respond(r, nil);
69980ee5cbfSDavid du Colombier }
70080ee5cbfSDavid du Colombier
70180ee5cbfSDavid du Colombier static void
fsread(Req * r)7029a747e4fSDavid du Colombier fsread(Req *r)
70380ee5cbfSDavid du Colombier {
7049a747e4fSDavid du Colombier dfile[r->fid->qid.path].read(r);
70580ee5cbfSDavid du Colombier }
70680ee5cbfSDavid du Colombier
70780ee5cbfSDavid du Colombier static void
fswrite(Req * r)7089a747e4fSDavid du Colombier fswrite(Req *r)
70980ee5cbfSDavid du Colombier {
7109a747e4fSDavid du Colombier dfile[r->fid->qid.path].write(r);
71180ee5cbfSDavid du Colombier }
71280ee5cbfSDavid du Colombier
71380ee5cbfSDavid du Colombier static void
rootread(Req * r)7149a747e4fSDavid du Colombier rootread(Req *r)
71580ee5cbfSDavid du Colombier {
716*5e91980fSDavid du Colombier int n;
717*5e91980fSDavid du Colombier uvlong offset;
7189a747e4fSDavid du Colombier char *p, *ep;
71980ee5cbfSDavid du Colombier Dir d;
72080ee5cbfSDavid du Colombier
7219a747e4fSDavid du Colombier if(r->ifcall.offset == 0)
7229a747e4fSDavid du Colombier offset = 0;
7239a747e4fSDavid du Colombier else
724*5e91980fSDavid du Colombier offset = (uvlong)r->fid->aux;
7259a747e4fSDavid du Colombier
7269a747e4fSDavid du Colombier p = r->ofcall.data;
7279a747e4fSDavid du Colombier ep = r->ofcall.data+r->ifcall.count;
7289a747e4fSDavid du Colombier
7299a747e4fSDavid du Colombier if(offset == 0) /* skip root */
7309a747e4fSDavid du Colombier offset = 1;
7319a747e4fSDavid du Colombier for(; p+2 < ep; p+=n){
7329a747e4fSDavid du Colombier if(fillstat(offset, &d, 0) < 0)
73380ee5cbfSDavid du Colombier break;
7349a747e4fSDavid du Colombier n = convD2M(&d, (uchar*)p, ep-p);
7359a747e4fSDavid du Colombier if(n <= BIT16SZ)
7369a747e4fSDavid du Colombier break;
7379a747e4fSDavid du Colombier offset++;
73880ee5cbfSDavid du Colombier }
7399a747e4fSDavid du Colombier r->fid->aux = (void*)offset;
7409a747e4fSDavid du Colombier r->ofcall.count = p - r->ofcall.data;
74180ee5cbfSDavid du Colombier respond(r, nil);
74280ee5cbfSDavid du Colombier }
74380ee5cbfSDavid du Colombier
74480ee5cbfSDavid du Colombier static void
batteryread(Req * r)7459a747e4fSDavid du Colombier batteryread(Req *r)
74680ee5cbfSDavid du Colombier {
74780ee5cbfSDavid du Colombier char buf[Mbattery*80], *ep, *p;
74880ee5cbfSDavid du Colombier int i;
74980ee5cbfSDavid du Colombier
75080ee5cbfSDavid du Colombier apmgetpowerstatus(&apm, DevAll);
75180ee5cbfSDavid du Colombier
75280ee5cbfSDavid du Colombier p = buf;
75380ee5cbfSDavid du Colombier ep = buf+sizeof buf;
7549a747e4fSDavid du Colombier *p = '\0'; /* could be no batteries */
75580ee5cbfSDavid du Colombier for(i=0; i<apm.nbattery && i<Mbattery; i++)
75680ee5cbfSDavid du Colombier p += snprint(p, ep-p, "%s %d %d\n",
75780ee5cbfSDavid du Colombier batterystatus(apm.battery[i].status),
75880ee5cbfSDavid du Colombier apm.battery[i].percent, apm.battery[i].time);
75980ee5cbfSDavid du Colombier
7609a747e4fSDavid du Colombier readstr(r, buf);
76180ee5cbfSDavid du Colombier respond(r, nil);
76280ee5cbfSDavid du Colombier }
76380ee5cbfSDavid du Colombier
76480ee5cbfSDavid du Colombier int
iscmd(char * p,char * cmd)76580ee5cbfSDavid du Colombier iscmd(char *p, char *cmd)
76680ee5cbfSDavid du Colombier {
76780ee5cbfSDavid du Colombier int l;
76880ee5cbfSDavid du Colombier
76980ee5cbfSDavid du Colombier l = strlen(cmd);
77080ee5cbfSDavid du Colombier return strncmp(p, cmd, l)==0 && p[l]=='\0' || p[l]==' ' || p[l]=='\t';
77180ee5cbfSDavid du Colombier }
77280ee5cbfSDavid du Colombier
77380ee5cbfSDavid du Colombier char*
skip(char * p,char * cmd)77480ee5cbfSDavid du Colombier skip(char *p, char *cmd)
77580ee5cbfSDavid du Colombier {
77680ee5cbfSDavid du Colombier p += strlen(cmd);
77780ee5cbfSDavid du Colombier while(*p==' ' || *p=='\t')
77880ee5cbfSDavid du Colombier p++;
77980ee5cbfSDavid du Colombier return p;
78080ee5cbfSDavid du Colombier }
78180ee5cbfSDavid du Colombier
78280ee5cbfSDavid du Colombier static void
respondx(Req * r,int c)78380ee5cbfSDavid du Colombier respondx(Req *r, int c)
78480ee5cbfSDavid du Colombier {
7859a747e4fSDavid du Colombier char err[ERRMAX];
78680ee5cbfSDavid du Colombier
78780ee5cbfSDavid du Colombier if(c == 0)
78880ee5cbfSDavid du Colombier respond(r, nil);
78980ee5cbfSDavid du Colombier else{
7909a747e4fSDavid du Colombier rerrstr(err, sizeof err);
79180ee5cbfSDavid du Colombier respond(r, err);
79280ee5cbfSDavid du Colombier }
79380ee5cbfSDavid du Colombier }
79480ee5cbfSDavid du Colombier
79580ee5cbfSDavid du Colombier /*
79680ee5cbfSDavid du Colombier * we don't do suspend because it messes up the
79780ee5cbfSDavid du Colombier * cycle counter as well as the pcmcia ethernet cards.
79880ee5cbfSDavid du Colombier */
79980ee5cbfSDavid du Colombier static void
ctlwrite(Req * r)8009a747e4fSDavid du Colombier ctlwrite(Req *r)
80180ee5cbfSDavid du Colombier {
80280ee5cbfSDavid du Colombier char buf[80], *p, *q;
80380ee5cbfSDavid du Colombier int dev;
8049a747e4fSDavid du Colombier long count;
80580ee5cbfSDavid du Colombier
8069a747e4fSDavid du Colombier count = r->ifcall.count;
8079a747e4fSDavid du Colombier if(count > sizeof(buf)-1)
8089a747e4fSDavid du Colombier count = sizeof(buf)-1;
8099a747e4fSDavid du Colombier memmove(buf, r->ifcall.data, count);
8109a747e4fSDavid du Colombier buf[count] = '\0';
81180ee5cbfSDavid du Colombier
8129a747e4fSDavid du Colombier if(count && buf[count-1] == '\n'){
8139a747e4fSDavid du Colombier --count;
8149a747e4fSDavid du Colombier buf[count] = '\0';
8159a747e4fSDavid du Colombier }
81680ee5cbfSDavid du Colombier
81780ee5cbfSDavid du Colombier q = buf;
81880ee5cbfSDavid du Colombier p = strchr(q, ' ');
81980ee5cbfSDavid du Colombier if(p==nil)
82080ee5cbfSDavid du Colombier p = q+strlen(q);
82180ee5cbfSDavid du Colombier else
82280ee5cbfSDavid du Colombier *p++ = '\0';
82380ee5cbfSDavid du Colombier
82480ee5cbfSDavid du Colombier if(strcmp(q, "")==0 || strcmp(q, "system")==0)
82580ee5cbfSDavid du Colombier dev = DevAll;
82680ee5cbfSDavid du Colombier else if(strcmp(q, "display")==0)
82780ee5cbfSDavid du Colombier dev = DevDisplay;
82880ee5cbfSDavid du Colombier else if(strcmp(q, "storage")==0)
82980ee5cbfSDavid du Colombier dev = DevStorage;
83080ee5cbfSDavid du Colombier else if(strcmp(q, "lpt")==0)
83180ee5cbfSDavid du Colombier dev = DevLpt;
83280ee5cbfSDavid du Colombier else if(strcmp(q, "eia")==0)
83380ee5cbfSDavid du Colombier dev = DevEia;
83480ee5cbfSDavid du Colombier else if(strcmp(q, "network")==0)
83580ee5cbfSDavid du Colombier dev = DevNetwork;
83680ee5cbfSDavid du Colombier else if(strcmp(q, "pcmcia")==0)
83780ee5cbfSDavid du Colombier dev = DevPCMCIA;
83880ee5cbfSDavid du Colombier else{
83980ee5cbfSDavid du Colombier respond(r, "unknown device");
84080ee5cbfSDavid du Colombier return;
84180ee5cbfSDavid du Colombier }
84280ee5cbfSDavid du Colombier
84380ee5cbfSDavid du Colombier if(strcmp(p, "enable")==0)
84480ee5cbfSDavid du Colombier respondx(r, apmsetpowermgmt(&apm, dev, EnablePowerMgmt));
84580ee5cbfSDavid du Colombier else if(strcmp(p, "disable")==0)
84680ee5cbfSDavid du Colombier respondx(r, apmsetpowermgmt(&apm, dev, DisablePowerMgmt));
84780ee5cbfSDavid du Colombier else if(strcmp(p, "standby")==0)
84880ee5cbfSDavid du Colombier respondx(r, apmsetpowerstate(&apm, dev, PowerStandby));
84980ee5cbfSDavid du Colombier else if(strcmp(p, "on")==0)
85080ee5cbfSDavid du Colombier respondx(r, apmsetpowerstate(&apm, dev, PowerEnabled));
85180ee5cbfSDavid du Colombier /*
85280ee5cbfSDavid du Colombier else if(strcmp(p, "off")==0)
85380ee5cbfSDavid du Colombier respondx(r, apmsetpowerstate(&apm, dev, PowerOff));
8549a747e4fSDavid du Colombier */
85580ee5cbfSDavid du Colombier else if(strcmp(p, "suspend")==0)
85680ee5cbfSDavid du Colombier respondx(r, apmsetpowerstate(&apm, dev, PowerSuspend));
85780ee5cbfSDavid du Colombier else
85880ee5cbfSDavid du Colombier respond(r, "unknown verb");
85980ee5cbfSDavid du Colombier }
86080ee5cbfSDavid du Colombier
86180ee5cbfSDavid du Colombier static int
statusline(char * buf,int nbuf,char * name,int dev)86280ee5cbfSDavid du Colombier statusline(char *buf, int nbuf, char *name, int dev)
86380ee5cbfSDavid du Colombier {
86480ee5cbfSDavid du Colombier int s;
86580ee5cbfSDavid du Colombier char *state;
86680ee5cbfSDavid du Colombier
86780ee5cbfSDavid du Colombier state = "unknown";
86880ee5cbfSDavid du Colombier if((s = apmgetpowerstate(&apm, dev)) >= 0)
86980ee5cbfSDavid du Colombier state = powerstate(s);
87080ee5cbfSDavid du Colombier return snprint(buf, nbuf, "%s %s\n", name, state);
87180ee5cbfSDavid du Colombier }
87280ee5cbfSDavid du Colombier
87380ee5cbfSDavid du Colombier static void
ctlread(Req * r)8749a747e4fSDavid du Colombier ctlread(Req *r)
87580ee5cbfSDavid du Colombier {
87680ee5cbfSDavid du Colombier char buf[256+7*50], *ep, *p;
87780ee5cbfSDavid du Colombier
87880ee5cbfSDavid du Colombier p = buf;
87980ee5cbfSDavid du Colombier ep = buf+sizeof buf;
88080ee5cbfSDavid du Colombier
88180ee5cbfSDavid du Colombier p += snprint(p, ep-p, "ac %s\n", acstatus(apm.acstatus));
88280ee5cbfSDavid du Colombier p += snprint(p, ep-p, "capabilities");
88380ee5cbfSDavid du Colombier if(apm.capabilities & CapStandby)
88480ee5cbfSDavid du Colombier p += snprint(p, ep-p, " standby");
88580ee5cbfSDavid du Colombier if(apm.capabilities & CapSuspend)
88680ee5cbfSDavid du Colombier p += snprint(p, ep-p, " suspend");
88780ee5cbfSDavid du Colombier if(apm.capabilities & CapSlowCpu)
88880ee5cbfSDavid du Colombier p += snprint(p, ep-p, " slowcpu");
88980ee5cbfSDavid du Colombier p += snprint(p, ep-p, "\n");
89080ee5cbfSDavid du Colombier
89180ee5cbfSDavid du Colombier p += statusline(p, ep-p, "system", DevAll);
89280ee5cbfSDavid du Colombier p += statusline(p, ep-p, "display", DevDisplay);
89380ee5cbfSDavid du Colombier p += statusline(p, ep-p, "storage", DevStorage);
89480ee5cbfSDavid du Colombier p += statusline(p, ep-p, "lpt", DevLpt);
89580ee5cbfSDavid du Colombier p += statusline(p, ep-p, "eia", DevEia|All);
89680ee5cbfSDavid du Colombier p += statusline(p, ep-p, "network", DevNetwork|All);
89780ee5cbfSDavid du Colombier p += statusline(p, ep-p, "pcmcia", DevPCMCIA|All);
89880ee5cbfSDavid du Colombier USED(p);
89980ee5cbfSDavid du Colombier
9009a747e4fSDavid du Colombier readstr(r, buf);
90180ee5cbfSDavid du Colombier respond(r, nil);
90280ee5cbfSDavid du Colombier }
90380ee5cbfSDavid du Colombier
90480ee5cbfSDavid du Colombier enum {
90580ee5cbfSDavid du Colombier STACK = 16384,
90680ee5cbfSDavid du Colombier };
90780ee5cbfSDavid du Colombier
90880ee5cbfSDavid du Colombier Channel *creq;
90980ee5cbfSDavid du Colombier Channel *cflush;
91080ee5cbfSDavid du Colombier Channel *cevent;
91180ee5cbfSDavid du Colombier Req *rlist, **tailp;
91280ee5cbfSDavid du Colombier int rp, wp;
91380ee5cbfSDavid du Colombier int nopoll;
91480ee5cbfSDavid du Colombier char eventq[32][80];
91580ee5cbfSDavid du Colombier
91680ee5cbfSDavid du Colombier static void
flushthread(void *)91780ee5cbfSDavid du Colombier flushthread(void*)
91880ee5cbfSDavid du Colombier {
91980ee5cbfSDavid du Colombier Req *r, *or, **rq;
92080ee5cbfSDavid du Colombier
92180ee5cbfSDavid du Colombier threadsetname("flushthread");
92280ee5cbfSDavid du Colombier while(r = recvp(cflush)){
92380ee5cbfSDavid du Colombier or = r->oldreq;
92480ee5cbfSDavid du Colombier for(rq=&rlist; *rq; rq=&(*rq)->aux){
92580ee5cbfSDavid du Colombier if(*rq == or){
92680ee5cbfSDavid du Colombier *rq = or->aux;
92780ee5cbfSDavid du Colombier if(tailp==&or->aux)
92880ee5cbfSDavid du Colombier tailp = rq;
929d3c05884SDavid du Colombier respond(or, "interrupted");
93080ee5cbfSDavid du Colombier break;
93180ee5cbfSDavid du Colombier }
93280ee5cbfSDavid du Colombier }
93380ee5cbfSDavid du Colombier respond(r, nil);
93480ee5cbfSDavid du Colombier }
93580ee5cbfSDavid du Colombier }
93680ee5cbfSDavid du Colombier
93780ee5cbfSDavid du Colombier static void
answerany(void)93880ee5cbfSDavid du Colombier answerany(void)
93980ee5cbfSDavid du Colombier {
94080ee5cbfSDavid du Colombier char *buf;
94180ee5cbfSDavid du Colombier int l, m;
94280ee5cbfSDavid du Colombier Req *r;
94380ee5cbfSDavid du Colombier
94480ee5cbfSDavid du Colombier if(rlist==nil || rp==wp)
94580ee5cbfSDavid du Colombier return;
94680ee5cbfSDavid du Colombier
94780ee5cbfSDavid du Colombier while(rlist && rp != wp){
94880ee5cbfSDavid du Colombier r = rlist;
94980ee5cbfSDavid du Colombier rlist = r->aux;
95080ee5cbfSDavid du Colombier if(rlist==nil)
95180ee5cbfSDavid du Colombier tailp = &rlist;
95280ee5cbfSDavid du Colombier
95380ee5cbfSDavid du Colombier l = 0;
95480ee5cbfSDavid du Colombier buf = r->ofcall.data;
955da51d93aSDavid du Colombier m = r->ifcall.count;
95680ee5cbfSDavid du Colombier while(rp != wp){
95780ee5cbfSDavid du Colombier if(l+strlen(eventq[rp]) <= m){
95880ee5cbfSDavid du Colombier strcpy(buf+l, eventq[rp]);
95980ee5cbfSDavid du Colombier l += strlen(buf+l);
96080ee5cbfSDavid du Colombier }else if(l==0){
96180ee5cbfSDavid du Colombier strncpy(buf, eventq[rp], m-1);
96280ee5cbfSDavid du Colombier buf[m-1] = '\0';
96380ee5cbfSDavid du Colombier l += m;
96480ee5cbfSDavid du Colombier }else
96580ee5cbfSDavid du Colombier break;
96680ee5cbfSDavid du Colombier rp++;
96780ee5cbfSDavid du Colombier if(rp == nelem(eventq))
96880ee5cbfSDavid du Colombier rp = 0;
96980ee5cbfSDavid du Colombier }
97080ee5cbfSDavid du Colombier r->ofcall.count = l;
97180ee5cbfSDavid du Colombier respond(r, nil);
97280ee5cbfSDavid du Colombier }
97380ee5cbfSDavid du Colombier }
97480ee5cbfSDavid du Colombier
97580ee5cbfSDavid du Colombier static void
eventwatch(void *)97680ee5cbfSDavid du Colombier eventwatch(void*)
97780ee5cbfSDavid du Colombier {
97880ee5cbfSDavid du Colombier int e, s;
97980ee5cbfSDavid du Colombier
98080ee5cbfSDavid du Colombier threadsetname("eventwatch");
98180ee5cbfSDavid du Colombier for(;;){
98280ee5cbfSDavid du Colombier s = 0;
98380ee5cbfSDavid du Colombier while((e = apmgetevent(&apm)) >= 0){
98480ee5cbfSDavid du Colombier sendul(cevent, e);
98580ee5cbfSDavid du Colombier s = 1;
98680ee5cbfSDavid du Colombier }
98780ee5cbfSDavid du Colombier if(s)
98880ee5cbfSDavid du Colombier sendul(cevent, -1);
98980ee5cbfSDavid du Colombier if(sleep(750) < 0)
99080ee5cbfSDavid du Colombier break;
99180ee5cbfSDavid du Colombier }
99280ee5cbfSDavid du Colombier }
99380ee5cbfSDavid du Colombier
99480ee5cbfSDavid du Colombier static void
eventthread(void *)99580ee5cbfSDavid du Colombier eventthread(void*)
99680ee5cbfSDavid du Colombier {
99780ee5cbfSDavid du Colombier int e;
99880ee5cbfSDavid du Colombier
99980ee5cbfSDavid du Colombier threadsetname("eventthread");
100080ee5cbfSDavid du Colombier for(;;){
100180ee5cbfSDavid du Colombier while((e = recvul(cevent)) >= 0){
100280ee5cbfSDavid du Colombier snprint(eventq[wp], sizeof(eventq[wp])-1, "%s", apmevent(e));
100380ee5cbfSDavid du Colombier strcat(eventq[wp], "\n");
100480ee5cbfSDavid du Colombier wp++;
100580ee5cbfSDavid du Colombier if(wp==nelem(eventq))
100680ee5cbfSDavid du Colombier wp = 0;
100780ee5cbfSDavid du Colombier if(wp+1==rp || (wp+1==nelem(eventq) && rp==0))
100880ee5cbfSDavid du Colombier break;
100980ee5cbfSDavid du Colombier }
101080ee5cbfSDavid du Colombier answerany();
101180ee5cbfSDavid du Colombier }
101280ee5cbfSDavid du Colombier }
101380ee5cbfSDavid du Colombier
101480ee5cbfSDavid du Colombier static void
eventproc(void *)101580ee5cbfSDavid du Colombier eventproc(void*)
101680ee5cbfSDavid du Colombier {
101780ee5cbfSDavid du Colombier Req *r;
101880ee5cbfSDavid du Colombier
101980ee5cbfSDavid du Colombier threadsetname("eventproc");
102080ee5cbfSDavid du Colombier
102180ee5cbfSDavid du Colombier creq = chancreate(sizeof(Req*), 0);
102280ee5cbfSDavid du Colombier cevent = chancreate(sizeof(ulong), 0);
102380ee5cbfSDavid du Colombier cflush = chancreate(sizeof(Req*), 0);
102480ee5cbfSDavid du Colombier
102580ee5cbfSDavid du Colombier tailp = &rlist;
102680ee5cbfSDavid du Colombier if(!nopoll)
102780ee5cbfSDavid du Colombier proccreate(eventwatch, nil, STACK);
102880ee5cbfSDavid du Colombier threadcreate(eventthread, nil, STACK);
102980ee5cbfSDavid du Colombier threadcreate(flushthread, nil, STACK);
103080ee5cbfSDavid du Colombier
103180ee5cbfSDavid du Colombier while(r = recvp(creq)){
103280ee5cbfSDavid du Colombier *tailp = r;
103380ee5cbfSDavid du Colombier r->aux = nil;
103480ee5cbfSDavid du Colombier tailp = &r->aux;
103580ee5cbfSDavid du Colombier answerany();
103680ee5cbfSDavid du Colombier }
103780ee5cbfSDavid du Colombier }
103880ee5cbfSDavid du Colombier
103980ee5cbfSDavid du Colombier static void
fsflush(Req * r)10409a747e4fSDavid du Colombier fsflush(Req *r)
104180ee5cbfSDavid du Colombier {
104280ee5cbfSDavid du Colombier sendp(cflush, r);
104380ee5cbfSDavid du Colombier }
104480ee5cbfSDavid du Colombier
104580ee5cbfSDavid du Colombier static void
eventread(Req * r)10469a747e4fSDavid du Colombier eventread(Req *r)
104780ee5cbfSDavid du Colombier {
104880ee5cbfSDavid du Colombier sendp(creq, r);
104980ee5cbfSDavid du Colombier }
105080ee5cbfSDavid du Colombier
105180ee5cbfSDavid du Colombier static void
fsattach(Req * r)10529a747e4fSDavid du Colombier fsattach(Req *r)
105380ee5cbfSDavid du Colombier {
10549a747e4fSDavid du Colombier char *spec;
105580ee5cbfSDavid du Colombier static int first = 1;
105680ee5cbfSDavid du Colombier
10579a747e4fSDavid du Colombier spec = r->ifcall.aname;
10589a747e4fSDavid du Colombier
105980ee5cbfSDavid du Colombier if(first){
106080ee5cbfSDavid du Colombier first = 0;
106180ee5cbfSDavid du Colombier proccreate(eventproc, nil, STACK);
106280ee5cbfSDavid du Colombier }
106380ee5cbfSDavid du Colombier
106480ee5cbfSDavid du Colombier if(spec && spec[0]){
106580ee5cbfSDavid du Colombier respond(r, "invalid attach specifier");
106680ee5cbfSDavid du Colombier return;
106780ee5cbfSDavid du Colombier }
10689a747e4fSDavid du Colombier r->fid->qid = dfile[0].qid;
10699a747e4fSDavid du Colombier r->ofcall.qid = dfile[0].qid;
107080ee5cbfSDavid du Colombier respond(r, nil);
107180ee5cbfSDavid du Colombier }
107280ee5cbfSDavid du Colombier
10739a747e4fSDavid du Colombier Srv fs = {
107480ee5cbfSDavid du Colombier .attach= fsattach,
10759a747e4fSDavid du Colombier .walk1= fswalk1,
107680ee5cbfSDavid du Colombier .open= fsopen,
107780ee5cbfSDavid du Colombier .read= fsread,
107880ee5cbfSDavid du Colombier .write= fswrite,
107980ee5cbfSDavid du Colombier .stat= fsstat,
108080ee5cbfSDavid du Colombier .flush= fsflush,
108180ee5cbfSDavid du Colombier };
108280ee5cbfSDavid du Colombier
108380ee5cbfSDavid du Colombier void
usage(void)10849a747e4fSDavid du Colombier usage(void)
10859a747e4fSDavid du Colombier {
10869a747e4fSDavid du Colombier fprint(2, "usage: aux/apm [-ADPi] [-d /dev/apm] [-m /mnt/apm] [-s service]\n");
10879a747e4fSDavid du Colombier exits("usage");
10889a747e4fSDavid du Colombier }
10899a747e4fSDavid du Colombier
10909a747e4fSDavid du Colombier void
threadmain(int argc,char ** argv)109180ee5cbfSDavid du Colombier threadmain(int argc, char **argv)
109280ee5cbfSDavid du Colombier {
109380ee5cbfSDavid du Colombier char *dev, *mtpt, *srv;
109480ee5cbfSDavid du Colombier
10959a747e4fSDavid du Colombier dev = nil;
109680ee5cbfSDavid du Colombier mtpt = "/mnt/apm";
109780ee5cbfSDavid du Colombier srv = nil;
109880ee5cbfSDavid du Colombier ARGBEGIN{
109980ee5cbfSDavid du Colombier case 'A':
110080ee5cbfSDavid du Colombier apmdebug = 1;
110180ee5cbfSDavid du Colombier break;
110280ee5cbfSDavid du Colombier case 'D':
11039a747e4fSDavid du Colombier chatty9p = 1;
110480ee5cbfSDavid du Colombier break;
110580ee5cbfSDavid du Colombier case 'P':
110680ee5cbfSDavid du Colombier nopoll = 1;
110780ee5cbfSDavid du Colombier break;
110880ee5cbfSDavid du Colombier case 'd':
110980ee5cbfSDavid du Colombier dev = EARGF(usage());
111080ee5cbfSDavid du Colombier break;
11119a747e4fSDavid du Colombier case 'i':
11129a747e4fSDavid du Colombier fs.nopipe++;
11139a747e4fSDavid du Colombier fs.infd = 0;
11149a747e4fSDavid du Colombier fs.outfd = 1;
11159a747e4fSDavid du Colombier mtpt = nil;
11169a747e4fSDavid du Colombier break;
111780ee5cbfSDavid du Colombier case 'm':
111880ee5cbfSDavid du Colombier mtpt = EARGF(usage());
111980ee5cbfSDavid du Colombier break;
112080ee5cbfSDavid du Colombier case 's':
112180ee5cbfSDavid du Colombier srv = EARGF(usage());
112280ee5cbfSDavid du Colombier break;
112380ee5cbfSDavid du Colombier }ARGEND
112480ee5cbfSDavid du Colombier
11259a747e4fSDavid du Colombier if(dev == nil){
11269a747e4fSDavid du Colombier if((apm.fd = open("/dev/apm", ORDWR)) < 0
11279a747e4fSDavid du Colombier && (apm.fd = open("#P/apm", ORDWR)) < 0){
11289a747e4fSDavid du Colombier fprint(2, "open %s: %r\n", dev);
11299a747e4fSDavid du Colombier threadexitsall("open");
11309a747e4fSDavid du Colombier }
11319a747e4fSDavid du Colombier } else if((apm.fd = open(dev, ORDWR)) < 0){
11329a747e4fSDavid du Colombier fprint(2, "open %s: %r\n", dev);
113380ee5cbfSDavid du Colombier threadexitsall("open");
113480ee5cbfSDavid du Colombier }
113580ee5cbfSDavid du Colombier
113680ee5cbfSDavid du Colombier if(apmversion(&apm) < 0){
11379a747e4fSDavid du Colombier fprint(2, "cannot get apm version: %r\n");
113880ee5cbfSDavid du Colombier threadexitsall("apmversion");
113980ee5cbfSDavid du Colombier }
114080ee5cbfSDavid du Colombier
114180ee5cbfSDavid du Colombier if(apm.verhi < 1 || (apm.verhi==1 && apm.verlo < 2)){
11429a747e4fSDavid du Colombier fprint(2, "apm version %d.%d not supported\n", apm.verhi, apm.verlo);
114380ee5cbfSDavid du Colombier threadexitsall("apmversion");
114480ee5cbfSDavid du Colombier }
114580ee5cbfSDavid du Colombier
114680ee5cbfSDavid du Colombier if(apmgetcapabilities(&apm) < 0)
11479a747e4fSDavid du Colombier fprint(2, "warning: cannot read apm capabilities: %r\n");
114880ee5cbfSDavid du Colombier
114980ee5cbfSDavid du Colombier apminstallationcheck(&apm);
115080ee5cbfSDavid du Colombier apmcpuidle(&apm);
115180ee5cbfSDavid du Colombier
11529a747e4fSDavid du Colombier rfork(RFNOTEG);
11539a747e4fSDavid du Colombier threadpostmountsrv(&fs, srv, mtpt, MREPL);
115480ee5cbfSDavid du Colombier }
1155