9 * ATI Mach32. Some hope.
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 Advfunc = 0x4AE8, /* Advanced Function Control Register */
20 Clocksel = 0x4AEE, /* Clock Select Register */
21 Misc = 0x36EE, /* Miscellaneous Register */
22 Membndry = 0x42EE, /* Memory Boundary Register */
23 Memcfg = 0x5EEE, /* Memory Control Register */
35 * There are a number of possible clock generator chips for these
36 * boards, and I don't know how to find out which is installed, other
37 * than by looking at the board. So, pick a subset that will work for
42 uchar b8; /* <6> - divide by 2 */
43 uchar b9; /* <1> - bit <3> of frequency index */
44 uchar be; /* <4> - bit <2> of frequency index */
45 uchar misc; /* <3:2> - bits <1:0> of frequency index */
48 static Clock clocks[] = {
49 { VgaFreq0, 0x40, 0x02, 0x00, 0x00, },
50 { 32000000, 0x00, 0x00, 0x10, 0x04, },
51 { 40000000, 0x00, 0x02, 0x10, 0x00, },
52 { 44900000, 0x00, 0x02, 0x00, 0x0C, },
53 { 65000000, 0x00, 0x02, 0x10, 0x0C, },
54 { 75000000, 0x00, 0x02, 0x10, 0x08, },
63 outportb(atix, index);
64 return inportb(atix+1);
68 atixo(uchar index, uchar data)
70 outportw(atix, (data<<8)|index);
74 atixinit(Vga* vga, Ctlr*)
80 * We could try to read in a part of the BIOS and try to determine
81 * the extended register address, but since we can't determine the offset value,
82 * we'll just have to assume the defaults all round.
87 * Unlock the ATI Extended Registers.
88 * We leave them unlocked from now on.
89 * Why does this chip have so many
92 if((b = atixi(0xB8)) & 0x3F)
93 atixo(0xB8, b & 0xC0);
95 atixo(0xAB, b & ~0x18);
98 atixo(0xB9, b & ~0x80);
102 if(vga->private == 0)
103 vga->private = alloc(sizeof(mach32));
107 snarf(Vga* vga, Ctlr* ctlr)
113 for(i = 0xA0; i < 0xC0; i++)
114 vga->crt[i] = atixi(i);
116 mach32 = vga->private;
117 mach32->advfunc = inportw(Advfunc);
118 mach32->clocksel = inportw(Clocksel);
119 mach32->misc = inportw(Misc);
120 mach32->membndry = inportw(Membndry);
121 mach32->memcfg = inportw(Memcfg);
126 switch((mach32->misc>>2) & 0x03){
133 vga->vmz = 1024*1024;
137 vga->vmz = 2*1024*1024;
141 vga->vmz = 4*1024*1024;
145 ctlr->flag |= Fsnarf;
149 options(Vga*, Ctlr* ctlr)
151 ctlr->flag |= Foptions;
155 init(Vga* vga, Ctlr* ctlr)
163 vga->f[0] = vga->mode->frequency;
164 for(clockp = clocks; clockp->frequency; clockp++){
165 if(clockp->frequency > vga->f[0]+100000)
167 if(clockp->frequency > vga->f[0]-100000)
170 if(clockp->frequency == 0)
171 error("%s: no suitable clock for %lud\n",
172 ctlr->name, vga->f[0]);
174 vga->crt[0xB0] &= 0xDA;
175 vga->crt[0xB1] &= 0x87;
176 vga->crt[0xB5] &= 0x7E;
177 vga->crt[0xB6] &= 0xE2;
178 vga->crt[0xB3] &= 0xAF;
179 vga->crt[0xA6] &= 0xFE;
180 vga->crt[0xA7] &= 0xF4;
183 * 256-colour linear addressing.
186 vga->graphics[0x05] = 0x00;
187 vga->attribute[0x10] &= ~0x40;
188 vga->crt[0x13] = (mode->x/8)/2;
189 vga->crt[0x14] = 0x00;
190 vga->crt[0x17] = 0xE3;
192 vga->crt[0xB0] |= 0x20;
193 vga->crt[0xB6] |= 0x04;
195 vga->attribute[0x11] = 0x00;
196 vga->crt[0xB6] |= 0x01;
197 vga->crt[0xBE] &= ~0x04;
200 * Do the clock index bits.
202 vga->crt[0xB9] &= 0xFD;
203 vga->crt[0xB8] &= 0x3F;
204 vga->crt[0xBE] &= 0xE5;
206 vga->crt[0xB8] |= clockp->b8;
207 vga->crt[0xB9] |= clockp->b9;
208 vga->crt[0xBE] |= clockp->be;
209 vga->misc |= clockp->misc;
211 if(vga->mode->interlace == 'v')
212 vga->crt[0xBE] |= 0x02;
215 * Turn off 128Kb CPU address bit so
216 * we only have a 64Kb aperture at 0xA0000.
218 vga->crt[0xBD] &= ~0x04;
224 load(Vga* vga, Ctlr* ctlr)
229 * Make sure we are in VGA mode,
230 * and that we have access to all the video memory through
231 * the 64Kb VGA aperture by disabling and linear aperture
232 * and memory boundary.
234 outportw(Clocksel, 0x0000);
235 x = inportw(Memcfg) & ~0x0003;
237 outportw(Membndry, 0x0000);
239 atixo(0xB0, vga->crt[0xB0]);
240 atixo(0xB1, vga->crt[0xB1]);
241 atixo(0xB5, vga->crt[0xB5]);
242 atixo(0xB6, vga->crt[0xB6]);
243 atixo(0xB3, vga->crt[0xB3]);
244 atixo(0xA6, vga->crt[0xA6]);
245 atixo(0xA7, vga->crt[0xA7]);
246 atixo(0xB8, vga->crt[0xB8]);
247 atixo(0xB9, vga->crt[0xB9]);
248 atixo(0xBE, vga->crt[0xBE]);
249 vgao(MiscW, vga->misc);
255 dump(Vga* vga, Ctlr* ctlr)
260 printitem(ctlr->name, "ATIX");
261 for(i = 0xA0; i < 0xC0; i++)
262 printreg(vga->crt[i]);
264 if((mach32 = vga->private) == 0)
267 printitem(ctlr->name, "ADVFUNC");
268 Bprint(&stdout, "%.4ux\n", mach32->advfunc);
269 printitem(ctlr->name, "CLOCKSEL");
270 Bprint(&stdout, "%.4ux\n", mach32->clocksel);
271 printitem(ctlr->name, "MISC");
272 Bprint(&stdout, "%.4ux\n", mach32->misc);
273 printitem(ctlr->name, "MEMBNDRY");
274 Bprint(&stdout, "%.4ux\n", mach32->membndry);
275 printitem(ctlr->name, "MEMCFG");
276 Bprint(&stdout, "%.4ux\n", mach32->memcfg);
282 options, /* options */