Subversion Repositories planix.SVN

Rev

Details | 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
	NSeqx		= 0x05,
10
	NCrtx		= 0x19,
11
	NGrx		= 0x09,
12
	NAttrx		= 0x15,
13
};
14
 
15
uchar
16
vgai(long port)
17
{
18
	uchar data;
19
 
20
	switch(port){
21
 
22
	case MiscR:
23
	case Status0:
24
	case Status1:
25
	case FeatureR:
26
	case PaddrW:
27
	case Pdata:
28
	case Pixmask:
29
	case Pstatus:
30
		data = inportb(port);
31
		break;
32
 
33
	default:
34
		error("vgai(0x%4.4lX): unknown port\n", port);
35
		/*NOTREACHED*/
36
		data = 0xFF;
37
		break;
38
	}
39
	return data;
40
}
41
 
42
uchar
43
vgaxi(long port, uchar index)
44
{
45
	uchar data;
46
 
47
	switch(port){
48
 
49
	case Seqx:
50
	case Crtx:
51
	case Grx:
52
		outportb(port, index);
53
		data = inportb(port+1);
54
		break;
55
 
56
	case Attrx:
57
		/*
58
		 * Allow processor access to the colour
59
		 * palette registers. Writes to Attrx must
60
		 * be preceded by a read from Status1 to
61
		 * initialise the register to point to the
62
		 * index register and not the data register.
63
		 * Processor access is allowed by turning
64
		 * off bit 0x20.
65
		 */
66
		inportb(Status1);
67
		if(index < 0x10){
68
			outportb(Attrx, index);
69
			data = inportb(Attrx+1);
70
			inportb(Status1);
71
			outportb(Attrx, 0x20|index);
72
		}
73
		else{
74
			outportb(Attrx, 0x20|index);
75
			data = inportb(Attrx+1);
76
		}
77
		break;
78
 
79
	default:
80
		error("vgaxi(0x%4.4lx, 0x%2.2uX): unknown port\n", port, index);
81
		/*NOTREACHED*/
82
		data = 0xFF;
83
		break;
84
	}
85
	return data;
86
}
87
 
88
void
89
vgao(long port, uchar data)
90
{
91
	switch(port){
92
 
93
	case MiscW:
94
	case FeatureW:
95
	case PaddrW:
96
	case Pdata:
97
	case Pixmask:
98
	case PaddrR:
99
		outportb(port, data);
100
		break;
101
 
102
	default:
103
		error("vgao(0x%4.4lX, 0x%2.2uX): unknown port\n", port, data);
104
		/*NOTREACHED*/
105
		break;
106
	}
107
}
108
 
109
void
110
vgaxo(long port, uchar index, uchar data)
111
{
112
	switch(port){
113
 
114
	case Seqx:
115
	case Crtx:
116
	case Grx:
117
		/*
118
		 * We could use an outport here, but some chips
119
		 * (e.g. 86C928) have trouble with that for some
120
		 * registers.
121
		 */
122
		outportb(port, index);
123
		outportb(port+1, data);
124
		break;
125
 
126
	case Attrx:
127
		inportb(Status1);
128
		if(index < 0x10){
129
			outportb(Attrx, index);
130
			outportb(Attrx, data);
131
			inportb(Status1);
132
			outportb(Attrx, 0x20|index);
133
		}
134
		else{
135
			outportb(Attrx, 0x20|index);
136
			outportb(Attrx, data);
137
		}
138
		break;
139
 
140
	default:
141
		error("vgaxo(0x%4.4lX, 0x%2.2uX, 0x%2.2uX): unknown port\n",
142
			port, index, data);
143
		break;
144
	}
145
}
146
 
147
static void
148
snarf(Vga* vga, Ctlr* ctlr)
149
{
150
	int i;
151
 
152
	/*
153
	 * Generic VGA registers:
154
	 * 	misc, feature;
155
	 *	sequencer;
156
	 *	crt;
157
	 *	graphics;
158
	 *	attribute;
159
	 *	palette.
160
	 */
161
	vga->misc = vgai(MiscR);
162
	vga->feature = vgai(FeatureR);
163
 
164
	for(i = 0; i < NSeqx; i++)
165
		vga->sequencer[i] = vgaxi(Seqx, i);
166
 
167
	for(i = 0; i < NCrtx; i++)
168
		vga->crt[i] = vgaxi(Crtx, i);
169
 
170
	for(i = 0; i < NGrx; i++)
171
		vga->graphics[i] = vgaxi(Grx, i);
172
 
173
	for(i = 0; i < NAttrx; i++)
174
		vga->attribute[i] = vgaxi(Attrx, i);
175
 
176
	if(dflag)
177
		palette.snarf(vga, ctlr);
178
 
179
	ctlr->flag |= Fsnarf;
180
}
181
 
182
static void
183
init(Vga* vga, Ctlr* ctlr)
184
{
185
	Mode *mode;
186
	int vt, vde, vrs, vre;
187
	ulong tmp;
188
 
189
	mode = vga->mode;
190
 
191
	memset(vga->sequencer, 0, NSeqx*sizeof(vga->sequencer[0]));
192
	memset(vga->crt, 0, NCrtx*sizeof(vga->crt[0]));
193
	memset(vga->graphics, 0, NGrx*sizeof(vga->graphics[0]));
194
	memset(vga->attribute, 0, NAttrx*sizeof(vga->attribute[0]));
195
	if(dflag)
196
		memset(vga->palette, 0, sizeof(vga->palette));
197
 
198
	/*
199
	 * Misc. If both the horizontal and vertical sync polarity
200
	 * options are set, use them. Otherwise use the defaults for
201
	 * the given vertical size.
202
	 */
203
	vga->misc = 0x23;
204
	if(mode->frequency == VgaFreq1)
205
		vga->misc |= 0x04;
206
	if(mode->hsync && mode->vsync){
207
		if(mode->hsync == '-')
208
			vga->misc |= 0x40;
209
		if(mode->vsync == '-')
210
			vga->misc |= 0x80;
211
	}
212
	else{
213
		if(mode->y < 480)
214
			vga->misc |= 0x40;
215
		else if(mode->y < 400)
216
			vga->misc |= 0x80;
217
		else if(mode->y < 768)
218
			vga->misc |= 0xC0;
219
	}
220
 
221
	/*
222
	 * Sequencer
223
	 */
224
	vga->sequencer[0x00] = 0x03;
225
	vga->sequencer[0x01] = 0x01;
226
	vga->sequencer[0x02] = 0x0F;
227
	vga->sequencer[0x03] = 0x00;
228
	if(mode->z >= 8)
229
		vga->sequencer[0x04] = 0x0A;
230
	else
231
		vga->sequencer[0x04] = 0x06;
232
 
233
	/*
234
	 * Crt. Most of the work here is in dealing
235
	 * with field overflow.
236
	 */
237
	memset(vga->crt, 0, NCrtx);
238
 
239
	vga->crt[0x00] = (mode->ht>>3)-5;
240
	vga->crt[0x01] = (mode->x>>3)-1;
241
	vga->crt[0x02] = (mode->shb>>3)-1;
242
 
243
	/*
244
	 * End Horizontal Blank is a 6-bit field, 5-bits
245
	 * in Crt3, high bit in Crt5.
246
	 */
247
	tmp = mode->ehb>>3;
248
	vga->crt[0x03] = 0x80|(tmp & 0x1F);
249
	if(tmp & 0x20)
250
		vga->crt[0x05] |= 0x80;
251
 
252
	if(mode->shs == 0)
253
		mode->shs = mode->shb;
254
	vga->crt[0x04] = mode->shs>>3;
255
	if(mode->ehs == 0)
256
		mode->ehs = mode->ehb;
257
	vga->crt[0x05] |= ((mode->ehs>>3) & 0x1F);
258
 
259
	/*
260
	 * Vertical Total is 10-bits, 8 in Crt6, the high
261
	 * two bits in Crt7. What if vt is >= 1024? We hope
262
	 * the specific controller has some more overflow
263
	 * bits.
264
	 *
265
	 * Interlace: if 'v',  divide the vertical timing
266
	 * values by 2.
267
	 */
268
	vt = mode->vt;
269
	vde = mode->y;
270
	vrs = mode->vrs;
271
	vre = mode->vre;
272
 
273
	if(mode->interlace == 'v'){
274
		vt /= 2;
275
		vde /= 2;
276
		vrs /= 2;
277
		vre /= 2;
278
	}
279
 
280
	tmp = vt-2;
281
	vga->crt[0x06] = tmp;
282
	if(tmp & 0x100)
283
		vga->crt[0x07] |= 0x01;
284
	if(tmp & 0x200)
285
		vga->crt[0x07] |= 0x20;
286
 
287
	tmp = vrs;
288
	vga->crt[0x10] = tmp;
289
	if(tmp & 0x100)
290
		vga->crt[0x07] |= 0x04;
291
	if(tmp & 0x200)
292
		vga->crt[0x07] |= 0x80;
293
 
294
	vga->crt[0x11] = 0x20|(vre & 0x0F);
295
 
296
	tmp = vde-1;
297
	vga->crt[0x12] = tmp;
298
	if(tmp & 0x100)
299
		vga->crt[0x07] |= 0x02;
300
	if(tmp & 0x200)
301
		vga->crt[0x07] |= 0x40;
302
 
303
	vga->crt[0x15] = vrs;
304
	if(vrs & 0x100)
305
		vga->crt[0x07] |= 0x08;
306
	if(vrs & 0x200)
307
		vga->crt[0x09] |= 0x20;
308
 
309
	vga->crt[0x16] = (vrs+1);
310
 
311
	vga->crt[0x17] = 0x83;
312
	tmp = ((vga->virtx*mode->z)/8);
313
	if(tmp >= 512){
314
		vga->crt[0x14] |= 0x60;
315
		tmp /= 8;
316
	}
317
	else if(tmp >= 256){
318
		vga->crt[0x17] |= 0x08;
319
		tmp /= 4;
320
	}
321
	else{
322
		vga->crt[0x17] |= 0x40;
323
		tmp /= 2;
324
	}
325
	vga->crt[0x13] = tmp;
326
 
327
	if(mode->x*mode->y*mode->z/8 > 64*1024)
328
		vga->crt[0x17] |= 0x20;
329
 
330
	vga->crt[0x18] = 0x7FF;
331
	if(vga->crt[0x18] & 0x100)
332
		vga->crt[0x07] |= 0x10;
333
	if(vga->crt[0x18] & 0x200)
334
		vga->crt[0x09] |= 0x40;
335
 
336
	/*
337
	 * Graphics
338
	 */
339
	memset(vga->graphics, 0, NGrx);
340
	if((vga->sequencer[0x04] & 0x04) == 0)
341
		vga->graphics[0x05] |= 0x10;
342
	if(mode->z >= 8)
343
		vga->graphics[0x05] |= 0x40;
344
	vga->graphics[0x06] = 0x05;
345
	vga->graphics[0x07] = 0x0F;
346
	vga->graphics[0x08] = 0xFF;
347
 
348
	/*
349
	 * Attribute
350
	 */
351
	memset(vga->attribute, 0, NAttrx);
352
	for(tmp = 0; tmp < 0x10; tmp++)
353
		vga->attribute[tmp] = tmp;
354
	vga->attribute[0x10] = 0x01;
355
	if(mode->z >= 8)
356
		vga->attribute[0x10] |= 0x40;
357
	vga->attribute[0x11] = 0xFF;
358
	vga->attribute[0x12] = 0x0F;
359
 
360
	/*
361
	 * Palette
362
	 */
363
	if(dflag)
364
		palette.init(vga, ctlr);
365
 
366
	ctlr->flag |= Finit;
367
}
368
 
369
static void
370
load(Vga* vga, Ctlr* ctlr)
371
{
372
	int i;
373
 
374
	/*
375
	 * Reset the sequencer and leave it off.
376
	 * Load the generic VGA registers:
377
	 *	misc;
378
	 *	sequencer (but not seq01, display enable);
379
	 *	take the sequencer out of reset;
380
	 *	take off write-protect on crt[0x00-0x07];
381
	 *	crt;
382
	 *	graphics;
383
	 *	attribute;
384
	 *	palette.
385
	vgaxo(Seqx, 0x00, 0x00);
386
	 */
387
 
388
	vgao(MiscW, vga->misc);
389
 
390
	for(i = 2; i < NSeqx; i++)
391
		vgaxo(Seqx, i, vga->sequencer[i]);
392
	/*vgaxo(Seqx, 0x00, 0x03);*/
393
 
394
	vgaxo(Crtx, 0x11, vga->crt[0x11] & ~0x80);
395
	for(i = 0; i < NCrtx; i++)
396
		vgaxo(Crtx, i, vga->crt[i]);
397
 
398
	for(i = 0; i < NGrx; i++)
399
		vgaxo(Grx, i, vga->graphics[i]);
400
 
401
	for(i = 0; i < NAttrx; i++)
402
		vgaxo(Attrx, i, vga->attribute[i]);
403
 
404
	if(dflag)
405
		palette.load(vga, ctlr);
406
 
407
	ctlr->flag |= Fload;
408
}
409
 
410
static void
411
dump(Vga* vga, Ctlr* ctlr)
412
{
413
	int i;
414
 
415
	printitem(ctlr->name, "misc");
416
	printreg(vga->misc);
417
	printitem(ctlr->name, "feature");
418
	printreg(vga->feature);
419
 
420
	printitem(ctlr->name, "sequencer");
421
	for(i = 0; i < NSeqx; i++)
422
		printreg(vga->sequencer[i]);
423
 
424
	printitem(ctlr->name, "crt");
425
	for(i = 0; i < NCrtx; i++)
426
		printreg(vga->crt[i]);
427
 
428
	printitem(ctlr->name, "graphics");
429
	for(i = 0; i < NGrx; i++)
430
		printreg(vga->graphics[i]);
431
 
432
	printitem(ctlr->name, "attribute");
433
	for(i = 0; i < NAttrx; i++)
434
		printreg(vga->attribute[i]);
435
 
436
	if(dflag)
437
		palette.dump(vga, ctlr);
438
 
439
	printitem(ctlr->name, "virtual");
440
	Bprint(&stdout, "%ld %ld\n", vga->virtx, vga->virty);
441
	printitem(ctlr->name, "panning");
442
	Bprint(&stdout, "%s\n", vga->panning ? "on" : "off");
443
	if(vga->f[0]){
444
		printitem(ctlr->name, "clock[0] f");
445
		Bprint(&stdout, "%9ld\n", vga->f[0]);
446
		printitem(ctlr->name, "clock[0] d i m");
447
		Bprint(&stdout, "%9ld %8ld       - %8ld\n",
448
			vga->d[0], vga->i[0], vga->m[0]);
449
		printitem(ctlr->name, "clock[0] n p q r");
450
		Bprint(&stdout, "%9ld %8ld       - %8ld %8ld\n",
451
			vga->n[0], vga->p[0], vga->q[0], vga->r[0]);
452
	}
453
	if(vga->f[1]){
454
		printitem(ctlr->name, "clock[1] f");
455
		Bprint(&stdout, "%9ld\n", vga->f[1]);
456
		printitem(ctlr->name, "clock[1] d i m");
457
		Bprint(&stdout, "%9ld %8ld       - %8ld\n",
458
			vga->d[1], vga->i[1], vga->m[1]);
459
		printitem(ctlr->name, "clock[1] n p q r");
460
		Bprint(&stdout, "%9ld %8ld       - %8ld %8ld\n",
461
			vga->n[1], vga->p[1], vga->q[1], vga->r[1]);
462
	}
463
 
464
	if(vga->vma || vga->vmb){
465
		printitem(ctlr->name, "vm a b");
466
		Bprint(&stdout, "%9lud %8lud\n", vga->vma, vga->vmb);
467
	}
468
	if(vga->vmz){
469
		printitem(ctlr->name, "vmz");
470
		Bprint(&stdout, "%9lud\n", vga->vmz);
471
	}
472
	printitem(ctlr->name, "apz");
473
	Bprint(&stdout, "%9lud\n", vga->apz);
474
 
475
	printitem(ctlr->name, "linear");
476
	Bprint(&stdout, "%9d\n", vga->linear);
477
}
478
 
479
Ctlr generic = {
480
	"vga",				/* name */
481
	snarf,				/* snarf */
482
	0,				/* options */
483
	init,				/* init */
484
	load,				/* load */
485
	dump,				/* dump */
486
};