17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier
59a747e4fSDavid du Colombier #include "pci.h"
67dd7cddfSDavid du Colombier #include "vga.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier /*
97dd7cddfSDavid du Colombier * Trident Cyber938x.
107dd7cddfSDavid du Colombier */
117dd7cddfSDavid du Colombier typedef struct {
127dd7cddfSDavid du Colombier uchar old[3];
139a747e4fSDavid du Colombier int pcr; /* Pixel Command Register */
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier int x;
167dd7cddfSDavid du Colombier int y;
177dd7cddfSDavid du Colombier } Cyber938x;
187dd7cddfSDavid du Colombier
199a747e4fSDavid du Colombier /*
209a747e4fSDavid du Colombier * Access to the DAC Pixel Command Register.
219a747e4fSDavid du Colombier * The access is similar to that used on the old
229a747e4fSDavid du Colombier * SGS-Thompson STG1702 Enhanced True Color Palette-DAC
239a747e4fSDavid du Colombier * and Sierra SC1502[56] HiCOLOR-24 Palette.
249a747e4fSDavid du Colombier */
259a747e4fSDavid du Colombier static void
pcrrw(void)269a747e4fSDavid du Colombier pcrrw(void)
279a747e4fSDavid du Colombier {
289a747e4fSDavid du Colombier int i;
299a747e4fSDavid du Colombier
309a747e4fSDavid du Colombier inportb(PaddrW);
319a747e4fSDavid du Colombier for(i = 0; i < 4; i++)
329a747e4fSDavid du Colombier inportb(Pixmask);
339a747e4fSDavid du Colombier }
349a747e4fSDavid du Colombier
359a747e4fSDavid du Colombier static int
pcrr(void)369a747e4fSDavid du Colombier pcrr(void)
379a747e4fSDavid du Colombier {
389a747e4fSDavid du Colombier int pcr;
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier pcrrw();
419a747e4fSDavid du Colombier pcr = inportb(Pixmask);
429a747e4fSDavid du Colombier inportb(PaddrW);
439a747e4fSDavid du Colombier
449a747e4fSDavid du Colombier return pcr;
459a747e4fSDavid du Colombier }
469a747e4fSDavid du Colombier
479a747e4fSDavid du Colombier static void
pcrw(int pcr)489a747e4fSDavid du Colombier pcrw(int pcr)
499a747e4fSDavid du Colombier {
509a747e4fSDavid du Colombier pcrrw();
519a747e4fSDavid du Colombier outportb(Pixmask, pcr);
529a747e4fSDavid du Colombier inportb(PaddrW);
539a747e4fSDavid du Colombier }
549a747e4fSDavid du Colombier
557dd7cddfSDavid du Colombier static void
snarf(Vga * vga,Ctlr * ctlr)567dd7cddfSDavid du Colombier snarf(Vga* vga, Ctlr* ctlr)
577dd7cddfSDavid du Colombier {
587dd7cddfSDavid du Colombier int i;
597dd7cddfSDavid du Colombier Cyber938x *cyber;
607dd7cddfSDavid du Colombier
617dd7cddfSDavid du Colombier if(vga->private == nil)
627dd7cddfSDavid du Colombier vga->private = alloc(sizeof(Cyber938x));
637dd7cddfSDavid du Colombier cyber = vga->private;
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier /*
667dd7cddfSDavid du Colombier * Switch to old mode (write to Seq0B), read the old
677dd7cddfSDavid du Colombier * mode registers (Seq0[CDE]) then switch to new mode
687dd7cddfSDavid du Colombier * (read Seq0B).
697dd7cddfSDavid du Colombier */
707dd7cddfSDavid du Colombier vgaxo(Seqx, 0x0B, 0);
717dd7cddfSDavid du Colombier cyber->old[0] = vgaxi(Seqx, 0x0C);
727dd7cddfSDavid du Colombier cyber->old[1] = vgaxi(Seqx, 0x0D);
737dd7cddfSDavid du Colombier cyber->old[2] = vgaxi(Seqx, 0x0E);
747dd7cddfSDavid du Colombier vga->sequencer[0x0B] = vgaxi(Seqx, 0x0B);
757dd7cddfSDavid du Colombier
769a747e4fSDavid du Colombier cyber->pcr = pcrr();
779a747e4fSDavid du Colombier
789a747e4fSDavid du Colombier for(i = 0x08; i < 0x20; i++){
797dd7cddfSDavid du Colombier if(i == 0x0B)
807dd7cddfSDavid du Colombier continue;
817dd7cddfSDavid du Colombier vga->sequencer[i] = vgaxi(Seqx, i);
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier for(i = 0x19; i < 0x60; i++)
847dd7cddfSDavid du Colombier vga->crt[i] = vgaxi(Crtx, i);
859a747e4fSDavid du Colombier vga->crt[0xCF] = vgaxi(Crtx, 0xCF);
867dd7cddfSDavid du Colombier for(i = 0x09; i < 0x60; i++)
877dd7cddfSDavid du Colombier vga->graphics[i] = vgaxi(Grx, i);
887dd7cddfSDavid du Colombier
899a747e4fSDavid du Colombier vga->vma = 4*1024*1024;
907dd7cddfSDavid du Colombier switch(vga->crt[0x1F] & 0x07){
919a747e4fSDavid du Colombier case 0:
929a747e4fSDavid du Colombier case 4:
939a747e4fSDavid du Colombier vga->vma = 8*1024*1024;
949a747e4fSDavid du Colombier vga->vmz = 8*1024*1024;
959a747e4fSDavid du Colombier break;
967dd7cddfSDavid du Colombier case 1:
977dd7cddfSDavid du Colombier case 5:
987dd7cddfSDavid du Colombier vga->vmz = 4*1024*1024;
997dd7cddfSDavid du Colombier break;
1007dd7cddfSDavid du Colombier case 2:
1017dd7cddfSDavid du Colombier case 6:
1027dd7cddfSDavid du Colombier vga->vmz = 768*1024;
1037dd7cddfSDavid du Colombier break;
1047dd7cddfSDavid du Colombier case 7:
1057dd7cddfSDavid du Colombier vga->vmz = 2*1024*1024;
1067dd7cddfSDavid du Colombier break;
1077dd7cddfSDavid du Colombier case 3:
1087dd7cddfSDavid du Colombier default:
1097dd7cddfSDavid du Colombier vga->vmz = 1024*1024;
1107dd7cddfSDavid du Colombier break;
1117dd7cddfSDavid du Colombier }
1127dd7cddfSDavid du Colombier
1137dd7cddfSDavid du Colombier switch((vga->graphics[0x52]>>4) & 0x03){
1147dd7cddfSDavid du Colombier case 0:
1157dd7cddfSDavid du Colombier cyber->x = 1280;
1167dd7cddfSDavid du Colombier cyber->y = 1024;
1177dd7cddfSDavid du Colombier break;
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier case 1:
1207dd7cddfSDavid du Colombier cyber->x = 640;
1217dd7cddfSDavid du Colombier cyber->y = 480;
1227dd7cddfSDavid du Colombier break;
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier case 2:
1257dd7cddfSDavid du Colombier cyber->x = 1024;
1267dd7cddfSDavid du Colombier cyber->y = 768;
1277dd7cddfSDavid du Colombier break;
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier case 3:
1307dd7cddfSDavid du Colombier cyber->x = 800;
1317dd7cddfSDavid du Colombier cyber->y = 600;
1327dd7cddfSDavid du Colombier break;
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier
1357dd7cddfSDavid du Colombier ctlr->flag |= Fsnarf;
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier
1387dd7cddfSDavid du Colombier static void
options(Vga * vga,Ctlr * ctlr)1397dd7cddfSDavid du Colombier options(Vga* vga, Ctlr* ctlr)
1407dd7cddfSDavid du Colombier {
1417dd7cddfSDavid du Colombier USED(vga);
1427dd7cddfSDavid du Colombier ctlr->flag |= Hlinear|Foptions;
1437dd7cddfSDavid du Colombier }
1447dd7cddfSDavid du Colombier
1457dd7cddfSDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)1467dd7cddfSDavid du Colombier init(Vga* vga, Ctlr* ctlr)
1477dd7cddfSDavid du Colombier {
1489a747e4fSDavid du Colombier Cyber938x *cyber;
1499a747e4fSDavid du Colombier
1509a747e4fSDavid du Colombier cyber = vga->private;
1519a747e4fSDavid du Colombier
1527dd7cddfSDavid du Colombier vga->crt[0x1E] = 0x80;
1537dd7cddfSDavid du Colombier vga->crt[0x2A] |= 0x40;
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier if(vga->linear && (ctlr->flag & Hlinear))
1567dd7cddfSDavid du Colombier ctlr->flag |= Ulinear;
1577dd7cddfSDavid du Colombier
1587dd7cddfSDavid du Colombier vga->graphics[0x31] &= 0x8F;
1597dd7cddfSDavid du Colombier if(vga->mode->y > 768)
1607dd7cddfSDavid du Colombier vga->graphics[0x31] |= 0x30;
1617dd7cddfSDavid du Colombier else if(vga->mode->y > 600)
1627dd7cddfSDavid du Colombier vga->graphics[0x31] |= 0x20;
1637dd7cddfSDavid du Colombier else if(vga->mode->y > 480)
1647dd7cddfSDavid du Colombier vga->graphics[0x31] |= 0x10;
1657dd7cddfSDavid du Colombier
1669a747e4fSDavid du Colombier switch(vga->mode->z){
1679a747e4fSDavid du Colombier case 8:
1689a747e4fSDavid du Colombier cyber->pcr = 0; /* DAC Pixel Command Register */
1699a747e4fSDavid du Colombier vga->crt[0x38] = 0x00; /* Pixel Bus Register */
1709a747e4fSDavid du Colombier break;
1719a747e4fSDavid du Colombier case 16:
1729a747e4fSDavid du Colombier cyber->pcr = 0x30;
1739a747e4fSDavid du Colombier vga->crt[0x38] = 0x05;
1749a747e4fSDavid du Colombier vga->crt[0x29] |= 0x10; /* RSC: necessary for Versa SX */
1759a747e4fSDavid du Colombier break;
1769a747e4fSDavid du Colombier case 24:
1779a747e4fSDavid du Colombier cyber->pcr = 0xD0;
1789a747e4fSDavid du Colombier vga->crt[0x38] = 0x29;
1799a747e4fSDavid du Colombier break;
1809a747e4fSDavid du Colombier default:
1817dd7cddfSDavid du Colombier error("depth %d not supported\n", vga->mode->z);
1829a747e4fSDavid du Colombier }
1837dd7cddfSDavid du Colombier
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier switch(vga->sequencer[0x09]){
1867dd7cddfSDavid du Colombier
1877dd7cddfSDavid du Colombier default:
1887dd7cddfSDavid du Colombier error("unknown Cyber revision 0x%uX\n", vga->sequencer[0x09]);
1897dd7cddfSDavid du Colombier break;
1909a747e4fSDavid du Colombier case 0x21: /* ProVidia 9685 */
1919a747e4fSDavid du Colombier /*
1929a747e4fSDavid du Colombier * Incomplete - no clock code so only 640x480x8 works.
1939a747e4fSDavid du Colombier */
1949a747e4fSDavid du Colombier vga->attribute[0x11] = 0;
1959a747e4fSDavid du Colombier vga->graphics[0x0F] |= 0x07;
1969a747e4fSDavid du Colombier break;
19759cc4ca5SDavid du Colombier case 0x42: /* Cyber9382 */
19859cc4ca5SDavid du Colombier /*
19959cc4ca5SDavid du Colombier * Try a little magic for DSTN displays.
20059cc4ca5SDavid du Colombier * May work on other chips too, who knows.
20159cc4ca5SDavid du Colombier */
20259cc4ca5SDavid du Colombier if(!(vga->graphics[0x42] & 0x80) /* !TFT */
20359cc4ca5SDavid du Colombier && (vga->graphics[0x43] & 0x20)){ /* DSTN */
20459cc4ca5SDavid du Colombier if(vga->mode->x == 640)
20559cc4ca5SDavid du Colombier vga->graphics[0x30] |= 0x81;
20659cc4ca5SDavid du Colombier else
20759cc4ca5SDavid du Colombier vga->graphics[0x30] &= ~0x81;
20859cc4ca5SDavid du Colombier }
20959cc4ca5SDavid du Colombier /*FALLTHROUGH*/
210e0d6d19cSDavid du Colombier case 0x3: /* Cyber9320 */
2117dd7cddfSDavid du Colombier case 0x33: /* Cyber9385 */
212e0d6d19cSDavid du Colombier case 0x34: /* Cyber9385 */
21359cc4ca5SDavid du Colombier case 0x35: /* Cyber9385 */
214b7b24591SDavid du Colombier case 0x3A: /* Cyber9385 */
2157dd7cddfSDavid du Colombier vga->graphics[0x0F] |= 0x07;
2167dd7cddfSDavid du Colombier break;
2176b6b9ac8SDavid du Colombier case 0x41: /* Cyber9525/DVD */
2186b6b9ac8SDavid du Colombier vga->graphics[0x0F] |= 0x17;
2196b6b9ac8SDavid du Colombier break;
2207dd7cddfSDavid du Colombier case 0x4A: /* Cyber9388 */
2219a747e4fSDavid du Colombier case 0x5D: /* CyberBlade */
222*7def40e1SDavid du Colombier case 0x6A: /* CyberBlade (iTuner) */
2239a747e4fSDavid du Colombier case 0x7A: /* CyberBlade */
2247dd7cddfSDavid du Colombier vga->crt[0x2F] = 0x3F;
2257dd7cddfSDavid du Colombier vga->graphics[0x0F] |= 0x17;
2267dd7cddfSDavid du Colombier if(vga->mode->x == 1024)
2277dd7cddfSDavid du Colombier vga->graphics[0x30] = 0x18;
2287dd7cddfSDavid du Colombier break;
2297dd7cddfSDavid du Colombier }
2307dd7cddfSDavid du Colombier vga->graphics[0x52] &= ~0x01;
2317dd7cddfSDavid du Colombier vga->graphics[0x53] &= ~0x01;
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier ctlr->flag |= Finit;
2347dd7cddfSDavid du Colombier }
2357dd7cddfSDavid du Colombier
2367dd7cddfSDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)2377dd7cddfSDavid du Colombier load(Vga* vga, Ctlr* ctlr)
2387dd7cddfSDavid du Colombier {
2399a747e4fSDavid du Colombier Cyber938x *cyber;
2409a747e4fSDavid du Colombier
2419a747e4fSDavid du Colombier cyber = vga->private;
2429a747e4fSDavid du Colombier
2437dd7cddfSDavid du Colombier outportw(0x3C4, 0x000B);
2447dd7cddfSDavid du Colombier outportb(0x3C4, 0x0B);
2457dd7cddfSDavid du Colombier inportb(0x3C5);
2467dd7cddfSDavid du Colombier
2479a747e4fSDavid du Colombier pcrw(cyber->pcr);
2489a747e4fSDavid du Colombier
2497dd7cddfSDavid du Colombier outportw(0x3C4, (0xC2 << 8) | 0x0E);
2507dd7cddfSDavid du Colombier vgaxo(Grx, 0x52, vga->graphics[0x52]);
2517dd7cddfSDavid du Colombier vgaxo(Grx, 0x53, vga->graphics[0x53]);
2527dd7cddfSDavid du Colombier vgaxo(Grx, 0x30, vga->graphics[0x30]);
2537dd7cddfSDavid du Colombier vgaxo(Grx, 0x31, vga->graphics[0x31]);
2547dd7cddfSDavid du Colombier
2557dd7cddfSDavid du Colombier vgaxo(Crtx, 0x1E, vga->crt[0x1E]);
2567dd7cddfSDavid du Colombier if(ctlr->flag & Ulinear)
2577dd7cddfSDavid du Colombier vga->crt[0x21] |= 0x20;
2587dd7cddfSDavid du Colombier vgaxo(Crtx, 0x21, vga->crt[0x21]);
2599a747e4fSDavid du Colombier vgaxo(Crtx, 0x29, vga->crt[0x29]);
2607dd7cddfSDavid du Colombier vgaxo(Crtx, 0x2A, vga->crt[0x2A]);
2617dd7cddfSDavid du Colombier vgaxo(Crtx, 0x2F, vga->crt[0x2F]);
2627dd7cddfSDavid du Colombier vgaxo(Crtx, 0x38, vga->crt[0x38]);
2637dd7cddfSDavid du Colombier
2647dd7cddfSDavid du Colombier vgaxo(Grx, 0x0F, vga->graphics[0x0F]);
2657dd7cddfSDavid du Colombier
2667dd7cddfSDavid du Colombier ctlr->flag |= Fload;
2677dd7cddfSDavid du Colombier }
2687dd7cddfSDavid du Colombier
2697dd7cddfSDavid du Colombier static void
dump(Vga * vga,Ctlr * ctlr)2707dd7cddfSDavid du Colombier dump(Vga* vga, Ctlr* ctlr)
2717dd7cddfSDavid du Colombier {
2727dd7cddfSDavid du Colombier char *name;
2737dd7cddfSDavid du Colombier Cyber938x *cyber;
2749a747e4fSDavid du Colombier int i, k, m, n, vclka, vclkb;
2757dd7cddfSDavid du Colombier
2767dd7cddfSDavid du Colombier name = ctlr->name;
2777dd7cddfSDavid du Colombier cyber = vga->private;
2787dd7cddfSDavid du Colombier printitem(name, "Seq08");
2799a747e4fSDavid du Colombier for(i = 0x08; i < 0x20; i++)
2807dd7cddfSDavid du Colombier printreg(vga->sequencer[i]);
2817dd7cddfSDavid du Colombier printitem(name, "Old Seq0C");
2827dd7cddfSDavid du Colombier for(i = 0; i < 3; i++)
2837dd7cddfSDavid du Colombier printreg(cyber->old[i]);
2849a747e4fSDavid du Colombier printitem(name, "pcr");
2859a747e4fSDavid du Colombier printreg(cyber->pcr);
2867dd7cddfSDavid du Colombier printitem(name, "Crt19");
2877dd7cddfSDavid du Colombier for(i = 0x19; i < 0x20; i++)
2887dd7cddfSDavid du Colombier printreg(vga->crt[i]);
2897dd7cddfSDavid du Colombier printitem(name, "Crt20");
2907dd7cddfSDavid du Colombier for(i = 0x20; i < 0x60; i++)
2917dd7cddfSDavid du Colombier printreg(vga->crt[i]);
2929a747e4fSDavid du Colombier printitem(name, "CrtCF");
2939a747e4fSDavid du Colombier printreg(vga->crt[0xCF]);
2947dd7cddfSDavid du Colombier printitem(name, "Gr09");
2957dd7cddfSDavid du Colombier for(i = 0x09; i < 0x10; i++)
2967dd7cddfSDavid du Colombier printreg(vga->graphics[i]);
2977dd7cddfSDavid du Colombier printitem(name, "Gr10");
2987dd7cddfSDavid du Colombier for(i = 0x10; i < 0x60; i++)
2997dd7cddfSDavid du Colombier printreg(vga->graphics[i]);
3007dd7cddfSDavid du Colombier
3019a747e4fSDavid du Colombier if(vga->sequencer[0x09] >= 0x4A){
3029a747e4fSDavid du Colombier vclka = vga->sequencer[0x18];
3039a747e4fSDavid du Colombier vclkb = vga->sequencer[0x19];
3049a747e4fSDavid du Colombier }
3059a747e4fSDavid du Colombier else{
3069a747e4fSDavid du Colombier vclka = inportb(0x43C8);
3079a747e4fSDavid du Colombier vclkb = inportb(0x43C9);
3087dd7cddfSDavid du Colombier printitem(name, "mclk");
3097dd7cddfSDavid du Colombier printreg(inportb(0x43C6));
3107dd7cddfSDavid du Colombier printreg(inportb(0x43C7));
3119a747e4fSDavid du Colombier }
3127dd7cddfSDavid du Colombier printitem(name, "vclk");
3139a747e4fSDavid du Colombier printreg(vclka);
3149a747e4fSDavid du Colombier printreg(vclkb);
3159a747e4fSDavid du Colombier k = vclkb>>6;
3169a747e4fSDavid du Colombier m = vclkb & 0x3F;
3179a747e4fSDavid du Colombier n = vclka;
3189a747e4fSDavid du Colombier Bprint(&stdout, "%18d\n", (((n+8)*RefFreq)*(1<<k))/(m+2));
3197dd7cddfSDavid du Colombier
3207dd7cddfSDavid du Colombier printitem(name, "lcd size");
3217dd7cddfSDavid du Colombier Bprint(&stdout, "%9ud %8ud\n", cyber->x, cyber->y);
3227dd7cddfSDavid du Colombier }
3237dd7cddfSDavid du Colombier
3247dd7cddfSDavid du Colombier Ctlr cyber938x = {
3257dd7cddfSDavid du Colombier "cyber938x", /* name */
3267dd7cddfSDavid du Colombier snarf, /* snarf */
3277dd7cddfSDavid du Colombier options, /* options */
3287dd7cddfSDavid du Colombier init, /* init */
3297dd7cddfSDavid du Colombier load, /* load */
3307dd7cddfSDavid du Colombier dump, /* dump */
3317dd7cddfSDavid du Colombier };
3327dd7cddfSDavid du Colombier
3337dd7cddfSDavid du Colombier Ctlr cyber938xhwgc = {
3347dd7cddfSDavid du Colombier "cyber938xhwgc", /* name */
3357dd7cddfSDavid du Colombier 0, /* snarf */
3367dd7cddfSDavid du Colombier 0, /* options */
3377dd7cddfSDavid du Colombier 0, /* init */
3387dd7cddfSDavid du Colombier 0, /* load */
3397dd7cddfSDavid du Colombier 0, /* dump */
3407dd7cddfSDavid du Colombier };
341