xref: /plan9/sys/src/cmd/aux/vga/ark2000pv.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "pci.h"
6 #include "vga.h"
7 
8 /*
9  * ARK Logic ARK2000PV GUI accelerator.
10  */
11 static void
snarf(Vga * vga,Ctlr * ctlr)12 snarf(Vga* vga, Ctlr* ctlr)
13 {
14 	int i;
15 
16 	/*
17 	 * Unlock access to the extended I/O registers.
18 	 */
19 	vgaxo(Seqx, 0x1D, 0x01);
20 
21 	for(i = 0x10; i < 0x2E; i++)
22 		vga->sequencer[i] = vgaxi(Seqx, i);
23 	for(i = 0x40; i < 0x47; i++)
24 		vga->crt[i] = vgaxi(Crtx, i);
25 	vga->crt[0x50] = vgaxi(Crtx, 0x50);
26 
27 	/*
28 	 * A hidey-hole for the coprocessor status register.
29 	 */
30 	vga->crt[0xFF] = inportb(0x3CB);
31 
32 	/*
33 	 * Memory size.
34 	 */
35 	switch((vga->sequencer[0x10]>>6) & 0x03){
36 
37 	case 0x00:
38 		vga->vma = vga->vmz = 1*1024*1024;
39 		break;
40 
41 	case 0x01:
42 		vga->vma = vga->vmz = 2*1024*1024;
43 		break;
44 
45 	case 0x02:
46 		vga->vma = vga->vmz = 4*1024*1024;
47 		break;
48 	}
49 
50 	ctlr->flag |= Fsnarf;
51 }
52 
53 static void
options(Vga *,Ctlr * ctlr)54 options(Vga*, Ctlr* ctlr)
55 {
56 	ctlr->flag |= Hlinear|Hpclk2x8|Foptions;
57 }
58 
59 static void
init(Vga * vga,Ctlr * ctlr)60 init(Vga* vga, Ctlr* ctlr)
61 {
62 	Mode *mode;
63 	ulong x;
64 
65 	mode = vga->mode;
66 
67 	vga->crt[0x46] = 0x00;
68 	if(ctlr->flag & Upclk2x8){
69 		vga->crt[0x00] = ((mode->ht/2)>>3)-5;
70 		vga->crt[0x01] = ((mode->x/2)>>3)-1;
71 		vga->crt[0x02] = ((mode->shb/2)>>3)-1;
72 
73 		x = (mode->ehb/2)>>3;
74 		vga->crt[0x03] = 0x80|(x & 0x1F);
75 		vga->crt[0x04] = (mode->shs/2)>>3;
76 		vga->crt[0x05] = ((mode->ehs/2)>>3) & 0x1F;
77 		if(x & 0x20)
78 			vga->crt[0x05] |= 0x80;
79 		vga->crt[0x13] = mode->x/8;
80 
81 		vga->crt[0x46] |= 0x04;
82 	}
83 
84 	/*
85 	 * Overflow bits.
86 	 */
87 	vga->crt[0x40] = 0x00;
88 	if(vga->crt[0x18] & 0x400)
89 		vga->crt[0x40] |= 0x08;
90 	if(vga->crt[0x10] & 0x400)
91 		vga->crt[0x40] |= 0x10;
92 	if(vga->crt[0x15] & 0x400)
93 		vga->crt[0x40] |= 0x20;
94 	if(vga->crt[0x12] & 0x400)
95 		vga->crt[0x40] |= 0x40;
96 	if(vga->crt[0x06] & 0x400)
97 		vga->crt[0x40] |= 0x80;
98 
99 	vga->crt[0x41] = 0x00;
100 	if(vga->crt[0x13] & 0x100)
101 		vga->crt[0x41] |= 0x08;
102 	if(vga->crt[0x04] & 0x100)
103 		vga->crt[0x41] |= 0x10;
104 	if(vga->crt[0x02] & 0x100)
105 		vga->crt[0x41] |= 0x20;
106 	if(vga->crt[0x01] & 0x100)
107 		vga->crt[0x41] |= 0x40;
108 	if(vga->crt[0x00] & 0x100)
109 		vga->crt[0x41] |= 0x80;
110 
111 	/*
112 	 * Interlace.
113 	 */
114 	vga->crt[0x42] = 0x00;
115 	vga->crt[0x44] = 0x00;
116 	if(mode->interlace){
117 		vga->crt[0x42] = vga->crt[0]/2;
118 		vga->crt[0x44] |= 0x04;
119 	}
120 	vga->crt[0x45] = 0x00;
121 
122 	/*
123 	 * Memory configuration:
124 	 * enable linear|coprocessor|VESA modes;
125 	 * set aperture to 64Kb, 0xA0000;
126 	 * set aperture index 0.
127 	 * Bugs: 1024x768x1 doesn't work (aperture not set correctly?);
128 	 *	 hwgc doesn't work in 1-bit modes (hardware?).
129 	 */
130 	vga->sequencer[0x10] &= ~0x3F;
131 	vga->sequencer[0x11] &= ~0x0F;
132 	switch(mode->z){
133 
134 	case 1:
135 		vga->sequencer[0x10] |= 0x03;
136 		vga->sequencer[0x11] |= 0x01;
137 		cflag = 1;
138 		break;
139 
140 	case 8:
141 		vga->sequencer[0x10] |= 0x0F;
142 		vga->sequencer[0x11] |= 0x06;
143 		if(vga->linear && (ctlr->flag & Hlinear) && vga->vmz)
144 			ctlr->flag |= Ulinear;
145 		break;
146 
147 	default:
148 		error("depth %d not supported\n", mode->z);
149 	}
150 	vga->sequencer[0x12] &= ~0x03;
151 	vga->sequencer[0x13] = 0x0A;
152 	vga->sequencer[0x14] = 0x00;
153 	vga->sequencer[0x15] = 0x00;
154 	vga->sequencer[0x16] = 0x00;
155 
156 	/*
157 	 * Frame Buffer Pitch and FIFO control.
158 	 * Set the FIFO to 32 deep and refill trigger when
159 	 * 6 slots empty.
160 	 */
161 	vga->sequencer[0x17] = 0x00;
162 	vga->sequencer[0x18] = 0x13;
163 	if(mode->x <= 640)
164 		vga->sequencer[0x17] = 0x00;
165 	else if(mode->x <= 800)
166 		vga->sequencer[0x17] |= 0x01;
167 	else if(mode->x <= 1024)
168 		vga->sequencer[0x17] |= 0x02;
169 	else if(mode->x <= 1280)
170 		vga->sequencer[0x17] |= 0x04;
171 	else if(mode->x <= 1600)
172 		vga->sequencer[0x17] |= 0x05;
173 	else if(mode->x <= 2048)
174 		vga->sequencer[0x17] |= 0x06;
175 
176 	/*
177 	 * Clock select.
178 	 */
179 	vga->misc &= ~0x0C;
180 	vga->misc |= (vga->i[0] & 0x03)<<2;
181 	vga->sequencer[0x11] &= ~0xC0;
182 	vga->sequencer[0x11] |= (vga->i[0] & 0x0C)<<4;
183 
184 	vga->attribute[0x11] = 0x00;	/* color map entry for black */
185 
186 	ctlr->flag |= Finit;
187 }
188 
189 static void
load(Vga * vga,Ctlr * ctlr)190 load(Vga* vga, Ctlr* ctlr)
191 {
192 	ulong l;
193 
194 	/*
195 	 * Ensure there are no glitches when selecting a new
196 	 * clock frequency.
197 	 * The sequencer toggle seems to matter on the Hercules
198 	 * Stingray 64/Video at 1280x1024x8. Without it the screen
199 	 * is fuzzy; a second load clears it up and there's no
200 	 * difference between the two register sets. A mystery.
201 	 */
202 	vgao(MiscW, vga->misc & ~0x0C);
203 	vgaxo(Seqx, 0x11, vga->sequencer[0x11]);
204 	vgao(MiscW, vga->misc);
205 	if(vga->ramdac && strncmp(vga->ramdac->name, "w30c516", 7) == 0){
206 		sequencer(vga, 1);
207 		sleep(500);
208 		sequencer(vga, 0);
209 	}
210 
211 	if(ctlr->flag & Ulinear){
212 		vga->sequencer[0x10] |= 0x10;
213 		if(vga->vmz <= 1024*1024)
214 			vga->sequencer[0x12] |= 0x01;
215 		else if(vga->vmz <= 2*1024*1024)
216 			vga->sequencer[0x12] |= 0x02;
217 		else
218 			vga->sequencer[0x12] |= 0x03;
219 		l = vga->vmb>>16;
220 		vga->sequencer[0x13] = l & 0xFF;
221 		vga->sequencer[0x14] = (l>>8) & 0xFF;
222 	}
223 
224 	vgaxo(Seqx, 0x10, vga->sequencer[0x10]);
225 	vgaxo(Seqx, 0x12, vga->sequencer[0x12]);
226 	vgaxo(Seqx, 0x13, vga->sequencer[0x13]);
227 	vgaxo(Seqx, 0x14, vga->sequencer[0x14]);
228 	vgaxo(Seqx, 0x15, vga->sequencer[0x15]);
229 	vgaxo(Seqx, 0x16, vga->sequencer[0x16]);
230 	vgaxo(Seqx, 0x17, vga->sequencer[0x17]);
231 	vgaxo(Seqx, 0x18, vga->sequencer[0x18]);
232 
233 	vgaxo(Crtx, 0x40, vga->crt[0x40]);
234 	vgaxo(Crtx, 0x41, vga->crt[0x41]);
235 	vgaxo(Crtx, 0x42, vga->crt[0x42]);
236 	vgaxo(Crtx, 0x44, vga->crt[0x44]);
237 	vgaxo(Crtx, 0x45, vga->crt[0x45]);
238 	vgaxo(Crtx, 0x46, vga->crt[0x46]);
239 
240 	ctlr->flag |= Fload;
241 }
242 
243 static void
dump(Vga * vga,Ctlr * ctlr)244 dump(Vga* vga, Ctlr* ctlr)
245 {
246 	int i;
247 
248 	printitem(ctlr->name, "Seq10");
249 	for(i = 0x10; i < 0x2E; i++)
250 		printreg(vga->sequencer[i]);
251 	printitem(ctlr->name, "Crt40");
252 	for(i = 0x40; i < 0x47; i++)
253 		printreg(vga->crt[i]);
254 	printitem(ctlr->name, "Crt50");
255 	printreg(vga->crt[0x50]);
256 	printitem(ctlr->name, "Cop status");
257 	printreg(vga->crt[0xFF]);
258 }
259 
260 Ctlr ark2000pv = {
261 	"ark2000pv",			/* name */
262 	snarf,				/* snarf */
263 	options,			/* options */
264 	init,				/* init */
265 	load,				/* load */
266 	dump,				/* dump */
267 };
268 
269 Ctlr ark2000pvhwgc = {
270 	"ark2000pvhwgc",		/* name */
271 	0,				/* snarf */
272 	0,				/* options */
273 	0,				/* init */
274 	0,				/* load */
275 	0,				/* dump */
276 };
277