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
ctxi(uchar index)47 ctxi(uchar index)
48 {
49 outportb(X, index);
50 return inportb(D);
51 }
52
53 static void
ctxo(uchar index,uchar data)54 ctxo(uchar index, uchar data)
55 {
56 outportb(X, index);
57 outportb(D, data);
58 }
59
60 /*
61 * ct65540.
62 */
63 static void
snarf(Vga *,Ctlr * ctlr)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
options(Vga *,Ctlr * ctlr)77 options(Vga*, Ctlr* ctlr)
78 {
79 ctlr->flag |= Hlinear|Foptions;
80 }
81
82 /*
83 * brute force and ignorance
84 */
85 static int
setclock(Vga * vga)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
init(Vga * vga,Ctlr * ctlr)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
load(Vga * vga,Ctlr * ctlr)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
dump(Vga *,Ctlr * ctlr)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 };
274