20 vidScreenSize = 0x098/4,
21 vidDesktopOverlayStride = 0x0E8/4,
34 io32r(Tdfx* tdfx, int r)
36 return inportl(tdfx->io+(r*4));
40 io32w(Tdfx* tdfx, int r, ulong l)
42 outportl(tdfx->io+(r*4), l);
46 snarf(Vga* vga, Ctlr* ctlr)
52 if(vga->private == nil){
53 tdfx = alloc(sizeof(Tdfx));
56 tdfx->pci = pcimatch(0, 0x121A, 0);
57 if(tdfx->pci == nil || tdfx->pci->vid != 0x121A)
58 error("%s: not found\n", ctlr->name);
59 switch(tdfx->pci->did){
61 error("%s: unknown chip - DID %4.4uX\n",
62 ctlr->name, tdfx->pci->did);
64 case 0x0003: /* Banshee */
65 vga->f[1] = 270000000;
67 case 0x0005: /* Avenger (a.k.a. Voodoo3) */
68 vga->f[1] = 300000000;
70 case 0x0009: /* Voodoo5 */
71 vga->f[1] = 350000000;
75 * Frequency output of PLL's is given by
76 * fout = RefFreq*(n+2)/((m+2)*2^p)
77 * where there are 6 bits for m, 8 bits for n
78 * and 2 bits for p (k).
84 if((v = (tdfx->pci->mem[2].bar & ~0x3)) == 0)
85 error("%s: I/O not mapped\n", ctlr->name);
92 vga->crt[0x1A] = vgaxi(Crtx, 0x1A);
93 vga->crt[0x1B] = vgaxi(Crtx, 0x1B);
94 for(i = 0; i < Nior; i++)
95 tdfx->r[i] = io32r(tdfx, i);
98 * If SDRAM then there's 16MB memory else it's SGRAM
99 * and can count it based on the power-on straps -
100 * chip size can be 8Mb or 16Mb, and there can be 4 or
103 vga->vma = tdfx->pci->mem[1].size;
104 if(tdfx->r[dramInit1] & 0x40000000)
105 vga->vmz = 16*1024*1024;
107 if(tdfx->r[dramInit0] & 0x08000000)
111 if(tdfx->r[dramInit0] & 0x04000000)
118 ctlr->flag |= Fsnarf;
122 options(Vga*, Ctlr* ctlr)
124 ctlr->flag |= Hlinear|Hclk2|Foptions;
128 tdfxclock(Vga* vga, Ctlr*)
134 for(m = 1; m < vga->m[1]; m++){
135 for(n = 1; n < vga->n[1]; n++){
136 f = (RefFreq*(n+2))/(m+2);
137 for(p = 0; p < vga->p[1]; p++){
138 d = vga->f[0] - (f/(1<<p));
153 init(Vga* vga, Ctlr* ctlr)
162 if(vga->linear && (ctlr->flag & Hlinear))
163 ctlr->flag |= Ulinear;
166 * Clock bits. If the desired video clock is
167 * one of the two standard VGA clocks or 50MHz it can just be
168 * set using bits <3:2> of vga->misc, otherwise we
169 * need to programme the PLL.
172 vga->f[0] = mode->frequency;
174 if(vga->f[0] == VgaFreq0){
177 else if(vga->f[0] == VgaFreq1)
179 else if(vga->f[0] == 50000000)
182 if(vga->f[0] > vga->f[1])
183 error("%s: invalid pclk - %lud\n",
184 ctlr->name, vga->f[0]);
185 if(vga->f[0] > 135000000 && (ctlr->flag & Hclk2)){
187 error("%s: f > 135MHz requires (x%%16) == 0\n",
191 tdfxclock(vga, ctlr);
193 tdfx->r[pllCtrl0] = (vga->n[0]<<8)|(vga->m[0]<<2)|vga->p[0];
198 * Pixel format and memory stride.
200 tdfx->r[vidScreenSize] = (mode->y<<12)|mode->x;
201 tdfx->r[vidProcCfg] = 0x00000081;
204 error("%s: %d-bit mode not supported\n", ctlr->name, mode->z);
207 tdfx->r[vidDesktopOverlayStride] = mode->x;
210 tdfx->r[vidDesktopOverlayStride] = mode->x*2;
211 tdfx->r[vidProcCfg] |= 0x00040400;
214 tdfx->r[vidDesktopOverlayStride] = mode->x*4;
215 tdfx->r[vidProcCfg] |= 0x000C0400;
218 tdfx->r[vgaInit0] = 0x140;
221 * Adjust horizontal timing if doing two screen pixels per clock.
223 tdfx->r[dacMode] = 0;
224 if(ctlr->flag & Uclk2){
225 vga->crt[0x00] = ((mode->ht/2)>>3)-5;
226 vga->crt[0x01] = ((mode->x/2)>>3)-1;
227 vga->crt[0x02] = ((mode->shb/2)>>3)-1;
229 x = (mode->ehb/2)>>3;
230 vga->crt[0x03] = 0x80|(x & 0x1F);
231 vga->crt[0x04] = (mode->shs/2)>>3;
232 vga->crt[0x05] = ((mode->ehs/2)>>3) & 0x1F;
234 vga->crt[0x05] |= 0x80;
236 tdfx->r[dacMode] |= 0x01;
237 tdfx->r[vidProcCfg] |= 0x04000000;
243 vga->crt[0x1A] = 0x00;
244 if(vga->crt[0x00] & 0x100)
245 vga->crt[0x1A] |= 0x01;
246 if(vga->crt[0x01] & 0x100)
247 vga->crt[0x1A] |= 0x04;
248 if(vga->crt[0x03] & 0x100)
249 vga->crt[0x1A] |= 0x10;
251 if(ctlr->flag & Uclk2)
254 vga->crt[0x1A] |= 0x20;
255 if(vga->crt[0x04] & 0x100)
256 vga->crt[0x1A] |= 0x40;
258 if(ctlr->flag & Uclk2)
261 vga->crt[0x1A] |= 0x80;
263 vga->crt[0x1B] = 0x00;
264 if(vga->crt[0x06] & 0x400)
265 vga->crt[0x1B] |= 0x01;
266 if(vga->crt[0x12] & 0x400)
267 vga->crt[0x1B] |= 0x04;
268 if(vga->crt[0x15] & 0x400)
269 vga->crt[0x1B] |= 0x10;
270 if(vga->crt[0x10] & 0x400)
271 vga->crt[0x1B] |= 0x40;
273 vga->attribute[0x11] = Pblack;
279 load(Vga* vga, Ctlr* ctlr)
283 vgaxo(Crtx, 0x1A, vga->crt[0x1A]);
284 vgaxo(Crtx, 0x1B, vga->crt[0x1B]);
287 io32w(tdfx, dacMode, tdfx->r[dacMode]);
288 io32w(tdfx, vidScreenSize, tdfx->r[vidScreenSize]);
289 io32w(tdfx, vidDesktopOverlayStride, tdfx->r[vidDesktopOverlayStride]);
290 io32w(tdfx, vidProcCfg, tdfx->r[vidProcCfg]);
291 io32w(tdfx, vgaInit0, tdfx->r[vgaInit0]);
293 if((vga->misc & 0x0C) == 0x0C)
294 io32w(tdfx, pllCtrl0, tdfx->r[pllCtrl0]);
300 pllctrl(Tdfx* tdfx, int pll)
304 r = tdfx->r[pllCtrl0+pll];
309 return (RefFreq*(n+2))/((m+2)*(1<<k));
313 dump(Vga* vga, Ctlr* ctlr)
318 if((tdfx = vga->private) == nil)
321 printitem(ctlr->name, "Crt1A");
322 printreg(vga->crt[0x1A]);
323 printreg(vga->crt[0x1B]);
325 Bprint(&stdout, "\n");
326 for(i = 0; i < Nior; i++)
327 Bprint(&stdout, "%s %2.2uX\t%.8luX\n",
328 ctlr->name, i*4, tdfx->r[i]);
330 printitem(ctlr->name, "pllCtrl");
331 Bprint(&stdout, "%9ud %8ud\n", pllctrl(tdfx, 0), pllctrl(tdfx, 1));
337 options, /* options */
344 "3dfxhwgc", /* name */