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
/*
9
 * Generic S3 GUI Accelerator.
10
 */
11
static void
12
snarf(Vga* vga, Ctlr* ctlr)
13
{
14
	int i;
15
 
16
	trace("%s->snarf->s3generic\n", ctlr->name);
17
 
18
	/*
19
	 * Unlock extended registers.
20
	 * 0xA5 ensures Crt36 and Crt37 are also unlocked
21
	 * (0xA0 unlocks everything else).
22
	 */
23
	vgaxo(Crtx, 0x38, 0x48);
24
	vgaxo(Crtx, 0x39, 0xA5);
25
 
26
	/*
27
	 * Not all registers exist on all chips.
28
	 * Crt3[EF] don't exist on any.
29
	 */
30
	for(i = 0x30; i < 0x70; i++)
31
		vga->crt[i] = vgaxi(Crtx, i);
32
 
33
	/*
34
	 * Memory size.
35
	 */
36
	switch((vga->crt[0x36]>>5) & 0x07){
37
 
38
	case 0x00:
39
		vga->vmz = 4*1024*1024;
40
		break;
41
 
42
	case 0x02:
43
		vga->vmz = 3*1024*1024;
44
		break;
45
 
46
	case 0x04:
47
		vga->vmz = 2*1024*1024;
48
		break;
49
 
50
	case 0x06:
51
		vga->vmz = 1*1024*1024;
52
		break;
53
 
54
	case 0x07:
55
		vga->vmz = 512*1024;
56
		break;
57
	}
58
 
59
	ctlr->flag |= Fsnarf;
60
}
61
 
62
static void
63
init(Vga* vga, Ctlr* ctlr)
64
{
65
	Mode *mode;
66
	ulong x;
67
 
68
	trace("%s->init->s3generic\n", ctlr->name);
69
	mode = vga->mode;
70
 
71
	/*
72
	 * Is enhanced mode is necessary?
73
	 */
74
	if((ctlr->flag & (Uenhanced|Henhanced)) == Henhanced){
75
		if(mode->z >= 8)
76
			resyncinit(vga, ctlr, Uenhanced, 0);
77
		else
78
			resyncinit(vga, ctlr, 0, Uenhanced|Henhanced);
79
	}
80
	if((ctlr->flag & Uenhanced) == 0 && mode->x > 1024)
81
		error("%s: no support for 1-bit mode > 1024x768x1\n", ctlr->name);
82
 
83
	vga->crt[0x31] = 0x85;
84
	vga->crt[0x6A] &= 0xC0;
85
	vga->crt[0x32] &= ~0x40;
86
 
87
	vga->crt[0x31] |= 0x08;
88
	vga->crt[0x32] |= 0x40;
89
 
90
	vga->crt[0x33] |= 0x20;
91
	if(mode->z >= 8)
92
		vga->crt[0x3A] |= 0x10;
93
	else
94
		vga->crt[0x3A] &= ~0x10;
95
 
96
	vga->crt[0x34] = 0x10;
97
	vga->crt[0x35] = 0x00;
98
	if(mode->interlace){
99
		vga->crt[0x3C] = vga->crt[0]/2;
100
		vga->crt[0x42] |= 0x20;
101
	}
102
	else{
103
		vga->crt[0x3C] = 0x00;
104
		vga->crt[0x42] &= ~0x20;
105
	}
106
 
107
	vga->crt[0x40] = (vga->crt[0x40] & 0xF2);
108
	vga->crt[0x43] = 0x00;
109
	vga->crt[0x45] = 0x00;
110
 
111
	vga->crt[0x50] &= 0x3E;
112
	if(mode->x <= 640)
113
		x = 0x40;
114
	else if(mode->x <= 800)
115
		x = 0x80;
116
	else if(mode->x <= 1024)
117
		x = 0x00;
118
	else if(mode->x <= 1152)
119
		x = 0x01;
120
	else if(mode->x <= 1280)
121
		x = 0xC0;
122
	else
123
		x = 0x81;
124
	vga->crt[0x50] |= x;
125
 
126
	vga->crt[0x51] = (vga->crt[0x51] & 0xC3)|((vga->crt[0x13]>>4) & 0x30);
127
	vga->crt[0x53] &= ~0x10;
128
 
129
	/*
130
	 * Set up linear aperture. For the moment it's 64K at 0xA0000.
131
	 * The real base address will be assigned before load is called.
132
	 */
133
	vga->crt[0x58] = 0x88;
134
	if(ctlr->flag & Uenhanced){
135
		vga->crt[0x58] |= 0x10;
136
		if(vga->linear && (ctlr->flag & Hlinear))
137
			ctlr->flag |= Ulinear;
138
		if(vga->vmz <= 1024*1024)
139
			vga->vma = 1024*1024;
140
		else if(vga->vmz <= 2*1024*1024)
141
			vga->vma = 2*1024*1024;
142
		else
143
			vga->vma = 8*1024*1024;
144
	}
145
	vga->crt[0x59] = 0x00;
146
	vga->crt[0x5A] = 0x0A;
147
 
148
	vga->crt[0x5D] &= 0x80;
149
	if(vga->crt[0x00] & 0x100)
150
		vga->crt[0x5D] |= 0x01;
151
	if(vga->crt[0x01] & 0x100)
152
		vga->crt[0x5D] |= 0x02;
153
	if(vga->crt[0x02] & 0x100)
154
		vga->crt[0x5D] |= 0x04;
155
	if(vga->crt[0x04] & 0x100)
156
		vga->crt[0x5D] |= 0x10;
157
	if(vga->crt[0x3B] & 0x100)
158
		vga->crt[0x5D] |= 0x40;
159
 
160
	vga->crt[0x5E] = 0x40;
161
	if(vga->crt[0x06] & 0x400)
162
		vga->crt[0x5E] |= 0x01;
163
	if(vga->crt[0x12] & 0x400)
164
		vga->crt[0x5E] |= 0x02;
165
	if(vga->crt[0x15] & 0x400)
166
		vga->crt[0x5E] |= 0x04;
167
	if(vga->crt[0x10] & 0x400)
168
		vga->crt[0x5E] |= 0x10;
169
 
170
	ctlr->type = s3generic.name;
171
 
172
	ctlr->flag |= Finit;
173
}
174
 
175
static void
176
load(Vga* vga, Ctlr* ctlr)
177
{
178
	ulong l;
179
 
180
	trace("%s->load->s3generic\n", ctlr->name);
181
 
182
	vgaxo(Crtx, 0x31, vga->crt[0x31]);
183
	vgaxo(Crtx, 0x32, vga->crt[0x32]);
184
	vgaxo(Crtx, 0x33, vga->crt[0x33]);
185
	vgaxo(Crtx, 0x34, vga->crt[0x34]);
186
	vgaxo(Crtx, 0x35, vga->crt[0x35]);
187
	vgaxo(Crtx, 0x3A, vga->crt[0x3A]);
188
	vgaxo(Crtx, 0x3B, vga->crt[0x3B]);
189
	vgaxo(Crtx, 0x3C, vga->crt[0x3C]);
190
 
191
	vgaxo(Crtx, 0x40, vga->crt[0x40]|0x01);
192
	vgaxo(Crtx, 0x42, vga->crt[0x42]);
193
	vgaxo(Crtx, 0x43, vga->crt[0x43]);
194
	vgaxo(Crtx, 0x45, vga->crt[0x45]);
195
 
196
	vgaxo(Crtx, 0x50, vga->crt[0x50]);
197
	vgaxo(Crtx, 0x51, vga->crt[0x51]);
198
	vgaxo(Crtx, 0x53, vga->crt[0x53]);
199
	vgaxo(Crtx, 0x54, vga->crt[0x54]);
200
	vgaxo(Crtx, 0x55, vga->crt[0x55]);
201
 
202
	if(ctlr->flag & Ulinear){
203
		l = vga->vmb>>16;
204
		vga->crt[0x59] = (l>>8) & 0xFF;
205
		vga->crt[0x5A] = l & 0xFF;
206
		if(vga->vmz <= 1024*1024)
207
			vga->crt[0x58] |= 0x01;
208
		else if(vga->vmz <= 2*1024*1024)
209
			vga->crt[0x58] |= 0x02;
210
		else
211
			vga->crt[0x58] |= 0x03;
212
	}
213
	vgaxo(Crtx, 0x59, vga->crt[0x59]);
214
	vgaxo(Crtx, 0x5A, vga->crt[0x5A]);
215
	vgaxo(Crtx, 0x58, vga->crt[0x58]);
216
 
217
	vgaxo(Crtx, 0x5D, vga->crt[0x5D]);
218
	vgaxo(Crtx, 0x5E, vga->crt[0x5E]);
219
 
220
	vgaxo(Crtx, 0x6A, vga->crt[0x6A]);
221
 
222
	ctlr->flag |= Fload;
223
}
224
 
225
static void
226
dump(Vga* vga, Ctlr* ctlr)
227
{
228
	int i, id, interlace, mul, div;
229
	char *name;
230
	ushort shb, vrs, x;
231
 
232
	name = ctlr->name;
233
 
234
	printitem(name, "Crt30");
235
	for(i = 0x30; i < 0x3E; i++)
236
		printreg(vga->crt[i]);
237
 
238
	printitem(name, "Crt40");
239
	for(i = 0x40; i < 0x50; i++)
240
		printreg(vga->crt[i]);
241
 
242
	printitem(name, "Crt50");
243
	for(i = 0x50; i < 0x60; i++)
244
		printreg(vga->crt[i]);
245
 
246
	printitem(name, "Crt60");
247
	for(i = 0x60; i < 0x70; i++)
248
		printreg(vga->crt[i]);
249
 
250
	/*
251
	 * Try to disassemble the snarfed values into
252
	 * understandable numbers.
253
	 * Only do this if we weren't called after Finit.
254
	 */
255
	if(ctlr->flag & Finit)
256
		return;
257
 
258
 
259
	/*
260
	 * If hde <= 400, assume this is a 928 or Vision964
261
	 * and the horizontal values have been divided by 4.
262
	 *
263
	 * if ViRGE/[DG]X and 15 or 16bpp, horizontal values have
264
	 * been multiplied by 2.
265
	 */
266
	mul = 1;
267
	div = 1;
268
 
269
	if(strcmp(name, "virge") == 0){
270
		id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
271
		/* S3 ViRGE/[DG]X */
272
		if(id==0x8A01 && ((vga->crt[0x67] & 0x30) || (vga->crt[0x67] & 0x50))){
273
			mul = 1;
274
			div = 2;
275
		}
276
	}
277
 
278
	x = vga->crt[0x01];
279
	if(vga->crt[0x5D] & 0x02)
280
		x |= 0x100;
281
	x = (x+1)<<3;
282
 
283
	if(x <= 400){
284
		mul = 4;
285
		div = 1;
286
	}
287
 
288
	x = (x * mul) / div;
289
	printitem(name, "hde");
290
	printreg(x);
291
	Bprint(&stdout, "%6ud", x);
292
 
293
	shb = vga->crt[0x02];
294
	if(vga->crt[0x5D] & 0x04)
295
		shb |= 0x100;
296
	shb = (shb+1)<<3;
297
	shb = (shb * mul) / div;
298
	printitem(name, "shb");
299
	printreg(shb);
300
	Bprint(&stdout, "%6ud", shb);
301
 
302
	x = vga->crt[0x03] & 0x1F;
303
	if(vga->crt[0x05] & 0x80)
304
		x |= 0x20;
305
	x = (x * mul) / div;
306
	x = shb|x;					/* ???? */
307
	if(vga->crt[0x5D] & 0x08)
308
		x += 64;
309
	printitem(name, "ehb");
310
	printreg(x);
311
	Bprint(&stdout, "%6ud", x);
312
 
313
	x = vga->crt[0x00];
314
	if(vga->crt[0x5D] & 0x01)
315
		x |= 0x100;
316
	x = (x+5)<<3;
317
	x = (x * mul) / div;
318
	printitem(name, "ht");
319
	printreg(x);
320
	Bprint(&stdout, "%6ud", x);
321
 
322
	interlace = vga->crt[0x42] & 0x20;
323
	x = vga->crt[0x12];
324
	if(vga->crt[0x07] & 0x02)
325
		x |= 0x100;
326
	if(vga->crt[0x07] & 0x40)
327
		x |= 0x200;
328
	if(vga->crt[0x5E] & 0x02)
329
		x |= 0x400;
330
	x += 1;
331
	if(interlace)
332
		x *= 2;
333
	printitem(name, "vde");
334
	printreg(x);
335
	Bprint(&stdout, "%6ud", x);
336
 
337
	vrs = vga->crt[0x10];
338
	if(vga->crt[0x07] & 0x04)
339
		vrs |= 0x100;
340
	if(vga->crt[0x07] & 0x80)
341
		vrs |= 0x200;
342
	if(vga->crt[0x5E] & 0x10)
343
		vrs |= 0x400;
344
	if(interlace)
345
		vrs *= 2;
346
	printitem(name, "vrs");
347
	printreg(vrs);
348
	Bprint(&stdout, "%6ud", vrs);
349
 
350
	if(interlace)
351
		vrs /= 2;
352
	x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F);
353
	if(interlace)
354
		x *= 2;
355
	printitem(name, "vre");
356
	printreg(x);
357
	Bprint(&stdout, "%6ud", x);
358
 
359
	x = vga->crt[0x06];
360
	if(vga->crt[0x07] & 0x01)
361
		x |= 0x100;
362
	if(vga->crt[0x07] & 0x20)
363
		x |= 0x200;
364
	if(vga->crt[0x5E] & 0x01)
365
		x |= 0x400;
366
	x += 2;
367
	if(interlace)
368
		x *= 2;
369
	printitem(name, "vt");
370
	printreg(x);
371
	Bprint(&stdout, "%6ud", x);
372
}
373
 
374
Ctlr s3generic = {
375
	"s3",				/* name */
376
	snarf,				/* snarf */
377
	0,				/* options */
378
	init,				/* init */
379
	load,				/* load */
380
	dump,				/* dump */
381
};