~kris/9p

9hist

ref: b73e35c1decbee5d23ff469df61d6a190cd4545f 9hist/pc/archnsx20.c -rw-r--r-- 2.6 KiB
b73e35c1 — David du Colombier Plan 9 from Bell Labs 1995-01-15 31 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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

/*
 *  safari nsx20 specific routines
 */

/*
 *  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
 */
static Lock pmulock;
static 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
 */
static int
nsx20serialpower(int onoff)
{
	return pmuwrbit(1, 1^onoff, 6);
}

/*
 *  power to modem
 *	onoff == 1 means on
 *	onoff == 0 means off
 */
static int
nsx20modempower(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
 */
static int
nsx20cpuspeed(int speed)
{
	return pmuwrbit(0, speed, 0);
}

/*
 *  f == frequency in Hz
 *  d == duration in ms
 */
static void
nsx20buzz(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
 */
static void
nsx20lights(int val)
{
	pmuwrbit(0, (val&1), 4);		/* owl */
	pmuwrbit(0, ((val>>1)&1), 1);		/* mail */
}

/*
 *  headland system controller (ht21)
 */
enum
{
	/*
	 *  system control port
	 */
	Head=		0x92,		/* control port */
	 Reset=		(1<<0),		/* reset the 386 */
	 A20ena=	(1<<1),		/* enable address line 20 */
};

/*
 *  reset machine
 */
static void
headreset(void)
{
	outb(Head, Reset);
}

PCArch nsx20 =
{
	"AT&TNSX",
	headreset,
	nsx20cpuspeed,
	nsx20buzz,
	nsx20lights,
	nsx20serialpower,
	nsx20modempower,
	0,
};