1163 lines · 20.2 KB · C
RawDownload
/*  * 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.