17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier
5*9a747e4fSDavid du Colombier #include "pci.h"
67dd7cddfSDavid du Colombier #include "vga.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier /*
97dd7cddfSDavid du Colombier * ARK Logic ARK2000PV GUI accelerator.
107dd7cddfSDavid du Colombier */
117dd7cddfSDavid du Colombier static void
snarf(Vga * vga,Ctlr * ctlr)127dd7cddfSDavid du Colombier snarf(Vga* vga, Ctlr* ctlr)
137dd7cddfSDavid du Colombier {
147dd7cddfSDavid du Colombier int i;
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier /*
177dd7cddfSDavid du Colombier * Unlock access to the extended I/O registers.
187dd7cddfSDavid du Colombier */
197dd7cddfSDavid du Colombier vgaxo(Seqx, 0x1D, 0x01);
207dd7cddfSDavid du Colombier
217dd7cddfSDavid du Colombier for(i = 0x10; i < 0x2E; i++)
227dd7cddfSDavid du Colombier vga->sequencer[i] = vgaxi(Seqx, i);
237dd7cddfSDavid du Colombier for(i = 0x40; i < 0x47; i++)
247dd7cddfSDavid du Colombier vga->crt[i] = vgaxi(Crtx, i);
257dd7cddfSDavid du Colombier vga->crt[0x50] = vgaxi(Crtx, 0x50);
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier /*
287dd7cddfSDavid du Colombier * A hidey-hole for the coprocessor status register.
297dd7cddfSDavid du Colombier */
307dd7cddfSDavid du Colombier vga->crt[0xFF] = inportb(0x3CB);
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier /*
337dd7cddfSDavid du Colombier * Memory size.
347dd7cddfSDavid du Colombier */
357dd7cddfSDavid du Colombier switch((vga->sequencer[0x10]>>6) & 0x03){
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier case 0x00:
387dd7cddfSDavid du Colombier vga->vma = vga->vmz = 1*1024*1024;
397dd7cddfSDavid du Colombier break;
407dd7cddfSDavid du Colombier
417dd7cddfSDavid du Colombier case 0x01:
427dd7cddfSDavid du Colombier vga->vma = vga->vmz = 2*1024*1024;
437dd7cddfSDavid du Colombier break;
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier case 0x02:
467dd7cddfSDavid du Colombier vga->vma = vga->vmz = 4*1024*1024;
477dd7cddfSDavid du Colombier break;
487dd7cddfSDavid du Colombier }
497dd7cddfSDavid du Colombier
507dd7cddfSDavid du Colombier ctlr->flag |= Fsnarf;
517dd7cddfSDavid du Colombier }
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier static void
options(Vga *,Ctlr * ctlr)547dd7cddfSDavid du Colombier options(Vga*, Ctlr* ctlr)
557dd7cddfSDavid du Colombier {
567dd7cddfSDavid du Colombier ctlr->flag |= Hlinear|Hpclk2x8|Foptions;
577dd7cddfSDavid du Colombier }
587dd7cddfSDavid du Colombier
597dd7cddfSDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)607dd7cddfSDavid du Colombier init(Vga* vga, Ctlr* ctlr)
617dd7cddfSDavid du Colombier {
627dd7cddfSDavid du Colombier Mode *mode;
637dd7cddfSDavid du Colombier ulong x;
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier mode = vga->mode;
667dd7cddfSDavid du Colombier
677dd7cddfSDavid du Colombier vga->crt[0x46] = 0x00;
687dd7cddfSDavid du Colombier if(ctlr->flag & Upclk2x8){
697dd7cddfSDavid du Colombier vga->crt[0x00] = ((mode->ht/2)>>3)-5;
707dd7cddfSDavid du Colombier vga->crt[0x01] = ((mode->x/2)>>3)-1;
717dd7cddfSDavid du Colombier vga->crt[0x02] = ((mode->shb/2)>>3)-1;
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier x = (mode->ehb/2)>>3;
747dd7cddfSDavid du Colombier vga->crt[0x03] = 0x80|(x & 0x1F);
757dd7cddfSDavid du Colombier vga->crt[0x04] = (mode->shs/2)>>3;
767dd7cddfSDavid du Colombier vga->crt[0x05] = ((mode->ehs/2)>>3) & 0x1F;
777dd7cddfSDavid du Colombier if(x & 0x20)
787dd7cddfSDavid du Colombier vga->crt[0x05] |= 0x80;
797dd7cddfSDavid du Colombier vga->crt[0x13] = mode->x/8;
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier vga->crt[0x46] |= 0x04;
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier /*
857dd7cddfSDavid du Colombier * Overflow bits.
867dd7cddfSDavid du Colombier */
877dd7cddfSDavid du Colombier vga->crt[0x40] = 0x00;
887dd7cddfSDavid du Colombier if(vga->crt[0x18] & 0x400)
897dd7cddfSDavid du Colombier vga->crt[0x40] |= 0x08;
907dd7cddfSDavid du Colombier if(vga->crt[0x10] & 0x400)
917dd7cddfSDavid du Colombier vga->crt[0x40] |= 0x10;
927dd7cddfSDavid du Colombier if(vga->crt[0x15] & 0x400)
937dd7cddfSDavid du Colombier vga->crt[0x40] |= 0x20;
947dd7cddfSDavid du Colombier if(vga->crt[0x12] & 0x400)
957dd7cddfSDavid du Colombier vga->crt[0x40] |= 0x40;
967dd7cddfSDavid du Colombier if(vga->crt[0x06] & 0x400)
977dd7cddfSDavid du Colombier vga->crt[0x40] |= 0x80;
987dd7cddfSDavid du Colombier
997dd7cddfSDavid du Colombier vga->crt[0x41] = 0x00;
1007dd7cddfSDavid du Colombier if(vga->crt[0x13] & 0x100)
1017dd7cddfSDavid du Colombier vga->crt[0x41] |= 0x08;
1027dd7cddfSDavid du Colombier if(vga->crt[0x04] & 0x100)
1037dd7cddfSDavid du Colombier vga->crt[0x41] |= 0x10;
1047dd7cddfSDavid du Colombier if(vga->crt[0x02] & 0x100)
1057dd7cddfSDavid du Colombier vga->crt[0x41] |= 0x20;
1067dd7cddfSDavid du Colombier if(vga->crt[0x01] & 0x100)
1077dd7cddfSDavid du Colombier vga->crt[0x41] |= 0x40;
1087dd7cddfSDavid du Colombier if(vga->crt[0x00] & 0x100)
1097dd7cddfSDavid du Colombier vga->crt[0x41] |= 0x80;
1107dd7cddfSDavid du Colombier
1117dd7cddfSDavid du Colombier /*
1127dd7cddfSDavid du Colombier * Interlace.
1137dd7cddfSDavid du Colombier */
1147dd7cddfSDavid du Colombier vga->crt[0x42] = 0x00;
1157dd7cddfSDavid du Colombier vga->crt[0x44] = 0x00;
1167dd7cddfSDavid du Colombier if(mode->interlace){
1177dd7cddfSDavid du Colombier vga->crt[0x42] = vga->crt[0]/2;
1187dd7cddfSDavid du Colombier vga->crt[0x44] |= 0x04;
1197dd7cddfSDavid du Colombier }
1207dd7cddfSDavid du Colombier vga->crt[0x45] = 0x00;
1217dd7cddfSDavid du Colombier
1227dd7cddfSDavid du Colombier /*
1237dd7cddfSDavid du Colombier * Memory configuration:
1247dd7cddfSDavid du Colombier * enable linear|coprocessor|VESA modes;
1257dd7cddfSDavid du Colombier * set aperture to 64Kb, 0xA0000;
1267dd7cddfSDavid du Colombier * set aperture index 0.
1277dd7cddfSDavid du Colombier * Bugs: 1024x768x1 doesn't work (aperture not set correctly?);
1287dd7cddfSDavid du Colombier * hwgc doesn't work in 1-bit modes (hardware?).
1297dd7cddfSDavid du Colombier */
1307dd7cddfSDavid du Colombier vga->sequencer[0x10] &= ~0x3F;
1317dd7cddfSDavid du Colombier vga->sequencer[0x11] &= ~0x0F;
1327dd7cddfSDavid du Colombier switch(mode->z){
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier case 1:
1357dd7cddfSDavid du Colombier vga->sequencer[0x10] |= 0x03;
1367dd7cddfSDavid du Colombier vga->sequencer[0x11] |= 0x01;
1377dd7cddfSDavid du Colombier cflag = 1;
1387dd7cddfSDavid du Colombier break;
1397dd7cddfSDavid du Colombier
1407dd7cddfSDavid du Colombier case 8:
1417dd7cddfSDavid du Colombier vga->sequencer[0x10] |= 0x0F;
1427dd7cddfSDavid du Colombier vga->sequencer[0x11] |= 0x06;
1437dd7cddfSDavid du Colombier if(vga->linear && (ctlr->flag & Hlinear) && vga->vmz)
1447dd7cddfSDavid du Colombier ctlr->flag |= Ulinear;
1457dd7cddfSDavid du Colombier break;
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier default:
1487dd7cddfSDavid du Colombier error("depth %d not supported\n", mode->z);
1497dd7cddfSDavid du Colombier }
1507dd7cddfSDavid du Colombier vga->sequencer[0x12] &= ~0x03;
1517dd7cddfSDavid du Colombier vga->sequencer[0x13] = 0x0A;
1527dd7cddfSDavid du Colombier vga->sequencer[0x14] = 0x00;
1537dd7cddfSDavid du Colombier vga->sequencer[0x15] = 0x00;
1547dd7cddfSDavid du Colombier vga->sequencer[0x16] = 0x00;
1557dd7cddfSDavid du Colombier
1567dd7cddfSDavid du Colombier /*
1577dd7cddfSDavid du Colombier * Frame Buffer Pitch and FIFO control.
1587dd7cddfSDavid du Colombier * Set the FIFO to 32 deep and refill trigger when
1597dd7cddfSDavid du Colombier * 6 slots empty.
1607dd7cddfSDavid du Colombier */
1617dd7cddfSDavid du Colombier vga->sequencer[0x17] = 0x00;
1627dd7cddfSDavid du Colombier vga->sequencer[0x18] = 0x13;
1637dd7cddfSDavid du Colombier if(mode->x <= 640)
1647dd7cddfSDavid du Colombier vga->sequencer[0x17] = 0x00;
1657dd7cddfSDavid du Colombier else if(mode->x <= 800)
1667dd7cddfSDavid du Colombier vga->sequencer[0x17] |= 0x01;
1677dd7cddfSDavid du Colombier else if(mode->x <= 1024)
1687dd7cddfSDavid du Colombier vga->sequencer[0x17] |= 0x02;
1697dd7cddfSDavid du Colombier else if(mode->x <= 1280)
1707dd7cddfSDavid du Colombier vga->sequencer[0x17] |= 0x04;
1717dd7cddfSDavid du Colombier else if(mode->x <= 1600)
1727dd7cddfSDavid du Colombier vga->sequencer[0x17] |= 0x05;
1737dd7cddfSDavid du Colombier else if(mode->x <= 2048)
1747dd7cddfSDavid du Colombier vga->sequencer[0x17] |= 0x06;
1757dd7cddfSDavid du Colombier
1767dd7cddfSDavid du Colombier /*
1777dd7cddfSDavid du Colombier * Clock select.
1787dd7cddfSDavid du Colombier */
1797dd7cddfSDavid du Colombier vga->misc &= ~0x0C;
1807dd7cddfSDavid du Colombier vga->misc |= (vga->i[0] & 0x03)<<2;
1817dd7cddfSDavid du Colombier vga->sequencer[0x11] &= ~0xC0;
1827dd7cddfSDavid du Colombier vga->sequencer[0x11] |= (vga->i[0] & 0x0C)<<4;
1837dd7cddfSDavid du Colombier
1847dd7cddfSDavid du Colombier vga->attribute[0x11] = 0x00; /* color map entry for black */
1857dd7cddfSDavid du Colombier
1867dd7cddfSDavid du Colombier ctlr->flag |= Finit;
1877dd7cddfSDavid du Colombier }
1887dd7cddfSDavid du Colombier
1897dd7cddfSDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)1907dd7cddfSDavid du Colombier load(Vga* vga, Ctlr* ctlr)
1917dd7cddfSDavid du Colombier {
1927dd7cddfSDavid du Colombier ulong l;
1937dd7cddfSDavid du Colombier
1947dd7cddfSDavid du Colombier /*
1957dd7cddfSDavid du Colombier * Ensure there are no glitches when selecting a new
1967dd7cddfSDavid du Colombier * clock frequency.
1977dd7cddfSDavid du Colombier * The sequencer toggle seems to matter on the Hercules
1987dd7cddfSDavid du Colombier * Stingray 64/Video at 1280x1024x8. Without it the screen
1997dd7cddfSDavid du Colombier * is fuzzy; a second load clears it up and there's no
2007dd7cddfSDavid du Colombier * difference between the two register sets. A mystery.
2017dd7cddfSDavid du Colombier */
2027dd7cddfSDavid du Colombier vgao(MiscW, vga->misc & ~0x0C);
2037dd7cddfSDavid du Colombier vgaxo(Seqx, 0x11, vga->sequencer[0x11]);
2047dd7cddfSDavid du Colombier vgao(MiscW, vga->misc);
2057dd7cddfSDavid du Colombier if(vga->ramdac && strncmp(vga->ramdac->name, "w30c516", 7) == 0){
2067dd7cddfSDavid du Colombier sequencer(vga, 1);
2077dd7cddfSDavid du Colombier sleep(500);
2087dd7cddfSDavid du Colombier sequencer(vga, 0);
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier
2117dd7cddfSDavid du Colombier if(ctlr->flag & Ulinear){
2127dd7cddfSDavid du Colombier vga->sequencer[0x10] |= 0x10;
2137dd7cddfSDavid du Colombier if(vga->vmz <= 1024*1024)
2147dd7cddfSDavid du Colombier vga->sequencer[0x12] |= 0x01;
2157dd7cddfSDavid du Colombier else if(vga->vmz <= 2*1024*1024)
2167dd7cddfSDavid du Colombier vga->sequencer[0x12] |= 0x02;
2177dd7cddfSDavid du Colombier else
2187dd7cddfSDavid du Colombier vga->sequencer[0x12] |= 0x03;
2197dd7cddfSDavid du Colombier l = vga->vmb>>16;
2207dd7cddfSDavid du Colombier vga->sequencer[0x13] = l & 0xFF;
2217dd7cddfSDavid du Colombier vga->sequencer[0x14] = (l>>8) & 0xFF;
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier
2247dd7cddfSDavid du Colombier vgaxo(Seqx, 0x10, vga->sequencer[0x10]);
2257dd7cddfSDavid du Colombier vgaxo(Seqx, 0x12, vga->sequencer[0x12]);
2267dd7cddfSDavid du Colombier vgaxo(Seqx, 0x13, vga->sequencer[0x13]);
2277dd7cddfSDavid du Colombier vgaxo(Seqx, 0x14, vga->sequencer[0x14]);
2287dd7cddfSDavid du Colombier vgaxo(Seqx, 0x15, vga->sequencer[0x15]);
2297dd7cddfSDavid du Colombier vgaxo(Seqx, 0x16, vga->sequencer[0x16]);
2307dd7cddfSDavid du Colombier vgaxo(Seqx, 0x17, vga->sequencer[0x17]);
2317dd7cddfSDavid du Colombier vgaxo(Seqx, 0x18, vga->sequencer[0x18]);
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier vgaxo(Crtx, 0x40, vga->crt[0x40]);
2347dd7cddfSDavid du Colombier vgaxo(Crtx, 0x41, vga->crt[0x41]);
2357dd7cddfSDavid du Colombier vgaxo(Crtx, 0x42, vga->crt[0x42]);
2367dd7cddfSDavid du Colombier vgaxo(Crtx, 0x44, vga->crt[0x44]);
2377dd7cddfSDavid du Colombier vgaxo(Crtx, 0x45, vga->crt[0x45]);
2387dd7cddfSDavid du Colombier vgaxo(Crtx, 0x46, vga->crt[0x46]);
2397dd7cddfSDavid du Colombier
2407dd7cddfSDavid du Colombier ctlr->flag |= Fload;
2417dd7cddfSDavid du Colombier }
2427dd7cddfSDavid du Colombier
2437dd7cddfSDavid du Colombier static void
dump(Vga * vga,Ctlr * ctlr)2447dd7cddfSDavid du Colombier dump(Vga* vga, Ctlr* ctlr)
2457dd7cddfSDavid du Colombier {
2467dd7cddfSDavid du Colombier int i;
2477dd7cddfSDavid du Colombier
2487dd7cddfSDavid du Colombier printitem(ctlr->name, "Seq10");
2497dd7cddfSDavid du Colombier for(i = 0x10; i < 0x2E; i++)
2507dd7cddfSDavid du Colombier printreg(vga->sequencer[i]);
2517dd7cddfSDavid du Colombier printitem(ctlr->name, "Crt40");
2527dd7cddfSDavid du Colombier for(i = 0x40; i < 0x47; i++)
2537dd7cddfSDavid du Colombier printreg(vga->crt[i]);
2547dd7cddfSDavid du Colombier printitem(ctlr->name, "Crt50");
2557dd7cddfSDavid du Colombier printreg(vga->crt[0x50]);
2567dd7cddfSDavid du Colombier printitem(ctlr->name, "Cop status");
2577dd7cddfSDavid du Colombier printreg(vga->crt[0xFF]);
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier
2607dd7cddfSDavid du Colombier Ctlr ark2000pv = {
2617dd7cddfSDavid du Colombier "ark2000pv", /* name */
2627dd7cddfSDavid du Colombier snarf, /* snarf */
2637dd7cddfSDavid du Colombier options, /* options */
2647dd7cddfSDavid du Colombier init, /* init */
2657dd7cddfSDavid du Colombier load, /* load */
2667dd7cddfSDavid du Colombier dump, /* dump */
2677dd7cddfSDavid du Colombier };
2687dd7cddfSDavid du Colombier
2697dd7cddfSDavid du Colombier Ctlr ark2000pvhwgc = {
2707dd7cddfSDavid du Colombier "ark2000pvhwgc", /* name */
2717dd7cddfSDavid du Colombier 0, /* snarf */
2727dd7cddfSDavid du Colombier 0, /* options */
2737dd7cddfSDavid du Colombier 0, /* init */
2747dd7cddfSDavid du Colombier 0, /* load */
2757dd7cddfSDavid du Colombier 0, /* dump */
2767dd7cddfSDavid du Colombier };
277