/* Philippe Anel : philippe.anel@noos.fr */ #include #include #include #include "vga.h" #include "pci.h" /* * Matrox G4xx 3D graphics accelerators */ enum { Kilo = 1024, Meg = 1024*1024, MATROX = 0x102B, /* pci chip manufacturer */ MGA4XX = 0x0525, /* pci chip device ids */ /* Pci configuration space mapping */ PCfgMgaFBAA = 0x10, /* Frame buffer Aperture Address */ PCfgMgaCAA = 0x14, /* Control Aperture Address base */ PCfgMgaIAA = 0x18, /* ILOAD Aperture base Address */ PCfgMgaOption1 = 0x40, /* Option Register 1 */ PCfgMgaOption2 = 0x50, /* Option Register 2 */ PCfgMgaOption3 = 0x54, /* Option Register 3 */ PCfgMgaDevCtrl = 0x04, /* Device Control */ /* control aperture offsets */ DMAWIN = 0x0000, /* 7KByte Pseudo-DMA Window */ STATUS0 = 0x1FC2, /* Input Status 0 */ STATUS1 = 0x1FDA, /* Input Status 1 */ SEQIDX = 0x1FC4, /* Sequencer Index */ SEQDATA = 0x1FC5, /* Sequencer Data */ MISC_W = 0x1FC2, /* Misc. WO */ MISC_R = 0x1FCC, /* Misc. RO */ GCTLIDX = 0x1FCE, /* Graphic Controler Index */ GCTLDATA = 0x1FCF, /* Graphic Controler Data */ CRTCIDX = 0x1FD4, /* CRTC Index */ CRTCDATA = 0x1FD5, /* CRTC Data */ CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */ CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */ RAMDACIDX = 0x3C00, /* RAMDAC registers Index */ RAMDACDATA = 0x3C0A, /* RAMDAC Indexed Data */ RAMDACPALDATA = 0x3C01, ATTRIDX = 0x1FC0, /* Attribute Index */ ATTRDATA = 0x1FC1, /* Attribute Data */ CACHEFLUSH = 0x1FFF, C2_CTL = 0X3C10, MGA_STATUS = 0X1E14, Z_DEPTH_ORG = 0X1C0C, }; typedef struct { Pcidev* pci; int devid; int revid; ulong mmio; ulong mmfb; int fbsize; ulong iload; uchar syspll_m; uchar syspll_n; uchar syspll_p; uchar syspll_s; uchar pixpll_m; uchar pixpll_n; uchar pixpll_p; uchar pixpll_s; ulong option1; ulong option2; ulong option3; /* From plan9.ini */ uchar sdram; uchar colorkey; uchar maskkey; ulong maxpclk; uchar graphics[9]; uchar attribute[0x14]; uchar sequencer[5]; uchar crtc[0x19]; uchar crtcext[9]; ulong htotal; ulong hdispend; ulong hblkstr; ulong hblkend; ulong hsyncstr; ulong hsyncend; ulong vtotal; ulong vdispend; ulong vblkstr; ulong vblkend; ulong vsyncstr; ulong vsyncend; ulong linecomp; ulong hsyncsel; ulong startadd; ulong offset; ulong maxscan; ulong curloc; ulong prowscan; ulong currowstr; ulong currowend; ulong curoff; ulong undrow; ulong curskew; ulong conv2t4; ulong interlace; ulong hsyncdel; ulong hdispskew; ulong bytepan; ulong dotclkrt; ulong dword; ulong wbmode; ulong addwrap; ulong selrowscan; ulong cms; ulong csynccen; ulong hrsten; ulong vrsten; ulong vinten; ulong vintclr; ulong hsyncoff; ulong vsyncoff; ulong crtcrstN; ulong mgamode; ulong scale; ulong hiprilvl; ulong maxhipri; ulong c2hiprilvl; ulong c2maxhipri; ulong misc; ulong crtcprotect; ulong winsize; ulong winfreq; } Mga; static void mgawrite32(Mga* mga, int index, ulong val) { ((ulong*)mga->mmio)[index] = val; } static ulong mgaread32(Mga* mga, int index) { return ((ulong*)mga->mmio)[index]; } static void mgawrite8(Mga* mga, int index, uchar val) { ((uchar*)mga->mmio)[index] = val; } static uchar mgaread8(Mga* mga, int index) { return ((uchar*)mga->mmio)[index]; } static uchar seqget(Mga* mga, int index) { mgawrite8(mga, SEQIDX, index); return mgaread8(mga, SEQDATA); } static uchar seqset(Mga* mga, int index, uchar set, uchar clr) { uchar tmp; mgawrite8(mga, SEQIDX, index); tmp = mgaread8(mga, SEQDATA); mgawrite8(mga, SEQIDX, index); mgawrite8(mga, SEQDATA, (tmp & ~clr) | set); return tmp; } static uchar crtcget(Mga* mga, int index) { mgawrite8(mga, CRTCIDX, index); return mgaread8(mga, CRTCDATA); } static uchar crtcset(Mga* mga, int index, uchar set, uchar clr) { uchar tmp; mgawrite8(mga, CRTCIDX, index); tmp = mgaread8(mga, CRTCDATA); mgawrite8(mga, CRTCIDX, index); mgawrite8(mga, CRTCDATA, (tmp & ~clr) | set); return tmp; } static uchar crtcextget(Mga* mga, int index) { mgawrite8(mga, CRTCEXTIDX, index); return mgaread8(mga, CRTCEXTDATA); } static uchar crtcextset(Mga* mga, int index, uchar set, uchar clr) { uchar tmp; mgawrite8(mga, CRTCEXTIDX, index); tmp = mgaread8(mga, CRTCEXTDATA); mgawrite8(mga, CRTCEXTIDX, index); mgawrite8(mga, CRTCEXTDATA, (tmp & ~clr) | set); return tmp; } static uchar dacget(Mga* mga, int index) { mgawrite8(mga, RAMDACIDX, index); return mgaread8(mga, RAMDACDATA); } static uchar dacset(Mga* mga, int index, uchar set, uchar clr) { uchar tmp; mgawrite8(mga, RAMDACIDX, index); tmp = mgaread8(mga, RAMDACDATA); mgawrite8(mga, RAMDACIDX, index); mgawrite8(mga, RAMDACDATA, (tmp & ~clr) | set); return tmp; } static uchar gctlget(Mga* mga, int index) { mgawrite8(mga, GCTLIDX, index); return mgaread8(mga, GCTLDATA); } static uchar gctlset(Mga* mga, int index, uchar set, uchar clr) { uchar tmp; mgawrite8(mga, GCTLIDX, index); tmp = mgaread8(mga, GCTLDATA); mgawrite8(mga, GCTLIDX, index); mgawrite8(mga, GCTLDATA, (tmp & ~clr) | set); return tmp; } static uchar attrget(Mga* mga, int index) { mgawrite8(mga, ATTRIDX, index); return mgaread8(mga, ATTRDATA); } static uchar attrset(Mga* mga, int index, uchar set, uchar clr) { uchar tmp; mgawrite8(mga, ATTRIDX, index); tmp = mgaread8(mga, ATTRDATA); mgawrite8(mga, ATTRIDX, index); mgawrite8(mga, ATTRDATA, (tmp & ~clr) | set); return tmp; } static uchar miscget(Mga* mga) { return mgaread8(mga, MISC_R); } static uchar miscset(Mga* mga, uchar set, uchar clr) { uchar tmp; tmp = mgaread8(mga, MISC_R); mgawrite8(mga, MISC_W, (tmp & ~clr) | set); return tmp; } /* ************************************************************ */ static void dump_all_regs(Mga* mga) { int i; for (i = 0; i < 25; i++) trace("crtc[%d] = 0x%x\n", i, crtcget(mga, i)); for (i = 0; i < 9; i++) trace("crtcext[%d] = 0x%x\n", i, crtcextget(mga, i)); for (i = 0; i < 5; i++) trace("seq[%d] = 0x%x\n", i, seqget(mga, i)); for (i = 0; i < 9; i++) trace("gctl[%d] = 0x%x\n", i, gctlget(mga, i)); trace("misc = 0x%x\n", mgaread8(mga, MISC_R)); for (i = 0; i < 0x87; i++) trace("dac[%d] = 0x%x\n", i, dacget(mga, i)); } /* ************************************************************ */ static void dump(Vga* vga, Ctlr* ctlr) { dump_all_regs(vga->private); ctlr->flag |= Fdump; } static void mapmga4xx(Vga* vga, Ctlr* ctlr) { int f; long m; Mga * mga; if(vga->private == nil) error("%s: g4xxio: no *mga4xx\n", ctlr->name); mga = vga->private; f = open("#v/vgactl", OWRITE); if(f < 0) error("%s: can't open vgactl\n", ctlr->name); if(write(f, "type mga4xx", 11) != 11) error("%s: can't set mga type\n", ctlr->name); m = segattach(0, "mga4xxmmio", 0, 16*Kilo); if(m == -1) error("%s: can't attach mga4xxmmio segment\n", ctlr->name); mga->mmio = m; trace("%s: mmio at 0x%lx\n", ctlr->name, mga->mmio); m = segattach(0, "mga4xxscreen", 0, 32*Meg); if(m == -1) error("%s: can't attach mga4xxscreen segment\n", ctlr->name); mga->mmfb = m; trace("%s: frame buffer at 0x%lx\n", ctlr->name, mga->mmfb); /* TODO : When needed ... map ILOAD too ... */ } static void snarf(Vga* vga, Ctlr* ctlr) { int i, k, n; uchar * p; uchar x[16]; Pcidev * pci; Mga * mga; uchar crtcext3; trace("%s->snarf\n", ctlr->name); if(vga->private == nil) { pci = pcimatch(nil, MATROX, MGA4XX); if(pci == nil) error("%s: no Pcidev with Vid=0x102B, Did=0x0525\n", ctlr->name); trace("%s: G4%d0 rev %d\n", ctlr->name, pci->rid&0x80?5:0, pci->rid&(~0x80)); i = pcicfgr32(pci, PCfgMgaDevCtrl); if ((i & 2) != 2) error("%s: Memory Space not enabled ... Aborting ...\n", ctlr->name); vga->private = alloc(sizeof(Mga)); mga = (Mga*)vga->private; mga->devid = pci->did; mga->revid = pci->rid; mga->pci = pci; mapmga4xx(vga, ctlr); } else { mga = (Mga*)vga->private; } /* Find out how much memory is here, some multiple of 2Meg */ /* First Set MGA Mode ... */ crtcext3 = crtcextset(mga, 3, 0x80, 0xff); p = (uchar*)mga->mmfb; n = 16; for (i = 0; i < n; i++) { k = (2*i+1)*Meg; p[k] = 0; p[k] = i+1; *((uchar*)(mga->mmio + CACHEFLUSH)) = 0; x[i] = p[k]; trace("x[%d]=%d\n", i, x[i]); } for(i = 1; i < n; i++) if(x[i] != i+1) break; vga->vmz = mga->fbsize = 2*i*Meg; trace("probe found %d megabytes\n", 2*i); crtcextset(mga, 3, crtcext3, 0xff); ctlr->flag |= Fsnarf; } static void options(Vga* vga, Ctlr* ctlr) { Mode *mode; mode = vga->mode; if(mode->x % 128){ mode->x = (mode->x/128)*128; sprint(mode->size, "%dx%dx%d", mode->x, mode->y, mode->z); } ctlr->flag |= Foptions; } /* calcclock - Calculate the PLL settings (m, n, p, s). */ static double calcclock(Mga* mga, long Fneeded) { double Fpll; double Fvco; double Fref; int pixpll_m_min; int pixpll_m_max; int pixpll_n_min; int pixpll_n_max; int pixpll_p_max; int pll_min; int pll_max; double Ferr, Fcalc; int m, n, p; /* These values are taken from Matrox G400 Specification - p 4-91 */ Fref = 27000000.0; pixpll_n_min = 7; pixpll_n_max = 127; pixpll_m_min = 1; pixpll_m_max = 31; pixpll_p_max = 7; pll_min = 50000; pll_max = mga->maxpclk; if (Fneeded < pll_min) error("mga: Too little Frequency %ld : Minimum supported by PLL is %d", Fneeded, pll_min); if (Fneeded > pll_max) error("mga: Too big Frequency %ld : Maximum supported by PLL is %d", Fneeded, pll_max); Fvco = ( double ) Fneeded; for (p = 0; p <= pixpll_p_max && Fvco < pll_max; p = p * 2 + 1, Fvco *= 2.0) ; mga->pixpll_p = p; Ferr = Fneeded; for ( m = pixpll_m_min ; m <= pixpll_m_max ; m++ ) for ( n = pixpll_n_min; n <= pixpll_n_max; n++ ) { Fcalc = Fref * (n + 1) / (m + 1) ; /* * Pick the closest frequency. */ if ( abs(Fcalc - Fvco) < Ferr ) { Ferr = abs(Fcalc - Fvco); mga->pixpll_m = m; mga->pixpll_n = n; } } Fvco = Fref * (mga->pixpll_n + 1) / (mga->pixpll_m + 1); if ( (50000000.0 <= Fvco) && (Fvco < 110000000.0) ) mga->pixpll_p |= 0; if ( (110000000.0 <= Fvco) && (Fvco < 170000000.0) ) mga->pixpll_p |= (1<<3); if ( (170000000.0 <= Fvco) && (Fvco < 240000000.0) ) mga->pixpll_p |= (2<<3); if ( (240000000.0 <= Fvco) ) mga->pixpll_p |= (3<<3); Fpll = Fvco / (p + 1); return Fpll; } static void init(Vga* vga, Ctlr* ctlr) { Mode* mode; Mga* mga; double Fpll; Ctlr* c; int i; ulong t; mga = vga->private; mode = vga->mode; trace("mga mmio at %lx\n", mga->mmio); ctlr->flag |= Ulinear; if ((mode->z != 32) && (mode->z != 8)) error("depth %d not supported !\n", mode->z); if (mode->interlace) error("interlaced mode not supported !\n"); trace("%s: Initializing mode %dx%dx%d on %s\n", ctlr->name, mode->x, mode->y, mode->z, mode->type); trace("%s: Suggested Dot Clock : %d\n", ctlr->name, mode->frequency); trace("%s: Horizontal Total = %d\n", ctlr->name, mode->ht); trace("%s: Start Horizontal Blank = %d\n", ctlr->name, mode->shb); trace("%s: End Horizontal Blank = %d\n", ctlr->name, mode->ehb); trace("%s: Vertical Total = %d\n", ctlr->name, mode->vt); trace("%s: Vertical Retrace Start = %d\n", ctlr->name, mode->vrs); trace("%s: Vertical Retrace End = %d\n", ctlr->name, mode->vre); trace("%s: Start Horizontal Sync = %d\n", ctlr->name, mode->shs); trace("%s: End Horizontal Sync = %d\n", ctlr->name, mode->ehs); trace("%s: HSync = %c\n", ctlr->name, mode->hsync); trace("%s: VSync = %c\n", ctlr->name, mode->vsync); trace("%s: Interlace = %d\n", ctlr->name, mode->interlace); mga->maxpclk = 300000000; Fpll = calcclock(mga, mode->frequency); trace("Fpll set to %f\n", Fpll); trace("pixclks : n = %d m = %d p = %d\n", mga->pixpll_n, mga->pixpll_m, mga->pixpll_p & 0x7); trace("PCI Option1 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption1)); trace("PCI Option2 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption2)); trace("PCI Option3 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption3)); mga->htotal = (mode->ht >> 3) - 5; mga->hdispend = (mode->x >> 3) - 1; if (1) { mga->hblkstr = mga->hdispend; /* (mode->shb >> 3); */ mga->hblkend = mga->htotal + 4; /* (mode->ehb >> 3); */ } else { mga->hblkstr = (mode->shb >> 3); mga->hblkend = (mode->ehb >> 3); } mga->hsyncstr = (mode->shs >> 3); mga->hsyncend = (mode->ehs >> 3); mga->hsyncdel = 0; mga->vtotal = mode->vt - 2; mga->vdispend = mode->y - 1; mga->vblkstr = mode->y - 1; mga->vblkend = mode->vt - 1; mga->vsyncstr = mode->vrs; mga->vsyncend = mode->vre; mga->linecomp = mode->y; mga->hsyncsel = 0; /* Do not double lines ... */ mga->startadd = 0; mga->offset = (mode->x * mode->z) / 128; /* No Zoom */ mga->maxscan = 0; /* Not used in Power Graphic mode */ mga->curloc = 0; mga->prowscan = 0; mga->currowstr = 0; mga->currowend = 0; mga->curoff = 1; mga->undrow = 0; mga->curskew = 0; mga->conv2t4 = 0; mga->interlace = 0; mga->hdispskew = 0; mga->bytepan = 0; mga->dotclkrt = 0; mga->dword = 0; mga->wbmode = 1; mga->addwrap = 0; /* Not Used ! */ mga->selrowscan = 1; mga->cms = 1; mga->csynccen = 0; /* Disable composite sync */ /* VIDRST Pin */ mga->hrsten = 1; mga->vrsten = 1; /* vertical interrupt control */ mga->vinten = 1; mga->vintclr = 1; /* Let [hv]sync run freely */ mga->hsyncoff = 0; mga->vsyncoff = 0; mga->crtcrstN = 1; mga->mgamode = 1; mga->scale = (mode->z == 8) ? 0 : 3; /* 8 or 32 bits mode */ mga->crtcprotect = 1; mga->winsize = 0; mga->winfreq = 0; if ((mga->htotal == 0) || (mga->hblkend <= (mga->hblkstr + 1)) || ((mga->htotal - mga->hdispend) == 0) || ((mga->htotal - mga->bytepan + 2) <= mga->hdispend) || (mga->hsyncstr <= (mga->hdispend + 2)) || (mga->vtotal == 0)) { error("Invalid Power Graphic Mode :\n" "mga->htotal = %ld\n" "mga->hdispend = %ld\n" "mga->hblkstr = %ld\n" "mga->hblkend = %ld\n" "mga->hsyncstr = %ld\n" "mga->hsyncend = %ld\n" "mga->hsyncdel = %ld\n" "mga->vtotal = %ld\n" "mga->vdispend = %ld\n" "mga->vblkstr = %ld\n" "mga->vblkend = %ld\n" "mga->vsyncstr = %ld\n" "mga->vsyncend = %ld\n" "mga->linecomp = %ld\n", mga->htotal, mga->hdispend, mga->hblkstr, mga->hblkend, mga->hsyncstr, mga->hsyncend, mga->hsyncdel, mga->vtotal, mga->vdispend, mga->vblkstr, mga->vblkend, mga->vsyncstr, mga->vsyncend, mga->linecomp ); } mga->hiprilvl = 0; mga->maxhipri = 0; mga->c2hiprilvl = 0; mga->c2maxhipri = 0; mga->misc = ((mode->hsync != '-')?0:(1<<6)) | ((mode->vsync != '-')?0:(1<<7)); mga->crtc[0x00] = 0xff & mga->htotal; mga->crtc[0x01] = 0xff & mga->hdispend; mga->crtc[0x02] = 0xff & mga->hblkstr; mga->crtc[0x03] = (0x1f & mga->hblkend) | ((0x03 & mga->hdispskew) << 5) | 0x80 /* cf 3-304 */ ; mga->crtc[0x04] = 0xff & mga->hsyncstr; mga->crtc[0x05] = (0x1f & mga->hsyncend) | ((0x03 & mga->hsyncdel) << 5) | ((0x01 & (mga->hblkend >> 5)) << 7) ; mga->crtc[0x06] = 0xff & mga->vtotal; t = ((0x01 & (mga->vtotal >> 8)) << 0) | ((0x01 & (mga->vdispend >> 8)) << 1) | ((0x01 & (mga->vsyncstr >> 8)) << 2) | ((0x01 & (mga->vblkstr >> 8)) << 3) | ((0x01 & (mga->linecomp >> 8)) << 4) | ((0x01 & (mga->vtotal >> 9)) << 5) | ((0x01 & (mga->vdispend >> 9)) << 6) | ((0x01 & (mga->vsyncstr >> 9)) << 7) ; mga->crtc[0x07] = 0xff & t; trace("*************"); trace("crtc 0x07 = %lx\n", t); trace("mga->vtotal = %lx\n", mga->vtotal); trace("mga->vdispend = %lx\n", mga->vdispend); trace("mga->vsyncstr = %lx\n", mga->vsyncstr); trace("mga->vblkstr = %lx\n", mga->vblkstr); trace("mga->linecomp = %lx\n", mga->linecomp); trace("*************"); mga->crtc[0x08] = (0x1f & mga->prowscan) | ((0x03 & mga->bytepan) << 5); mga->crtc[0x09] = (0x1f & mga->maxscan) | ((0x01 & (mga->vblkstr >> 9)) << 5) | ((0x01 & (mga->linecomp >> 9)) << 6) | ((0x01 & mga->conv2t4) << 7) ; mga->crtc[0x0a] = (0x1f & mga->currowstr) | ((0x01 & mga->curoff) << 5) ; mga->crtc[0x0b] = (0x1f & mga->currowend) | ((0x03 & mga->curskew) << 5) ; mga->crtc[0x0c] = 0xff & (mga->startadd >> 8); mga->crtc[0x0d] = 0xff & mga->startadd; mga->crtc[0x0e] = 0xff & (mga->curloc >> 8); mga->crtc[0x0f] = 0xff & mga->curloc; mga->crtc[0x10] = 0xff & mga->vsyncstr; mga->crtc[0x11] = (0x0f & mga->vsyncend) | ((0x01 & mga->vintclr) << 4) | ((0x01 & mga->vinten) << 5) | ((0x01 & mga->crtcprotect) << 7) ; mga->crtc[0x12] = 0xff & mga->vdispend; mga->crtc[0x13] = 0xff & mga->offset; mga->crtc[0x14] = 0x1f & mga->undrow; /* vga only */ mga->crtc[0x15] = 0xff & mga->vblkstr; mga->crtc[0x16] = 0xff & mga->vblkend; mga->crtc[0x17] = ((0x01 & mga->cms) << 0) | ((0x01 & mga->selrowscan) << 1) | ((0x01 & mga->hsyncsel) << 2) | ((0x01 & mga->addwrap) << 5) | ((0x01 & mga->wbmode) << 6) | ((0x01 & mga->crtcrstN) << 7) ; mga->crtc[0x18] = mga->linecomp; mga->crtcext[0] = (0x0f & (mga->startadd >> 16)) | ((0x03 & (mga->offset >> 8)) << 4) | ((0x01 & (mga->startadd >> 20)) << 6) | ((0x01 & mga->interlace) << 7) ; mga->crtcext[1] = ((0x01 & (mga->htotal >> 8)) << 0) | ((0x01 & (mga->hblkstr >> 8)) << 1) | ((0x01 & (mga->hsyncstr >> 8)) << 2) | ((0x01 & mga->hrsten) << 3) | ((0x01 & mga->hsyncoff) << 4) | ((0x01 & mga->vsyncoff) << 5) | ((0x01 & (mga->hblkend >> 6)) << 6) | ((0x01 & mga->vrsten) << 7) ; mga->crtcext[2] = ((0x03 & (mga->vtotal >> 10)) << 0) | ((0x01 & (mga->vdispend >> 10)) << 2) | ((0x03 & (mga->vblkstr >> 10)) << 3) | ((0x03 & (mga->vsyncstr >> 10)) << 5) | ((0x01 & (mga->linecomp >> 10)) << 7) ; mga->crtcext[3] = ((0x07 & mga->scale) << 0) | ((0x01 & mga->csynccen) << 6) | ((0x01 & mga->mgamode) << 7) ; mga->crtcext[4] = 0; /* memory page ... not used in Power Graphic Mode */ mga->crtcext[5] = 0; /* Not used in interlaced mode */ mga->crtcext[6] = ((0x07 & mga->hiprilvl) << 0) | ((0x07 & mga->maxhipri) << 4) ; mga->crtcext[7] = ((0x07 & mga->winsize) << 1) | ((0x07 & mga->winfreq) << 5) ; mga->crtcext[8] = (0x01 & (mga->startadd >> 21)) << 0; /* Initialize Sequencer */ mga->sequencer[0] = 0; mga->sequencer[1] = 0; mga->sequencer[2] = 0x03; mga->sequencer[3] = 0; mga->sequencer[4] = 0x02; /* Graphic Control registers are ignored when not using 0xA0000 aperture */ for (i = 0; i < 9; i++) mga->graphics[i] = 0; /* The Attribute Controler is not available in Power Graphics mode */ for (i = 0; i < 0x15; i++) mga->attribute[i] = i; /* disable vga load (want to do fields in different order) */ for(c = vga->link; c; c = c->link) if (strncmp(c->name, "vga", 3) == 0) c->load = nil; } enum { Seq_ClockingMode = 1, Dotmode = (1<<0), Shftldrt = (1<<2), Dotclkrt = (1<<3), Shiftfour = (1<<4), Scroff = (1<<5), CrtcExt_Horizontcount = 1, Htotal = (1<<0), Hblkstr = (1<<1), Hsyncstr = (1<<2), Hrsten = (1<<3), Hsyncoff = (1<<4), Vsyncoff = (1<<5), Hblkend = (1<<6), Vrsten = (1<<7), CrtcExt_Miscellaneous = 3, Mgamode = (1<<7), Dac_Xpixclkctrl = 0x1a, Pixclksl = (3<<0), Pixclkdis = (1<<2), Pixpllpdn = (1<<3), Dac_Xpixpllstat = 0x4f, Pixlock = (1<<6), Dac_Xpixpllan = 0x45, Dac_Xpixpllbn = 0x49, Dac_Xpixpllcn = 0x4d, Dac_Xpixpllam = 0x44, Dac_Xpixpllbm = 0x48, Dac_Xpixpllcm = 0x4c, Dac_Xpixpllap = 0x46, Dac_Xpixpllbp = 0x4a, Dac_Xpixpllcp = 0x4e, Dac_Xmulctrl = 0x19, ColorDepth = (7<<0), _8bitsPerPixel = 0, _15bitsPerPixel = 1, _16bitsPerPixel = 2, _24bitsPerPixel = 3, _32bitsPerPixelWithOv = 4, _32bitsPerPixel = 7, Dac_Xpanelmode = 0x1f, Dac_Xmiscctrl = 0x1e, Dacpdn = (1<<0), Mfcsel = (3<<1), Vga8dac = (1<<3), Ramcs = (1<<4), Vdoutsel = (7<<5), Dac_Xcurctrl = 0x06, CursorDis = 0, Cursor3Color = 1, CursorXGA = 2, CursorX11 = 3, Cursor16Color = 4, Dac_Xzoomctrl = 0x38, Misc_loaddsel = (1<<0), Misc_rammapen = (1<<1), Misc_clksel = (3<<2), Misc_videodis = (1<<4), Misc_hpgoddev = (1<<5), Misc_hsyncpol = (1<<6), Misc_vsyncpol = (1<<7), }; static void load(Vga* vga, Ctlr* ctlr) { Mga* mga; int i; uchar* p; Mode* mode; uchar cursor; mga = vga->private; mode = vga->mode; trace("mga: Loading ...\n"); dump_all_regs(mga); trace("mga mmio at %lx\n", mga->mmio); trace("mga: loading vga registers ...\n" ); /* Initialize Sequencer registers */ for(i = 0; i < 5; i++) seqset(mga, i, mga->sequencer[i], 0xff); /* Initialize Attribute register */ for(i = 0; i < 0x15; i++) attrset(mga, i, mga->attribute[i], 0xff); /* Initialize Graphic Control registers */ for(i = 0; i < 9; i++) gctlset(mga, i, mga->graphics[i], 0xff); /* Wait VSYNC */ while (mgaread8(mga, STATUS1) & 0x08); while (! (mgaread8(mga, STATUS1) & ~0x08)); /* Turn off the video. */ seqset(mga, Seq_ClockingMode, Scroff, 0); /* Crtc2 Off */ mgawrite32(mga, C2_CTL, 0); /* Disable Cursor */ cursor = dacset(mga, Dac_Xcurctrl, CursorDis, 0xff); /* Pixel Pll UP and set Pixel clock source to Pixel Clock PLL */ dacset(mga, Dac_Xpixclkctrl, 0x01 | 0x08, 0x0f); trace("mga: waiting for the clock source becomes stable ...\n"); while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock) ; trace("mga: pixpll locked !\n"); /* Enable LUT, Disable MAFC */ dacset(mga, Dac_Xmiscctrl, Ramcs | Mfcsel, Vdoutsel); /* Initialize Z Buffer ... (useful?) */ mgawrite32(mga, Z_DEPTH_ORG, 0); /* Disable Dac */ dacset(mga, Dac_Xmiscctrl, 0, Dacpdn); /* Initialize Panel Mode */ dacset(mga, Dac_Xpanelmode, 0, 0xff); /* Disable the PIXCLK and set Pixel clock source to Pixel Clock PLL */ dacset(mga, Dac_Xpixclkctrl, Pixclkdis | 0x01, 0x3); /* Disable mapping of the memory */ miscset(mga, 0, Misc_rammapen); /* Enable 8 bit palette */ dacset(mga, Dac_Xmiscctrl, Vga8dac, 0); /* Select MGA Pixel Clock */ miscset(mga, Misc_clksel, 0); /* Wait */ for (i = 0; i < 50; i++) mgaread32(mga, MGA_STATUS); /* Reprogram the desired PLL registers */ dacset(mga, Dac_Xpixpllcm, mga->pixpll_m, 0xff); dacset(mga, Dac_Xpixpllcn, mga->pixpll_n, 0xff); dacset(mga, Dac_Xpixpllcp, mga->pixpll_p, 0xff); /* Wait until new clock becomes stable */ trace("mga: waiting for the clock source becomes stable ...\n"); while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock) ; trace("mga: pixpll locked !\n"); /* Enable Pixel Clock Oscillation */ dacset(mga, Dac_Xpixclkctrl, 0, Pixclkdis); /* Enable Dac */ dacset(mga, Dac_Xmiscctrl, Dacpdn, 0); /* Set Video Mode */ if (mode->z != 8) dacset(mga, Dac_Xmulctrl, _32bitsPerPixel, ColorDepth); /* 32 bits mode ... */ else dacset(mga, Dac_Xmulctrl, _8bitsPerPixel, ColorDepth); /* 8 bits mode ... */ /* Wait */ for (i = 0; i < 50; i++) mgaread32(mga, MGA_STATUS); /* Set Video Mode */ if (mode->z != 8) dacset(mga, Dac_Xmulctrl, _32bitsPerPixel, ColorDepth); /* 32 bits mode ... */ else dacset(mga, Dac_Xmulctrl, _8bitsPerPixel, ColorDepth); /* 8 bits mode ... */ /* Wait until new clock becomes stable */ trace("mga: waiting for the clock source becomes stable ...\n"); while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock) ; trace("mga: pixpll locked !\n"); /* Initialize CRTC registers and remove irq */ crtcset(mga, 0x11, (1<<4), (1<<5)|0x80); for (i = 0; i < 25; i++) crtcset(mga, i, mga->crtc[i], 0xff); /* Initialize CRTC Extension registers */ for (i = 0; i < 9; i++) crtcextset(mga, i, mga->crtcext[i], 0xff); /* Initialize Palette */ mgawrite8(mga, RAMDACIDX, 0); for (i = 0; i < 0xff; i++) mgawrite8(mga, RAMDACPALDATA, i); /* Disable Zoom */ dacset(mga, Dac_Xzoomctrl, 0, 0xff); /* Enable mga mode again ... Just in case :) */ crtcextset(mga, CrtcExt_Miscellaneous, Mgamode, 0); /* Set final misc ... enable mapping ... */ miscset(mga, mga->misc | Misc_rammapen, 0); /* Enable Screen */ seqset(mga, 1, 0, 0xff); p = (uchar*)mga->mmfb; for (i = 0; i < mga->fbsize; i++) *p++ = (0xff & i); trace("mga: Loaded !\n" ); dump_all_regs(mga); trace("mga: Loaded [bis]!\n" ); /* Reenable Cursor */ dacset(mga, Dac_Xcurctrl, cursor, 0xff); ctlr->flag |= Fload; } Ctlr mga4xx = { "mga4xx", /* name */ snarf, /* snarf */ options, /* options */ init, /* init */ load, /* load */ dump, /* dump */ }; Ctlr mga4xxhwgc = { "mga4xxhwgc", /* name */ 0, /* snarf */ 0, /* options */ 0, /* init */ 0, /* load */ dump, /* dump */ };