~kris/9p

9hist

ref: ace215e79cb72065fe219e86d3583bbd34da94be 9hist/pc/pmu.c -rw-r--r-- 2.1 KiB
ace215e7 — David du Colombier Plan 9 from Bell Labs 1992-09-02 34 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

/*
 *  intel power management unit (i80c51)
 */
enum {
	/*
	 *  power management unit ports
	 */
	Pmudata=	0x198,

	Pmucsr=		0x199,
	 Busy=		0x1,

	/*
	 *  configuration port
	 */
	Pconfig=	0x3F3,
};

/*
 *  return when pmu ready
 */
static int
pmuready(void)
{
	int tries;

	for(tries = 0; (inb(Pmucsr) & Busy); tries++)
		if(tries > 1000)
			return -1;
	return 0;
}

/*
 *  return when pmu busy
 */
static int
pmubusy(void)
{
	int tries;

	for(tries = 0; !(inb(Pmucsr) & Busy); tries++)
		if(tries > 1000)
			return -1;
	return 0;
}

/*
 *  set a bit in the PMU
 */
Lock pmulock;
int
pmuwrbit(int index, int bit, int pos)
{
	lock(&pmulock);
	outb(Pmucsr, 0x02);		/* next is command request */
	if(pmuready() < 0){
		unlock(&pmulock);
		return -1;
	}
	outb(Pmudata, (2<<4) | index);	/* send write bit command */
	outb(Pmucsr, 0x01);		/* send available */
	if(pmubusy() < 0){
		unlock(&pmulock);
		return -1;
	}
	outb(Pmucsr, 0x01);		/* next is data */
	if(pmuready() < 0){
		unlock(&pmulock);
		return -1;
	}
	outb(Pmudata, (bit<<3) | pos);	/* send bit to write */
	outb(Pmucsr, 0x01);		/* send available */
	if(pmubusy() < 0){
		unlock(&pmulock);
		return -1;
	}
	unlock(&pmulock);
	return 0;
}

/*
 *  power to serial port
 *	onoff == 1 means on
 *	onoff == 0 means off
 */
int
pmuserial(int onoff)
{
	return pmuwrbit(1, 1^onoff, 6);
}

/*
 *  power to modem
 *	onoff == 1 means on
 *	onoff == 0 means off
 */
int
pmumodem(int onoff)
{
	if(pmuwrbit(1, 1^onoff, 0)<0)		/* modem speaker */
		return -1;
	return pmuwrbit(1, onoff, 5);		/* modem power */
}

/*
 *  set cpu speed
 * 	0 == low speed
 *	1 == high speed
 */
int
pmucpuspeed(int speed)
{
	return pmuwrbit(0, speed, 0);
}

/*
 *  f == frequency in Hz
 *  d == duration in ms
 */
void
pmubuzz(int f, int d)
{
	static QLock bl;
	static Rendez br;

	USED(f);
	qlock(&bl);
	pmuwrbit(0, 0, 6);
	tsleep(&br, return0, 0, d);
	pmuwrbit(0, 1, 6);
	qunlock(&bl);
}

/*
 *  1 == owl eye
 *  2 == mail icon
 */
void
pmulights(int val)
{
	pmuwrbit(0, (val&1), 4);		/* owl */
	pmuwrbit(0, ((val>>1)&1), 1);		/* mail */
}