9 * ATI Mach64. Some hope. Kind of like a Mach32.
10 * No support for accelerator so can only do up to 1024x768.
12 * All ATI Extended Registers are addressed using the modified index
13 * index = (0x02<<6)|(index & 0x3F);
14 * so registers 0x00->0x3F map to 0x80->0xBF, but we will only ever
15 * look at a few in the range 0xA0->0xBF. In this way we can stash
16 * them in the vga->crt[] array.
19 Configcntl = 0x6AEC, /* Configuration control */
20 Configstat = 0x72EC, /* Configuration status */
21 Memcntl = 0x52EC, /* Memory control */
22 Scratch1 = 0x46EC, /* Scratch Register (BIOS info) */
33 * There are a number of possible clock generator chips for these
34 * boards. We can divide any frequency by 2 (bit<6> of b8).
38 uchar be; /* <4> - bit<3> of frequency index */
39 uchar b9; /* <1> - bit<2> of frequency index */
40 uchar genmo; /* <3:2> - bits <1:0> of frequency index */
44 Npclkx = 16, /* number of clock entries per table */
50 static Pclk ati188110[Npclkx] = {
51 { 42950000, 0x00, 0x00, 0x00 },
52 { 48770000, 0x00, 0x00, 0x04 },
53 { 92400000, 0x00, 0x00, 0x08 },
54 { 36000000, 0x00, 0x00, 0x0C },
55 { 50350000, 0x00, 0x02, 0x00 },
56 { 56640000, 0x00, 0x02, 0x04 },
57 { 0, 0x00, 0x02, 0x08 },
58 { 44900000, 0x00, 0x02, 0x0C },
59 { 30240000, 0x10, 0x00, 0x00 },
60 { 32000000, 0x10, 0x00, 0x04 },
61 { 110000000, 0x10, 0x00, 0x08 },
62 { 80000000, 0x10, 0x00, 0x0C },
63 { 39910000, 0x10, 0x02, 0x00 },
64 { 44900000, 0x10, 0x02, 0x04 },
65 { 75000000, 0x10, 0x02, 0x08 },
66 { 65000000, 0x10, 0x02, 0x0C },
70 * ATI18811-1, ATI18811-2
71 * PCLK_TABLE = 0 in Mach64 speak.
73 static Pclk ati188111[Npclkx] = {
74 { 100000000, 0x00, 0x00, 0x00 },
75 { 126000000, 0x00, 0x00, 0x04 },
76 { 92400000, 0x00, 0x00, 0x08 },
77 { 36000000, 0x00, 0x00, 0x0C },
78 { 50350000, 0x00, 0x02, 0x00 },
79 { 56640000, 0x00, 0x02, 0x04 },
80 { 0, 0x00, 0x02, 0x08 },
81 { 44900000, 0x00, 0x02, 0x0C },
82 { 135000000, 0x10, 0x00, 0x00 },
83 { 32000000, 0x10, 0x00, 0x04 },
84 { 110000000, 0x10, 0x00, 0x08 },
85 { 80000000, 0x10, 0x00, 0x0C },
86 { 39910000, 0x10, 0x02, 0x00 },
87 { 44900000, 0x10, 0x02, 0x04 },
88 { 75000000, 0x10, 0x02, 0x08 },
89 { 65000000, 0x10, 0x02, 0x0C },
94 * The first four entries are programmable and the default
95 * settings are either those below or those below divided by 2
96 * (PCLK_TABLE = 1 and PCLK_TABLE = 2 respectively in Mach64
99 static Pclk ati18818[Npclkx] = {
100 { 50350000, 0x00, 0x00, 0x00 },
101 { 56640000, 0x00, 0x00, 0x04 },
102 { 63000000, 0x00, 0x00, 0x08 },
103 { 72000000, 0x00, 0x00, 0x0C },
104 { 40000000, 0x00, 0x02, 0x00 },
105 { 44900000, 0x00, 0x02, 0x04 },
106 { 49500000, 0x00, 0x02, 0x08 },
107 { 50000000, 0x00, 0x02, 0x0C },
108 { 0, 0x10, 0x00, 0x00 },
109 { 110000000, 0x10, 0x00, 0x04 },
110 { 126000000, 0x10, 0x00, 0x08 },
111 { 135000000, 0x10, 0x00, 0x0C },
112 { 0, 0x10, 0x02, 0x00 },
113 { 80000000, 0x10, 0x02, 0x04 },
114 { 75000000, 0x10, 0x02, 0x08 },
115 { 65000000, 0x10, 0x02, 0x0C },
118 static Pclk *pclkp; /* which clock chip we are using */
119 static ulong atix; /* index to extended regsiters */
124 outportb(atix, index);
125 return inportb(atix+1);
129 atixo(uchar index, uchar data)
131 outportw(atix, (data<<8)|index);
135 atixinit(Vga* vga, Ctlr*)
140 * Set the I/O address and offset for the ATI
141 * extended registers to something we know about.
144 outportw(Grx, (0xCE<<8)|0x50);
145 outportw(Grx, (0x81<<8)|0x51);
150 * Unlock the ATI Extended Registers.
151 * We leave them unlocked from now on.
152 * Why does this chip have so many
155 if((b = atixi(0xB8)) & 0x3F)
156 atixo(0xB8, b & 0xC0);
158 atixo(0xAB, b & ~0x18);
161 atixo(0xB9, b & ~0x80);
165 if(vga->private == 0)
166 vga->private = alloc(sizeof(Mach64));
170 snarf(Vga* vga, Ctlr* ctlr)
176 for(i = 0xA0; i < 0xC0; i++)
177 vga->crt[i] = atixi(i);
179 mach64 = vga->private;
180 mach64->configcntl = inportl(Configcntl);
181 mach64->configstat = inportl(Configstat);
182 mach64->memcntl = inportl(Memcntl);
183 mach64->scratch1 = inportl(Scratch1);
188 switch(mach64->memcntl & 0x07){
195 vga->vmz = 1024*1024;
199 vga->vmz = 2*1024*1024;
203 vga->vmz = 4*1024*1024;
207 vga->vmz = 6*1024*1024;
211 vga->vmz = 8*1024*1024;
215 ctlr->flag |= Fsnarf;
219 init(Vga* vga, Ctlr* ctlr)
222 int f, divisor, index;
227 * Must somehow determine which clock chip to use here.
228 * For now, punt and assume ATI18818.
232 error("%s: can't determine clock chip\n", ctlr->name);
235 vga->f[0] = vga->mode->frequency;
238 * Find a clock frequency close to what we want.
239 * 'Close' is within 1MHz.
241 for(divisor = 0, index = 0; index < Npclkx; index++, divisor = 0){
243 f = pclkp[index].frequency/divisor;
244 if(f < vga->f[0]+1000000 && f >= vga->f[0]-1000000)
249 if(f < vga->f[0]+1000000 && f >= vga->f[0]-1000000)
253 error("%s: no suitable clock for %lud\n",
254 ctlr->name, vga->f[0]);
259 vga->crt[0xB0] &= 0xDA;
260 vga->crt[0xB1] &= 0x87;
261 vga->crt[0xB5] &= 0x7E;
262 vga->crt[0xB6] &= 0xE2;
263 vga->crt[0xB3] &= 0xAF;
264 vga->crt[0xA6] &= 0xFE;
265 vga->crt[0xA7] &= 0xF4;
268 * 256-colour linear addressing.
271 vga->graphics[0x05] = 0x00;
272 vga->attribute[0x10] &= ~0x40;
273 vga->crt[0x13] = (mode->x/8)/2;
274 vga->crt[0x14] = 0x00;
275 vga->crt[0x17] = 0xE3;
277 vga->crt[0xB0] |= 0x20;
278 vga->crt[0xB6] |= 0x04;
280 vga->attribute[0x11] = 0x00;
281 vga->crt[0xB6] |= 0x01;
282 vga->crt[0xBE] &= ~0x04;
285 * Do the clock index bits.
287 vga->crt[0xB8] &= 0x3F;
288 vga->crt[0xB9] &= 0xFD;
289 vga->crt[0xBE] &= 0xE5;
292 vga->crt[0xB8] |= 0x40;
293 vga->crt[0xB9] |= pclkp[vga->i[0]].b9;
294 vga->crt[0xBE] |= pclkp[vga->i[0]].be;
295 vga->misc |= pclkp[vga->i[0]].genmo;
297 if(vga->mode->interlace == 'v')
298 vga->crt[0xBE] |= 0x02;
301 * Turn off 128Kb CPU address bit so
302 * we only have a 64Kb aperture at 0xA0000.
304 vga->crt[0xBD] &= ~0x04;
306 ctlr->type = mach32.name;
309 * The Mach64 can only address 1Mb in VGA mode
311 vga->vmz = 1*1024*1024;
317 load(Vga* vga, Ctlr* ctlr)
320 * We should probably do something here to make sure we that we
321 * have access to all the video memory through the 64Kb VGA aperture
322 * by disabling and linear aperture and memory boundary and then
323 * enabling the VGA controller.
324 * But for now, let's just assume it's ok, the Mach64 documentation
325 * is just as clear as the Mach32 documentation.
327 atixo(0xB0, vga->crt[0xB0]);
328 atixo(0xB1, vga->crt[0xB1]);
329 atixo(0xB5, vga->crt[0xB5]);
330 atixo(0xB6, vga->crt[0xB6]);
331 atixo(0xB3, vga->crt[0xB3]);
332 atixo(0xA6, vga->crt[0xA6]);
333 atixo(0xA7, vga->crt[0xA7]);
334 atixo(0xB8, vga->crt[0xB8]);
335 atixo(0xB9, vga->crt[0xB9]);
336 atixo(0xBE, vga->crt[0xBE]);
337 vgao(MiscW, vga->misc);
343 dump(Vga* vga, Ctlr* ctlr)
348 printitem(ctlr->name, "ATIX");
349 for(i = 0xA0; i < 0xC0; i++)
350 printreg(vga->crt[i]);
352 if((mach64 = vga->private) == 0)
355 printitem(ctlr->name, "CONFIGCNTL");
356 Bprint(&stdout, "%.8lux\n", mach64->configcntl);
357 printitem(ctlr->name, "CONFIGSTAT");
358 Bprint(&stdout, "%.8lux\n", mach64->configstat);
359 printitem(ctlr->name, "MEMCNTL");
360 Bprint(&stdout, "%.8lux\n", mach64->memcntl);
361 printitem(ctlr->name, "SCRATCH1");
362 Bprint(&stdout, "%.8lux\n", mach64->scratch1);