Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
 
5
#include "pci.h"
6
#include "vga.h"
7
 
8
enum
9
{
10
	X=	0x3D6,	/* index reg */
11
	D=	0x3D7,	/* data reg */
12
};
13
 
14
static int misc[] = {	0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0xE, 0x28, 0x29,
15
			0x70, 0x72, 0x73, 0x7D, 0x7F, -1};
16
static int map[] = {	0x7,  0x8,  0xB,  0xC,  0x10, 0x11, -1};
17
static int flags[] = {	0xF,  0x2B, 0x44, 0x45, -1};
18
static int compat[] = {	0x14, 0x15, 0x1F, 0x7E, -1};
19
static int clock[] = {	0x30, 0x31, 0x32, 0x33, -1};
20
static int mm[] = {	0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, -1};
21
static int alt[] = {	0x0D, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
22
			0x24, 0x25, 0x26, 0x64, 0x65, 0x66, 0x67, -1};
23
static int flat[] = {	0x2C, 0x2D, 0x2E, 0x2F, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
24
			0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E,
25
			0x5F, 0x60, 0x61, 0x62, 0x63, 0x68, 0x6C, 0x6E, 0x6F, -1};
26
 
27
typedef struct Group Group;
28
struct Group {
29
	char *name;
30
	int *x;
31
};
32
static Group group[] = 
33
{
34
	{ "misc", misc, },
35
	{ "map", map, },
36
	{ "compatability", compat, },
37
	{ "clock", clock, },
38
	{ "multimedia", mm, },
39
	{ "alternate", alt, },
40
	{ "flat-panel", flat, },
41
	{ 0 },
42
};
43
 
44
static uchar greg[256];
45
 
46
static uchar
47
ctxi(uchar index)
48
{
49
	outportb(X, index);
50
	return inportb(D);
51
}
52
 
53
static void
54
ctxo(uchar index, uchar data)
55
{
56
	outportb(X, index);
57
	outportb(D, data);
58
}
59
 
60
/*
61
 * ct65540.
62
 */
63
static void
64
snarf(Vga*, Ctlr* ctlr)
65
{
66
	Group *g;
67
	int *xp;
68
 
69
	ctlr->flag |= Fsnarf;
70
 
71
	for(g = group; g->name; g++)
72
		for(xp = g->x; *xp >= 0; xp++)
73
			greg[*xp] = ctxi(*xp);
74
}
75
 
76
static void
77
options(Vga*, Ctlr* ctlr)
78
{
79
	ctlr->flag |= Hlinear|Foptions;
80
}
81
 
82
/*
83
 *  brute force and ignorance
84
 */
85
static int
86
setclock(Vga* vga)
87
{
88
	ulong fvco, t;
89
	ulong m, n;
90
	ulong bestm, bestn, diff, bestdiff, lastdiff;
91
	ulong p;
92
 
93
	if(vga->mode->frequency > 220000000)
94
		return -1;
95
 
96
	vga->misc &= ~(3<<2);
97
	vga->feature &= ~3;
98
	greg[0x33] &= ~0x20;		/* set VCLK not MCLK */
99
	greg[0x33] &= ~0x80;		/* clk0 & clk1 are 25.175 & 28.322 MHz */
100
 
101
	vga->misc |= (2<<2);
102
	vga->feature |= 2;
103
 
104
	fvco = vga->mode->frequency;
105
	if(fvco == 0)
106
		return -1;
107
	p = 0;
108
	while(fvco < 100000000){
109
		fvco *= 2;
110
		p++;
111
	}
112
 
113
	m = (1<<31)/(4*RefFreq);
114
	if(m > 127)
115
		m = 127;
116
	bestdiff = 1<<31;
117
	bestm = 3;
118
	bestn = 3;
119
	for(; m > 2; m--){
120
		lastdiff = 1<<31;
121
		for(n = 3; n < 128; n++){
122
			t = (RefFreq*4*m)/n;
123
			diff = abs(fvco-t);
124
			if(diff < bestdiff){
125
				bestdiff = diff;
126
				bestm = m;
127
				bestn = n;
128
			} else {
129
				if(diff > lastdiff)
130
					break;
131
			}
132
			lastdiff = diff;
133
		}
134
	}
135
 
136
	greg[0x31] = bestm - 2;
137
	greg[0x32] = bestn - 2;
138
	greg[0x30] = (p<<1) | 1;
139
	return 0;
140
}
141
 
142
static void
143
init(Vga* vga, Ctlr* ctlr)
144
{
145
	int x;
146
 
147
	greg[0x15] = 0;			/* allow writes to all registers */
148
 
149
	if(vga->mode->z > 8)
150
		error("depth %d not supported\n", vga->mode->z);
151
 
152
	if(vga->mode->z == 8){
153
		if(vga->linear && (ctlr->flag & Hlinear))
154
			ctlr->flag |= Ulinear;
155
		vga->vmz = 1024*1024;
156
		vga->vmb = 1024*1024;
157
 
158
		/* linear mapping - extension regs*/
159
		greg[0x04] = (1<<2);	/* enable CRTC bits 16 & 17, 32 bit mode */
160
		greg[0x0b] = 0x15;	/* linear addressing, > 256k, sequential addr */
161
		greg[0x28] = 0x90;	/* non-interlaced, 256 colors */
162
 
163
		/* normal regs */
164
		vga->sequencer[0x04] = 0x0A;	/* sequential memory access */
165
		vga->graphics[0x05] = 0x00;	/* sequential access, shift out 8 bits at */
166
						/* a time */
167
		vga->attribute[0x10] &= ~(1<<6); /* 1 dot clock per pixel */
168
		vga->crt[0x14] = 0x00;
169
		vga->crt[0x17] = 0xe3;		/* always byte mode */
170
	} else {
171
		/* mapped to 0xa0000 - extension regs*/
172
		greg[0x04] = (1<<2);	/* enable CRTC bits 16 & 17, 32 bit mode */
173
		greg[0x0b] = 0x01;	/* 0xA0000 - 0xAFFFF, planar addressing */
174
		greg[0x28] = 0x80;	/* non-interlaced, 16 colors */
175
	}
176
 
177
	/* the extension registers have even more overflow bits */
178
	x = 0;
179
	if(vga->mode->vt & (1<<10))
180
		x |= (1<<0);
181
	if(vga->mode->vrs & (1<<10))
182
		x |= (1<<2);
183
	greg[0x16] = x;
184
	x = 0;
185
	if(vga->mode->ht & (1<<(8+3)))
186
		x |= (1<<0);
187
	if(vga->mode->shb & (1<<(8+3)))
188
		x |= (1<<4);
189
	if(vga->mode->ehb & (1<<(6+3)))
190
		x |= (1<<5);
191
	greg[0x17] = x;
192
 
193
	if(vga->mode->y > 480)
194
		vga->misc &= 0x3F;
195
 
196
	setclock(vga);
197
 
198
	ctlr->flag |= Finit;
199
}
200
 
201
static void
202
load(Vga* vga, Ctlr* ctlr)
203
{
204
	Group *g;
205
	int *xp;
206
 
207
	/* must be first */
208
	ctxo(0x15, greg[0x15]);	/* write protect */
209
	ctxo(0x33, greg[0x33]);	/* select clock */
210
 
211
	if(ctlr->flag & Ulinear){
212
		greg[0x8] = vga->vmb>>20;
213
		ctxo(0x08, greg[0x08]);
214
	}
215
 
216
	/* only write what changed */
217
	for(g = group; g->name; g++)
218
		for(xp = g->x; *xp >= 0; xp++)
219
			ctxo(*xp, greg[*xp]);
220
 
221
	ctlr->flag |= Fload;
222
}
223
 
224
static void
225
dump(Vga*, Ctlr* ctlr)
226
{
227
	Group *g;
228
	int *xp;
229
	char *name;
230
	int lastx;
231
	char item[32];
232
 
233
	name = ctlr->name;
234
 
235
	for(g = group; g->name; g++){
236
		lastx = -2;
237
		for(xp = g->x; *xp >= 0; xp++){
238
			if(*xp != lastx+1){
239
				sprint(item, "%s %2.2ux:", g->name, *xp);
240
				printitem(name, item);
241
			}
242
			lastx = *xp;
243
			printreg(greg[*xp]);
244
		}
245
	}
246
}
247
 
248
Ctlr ct65540 = {
249
	"ct65540",			/* name */
250
	snarf,				/* snarf */
251
	options,			/* options */
252
	init,				/* init */
253
	load,				/* load */
254
	dump,				/* dump */
255
};
256
 
257
Ctlr ct65545 = {
258
	"ct65545",			/* name */
259
	snarf,				/* snarf */
260
	options,			/* options */
261
	init,				/* init */
262
	load,				/* load */
263
	dump,				/* dump */
264
};
265
 
266
Ctlr ct65545hwgc = {
267
	"ct65545hwgc",			/* name */
268
	0,				/* snarf */
269
	0,				/* options */
270
	0,				/* init */
271
	0,				/* load */
272
	0,				/* dump */
273
};