123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603 |
- /*
- * Matrox G200, G400 and G450.
- * see /sys/src/cmd/aux/vga/mga4xx.c
- */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "io.h"
- #include "../port/error.h"
- #define Image IMAGE
- #include <draw.h>
- #include <memdraw.h>
- #include <cursor.h>
- #include "screen.h"
- enum {
- MATROX = 0x102B,
- MGA4xx = 0x0525,
- MGA200 = 0x0521,
- Kilo = 1024,
- Meg = 1024*1024,
- FCOL = 0x1c24,
- FXRIGHT = 0x1cac,
- FXLEFT = 0x1ca8,
- YDST = 0x1c90,
- YLEN = 0x1c5c,
- DWGCTL = 0x1c00,
- DWG_TRAP = 0x04,
- DWG_BITBLT = 0x08,
- DWG_ILOAD = 0x09,
- DWG_LINEAR = 0x0080,
- DWG_SOLID = 0x0800,
- DWG_ARZERO = 0x1000,
- DWG_SGNZERO = 0x2000,
- DWG_SHIFTZERO = 0x4000,
- DWG_REPLACE = 0x000C0000,
- DWG_REPLACE2 = (DWG_REPLACE | 0x40),
- DWG_XOR = 0x00060010,
- DWG_BFCOL = 0x04000000,
- DWG_BMONOWF = 0x08000000,
- DWG_TRANSC = 0x40000000,
- SRCORG = 0x2cb4,
- PITCH = 0x1c8c,
- DSTORG = 0x2cb8,
- PLNWRT = 0x1c1c,
- ZORG = 0x1c0c,
- MACCESS = 0x1c04,
- STATUS = 0x1e14,
- FXBNDRY = 0x1C84,
- CXBNDRY = 0x1C80,
- YTOP = 0x1C98,
- YBOT = 0x1C9C,
- YDSTLEN = 0x1C88,
- AR0 = 0x1C60,
- AR1 = 0x1C64,
- AR2 = 0x1C68,
- AR3 = 0x1C6C,
- AR4 = 0x1C70,
- AR5 = 0x1C74,
- SGN = 0x1C58,
- SGN_SCANLEFT = 1,
- SGN_SCANRIGHT = 0,
- SGN_SDY_POSITIVE = 0,
- SGN_SDY_NEGATIVE = 4,
- GO = 0x0100,
- FIFOSTATUS = 0x1E10,
- CACHEFLUSH = 0x1FFF,
- CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */
- CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */
- FILL_OPERAND = 0x800c7804,
- };
- static Pcidev*
- mgapcimatch(void)
- {
- Pcidev* p;
-
- p = pcimatch(nil, MATROX, MGA4xx);
- if (p == nil)
- p = pcimatch(nil, MATROX, MGA200);
- return p;
- }
- static ulong
- mga4xxlinear(VGAscr* scr, int* size, int* align)
- {
- ulong aperture, oaperture;
- int oapsize, wasupamem;
- Pcidev * p;
- oaperture = scr->aperture;
- oapsize = scr->apsize;
- wasupamem = scr->isupamem;
- if(p = mgapcimatch()){
- aperture = p->mem[0].bar & ~0x0F;
- if(p->did == MGA4xx)
- *size = 32*Meg;
- else
- *size = 8*Meg;
- }
- else
- aperture = 0;
- if(wasupamem) {
- if(oaperture == aperture)
- return oaperture;
- upafree(oaperture, oapsize);
- }
- scr->isupamem = 0;
- aperture = upamalloc(aperture, *size, *align);
- if(aperture == 0){
- if(wasupamem && upamalloc(oaperture, oapsize, 0)) {
- aperture = oaperture;
- scr->isupamem = 1;
- }
- else
- scr->isupamem = 0;
- }
- else
- scr->isupamem = 1;
- return aperture;
- }
- static void
- mgawrite8(VGAscr* scr, int index, uchar val)
- {
- ((uchar*)scr->io)[index] = val;
- }
- static uchar
- mgaread8(VGAscr* scr, int index)
- {
- return ((uchar*)scr->io)[index];
- }
- static uchar
- crtcextset(VGAscr* scr, int index, uchar set, uchar clr)
- {
- uchar tmp;
- mgawrite8(scr, CRTCEXTIDX, index);
- tmp = mgaread8(scr, CRTCEXTDATA);
- mgawrite8(scr, CRTCEXTIDX, index);
- mgawrite8(scr, CRTCEXTDATA, (tmp & ~clr) | set);
- return tmp;
- }
- static void
- mga4xxenable(VGAscr* scr)
- {
- Pcidev * pci;
- int size, align;
- ulong aperture;
- int i, n, k;
- uchar * p;
- uchar x[16];
- uchar crtcext3;
- /*
- * Only once, can't be disabled for now.
- * scr->io holds the virtual address of
- * the MMIO registers.
- */
- if(scr->io)
- return;
- pci = mgapcimatch();
- if(pci == nil)
- return;
- scr->io = upamalloc(pci->mem[1].bar & ~0x0F, 16*1024, 0);
- if(scr->io == 0)
- return;
- addvgaseg("mga4xxmmio", scr->io, pci->mem[1].size);
- scr->io = (ulong)KADDR(scr->io);
- /* need to map frame buffer here too, so vga can find memory size */
- size = 8*Meg;
- align = 0;
- aperture = mga4xxlinear(scr, &size, &align);
- if(aperture) {
- scr->aperture = aperture;
- addvgaseg("mga4xxscreen", aperture, size);
- /* Find out how much memory is here, some multiple of 2 Meg */
- /* First Set MGA Mode ... */
- crtcext3 = crtcextset(scr, 3, 0x80, 0x00);
- p = (uchar*)aperture;
- n = (size / Meg) / 2;
- for (i = 0; i < n; i++) {
- k = (2*i+1)*Meg;
- p[k] = 0;
- p[k] = i+1;
- *((uchar*)(scr->io + CACHEFLUSH)) = 0;
- x[i] = p[k];
- }
- for(i = 1; i < n; i++)
- if(x[i] != i+1)
- break;
- scr->apsize = 2*i*Meg;
- crtcextset(scr, 3, crtcext3, 0xff);
- }
- }
- enum {
- Index = 0x00, /* Index */
- Data = 0x0A, /* Data */
- Cxlsb = 0x0C, /* Cursor X LSB */
- Cxmsb = 0x0D, /* Cursor X MSB */
- Cylsb = 0x0E, /* Cursor Y LSB */
- Cymsb = 0x0F, /* Cursor Y MSB */
- Icuradrl = 0x04, /* Cursor Base Address Low */
- Icuradrh = 0x05, /* Cursor Base Address High */
- Icctl = 0x06, /* Indirect Cursor Control */
- };
- static void
- dac4xxdisable(VGAscr* scr)
- {
- uchar * dac4xx;
-
- if(scr->io == 0)
- return;
- dac4xx = KADDR(scr->io+0x3C00);
-
- *(dac4xx+Index) = Icctl;
- *(dac4xx+Data) = 0x00;
- }
- static void
- dac4xxload(VGAscr* scr, Cursor* curs)
- {
- int y;
- uchar * p;
- uchar * dac4xx;
- if(scr->io == 0)
- return;
- dac4xx = KADDR(scr->io+0x3C00);
-
- dac4xxdisable(scr);
- p = KADDR(scr->storage);
- for(y = 0; y < 64; y++){
- *p++ = 0; *p++ = 0; *p++ = 0;
- *p++ = 0; *p++ = 0; *p++ = 0;
- if(y <16){
- *p++ = curs->set[1+y*2]|curs->clr[1+2*y];
- *p++ = curs->set[y*2]|curs->clr[2*y];
- } else{
- *p++ = 0; *p++ = 0;
- }
- *p++ = 0; *p++ = 0; *p++ = 0;
- *p++ = 0; *p++ = 0; *p++ = 0;
- if(y <16){
- *p++ = curs->set[1+y*2];
- *p++ = curs->set[y*2];
- } else{
- *p++ = 0; *p++ = 0;
- }
- }
- scr->offset.x = 64 + curs->offset.x;
- scr->offset.y = 64 + curs->offset.y;
- *(dac4xx+Index) = Icctl;
- *(dac4xx+Data) = 0x03;
- }
- static int
- dac4xxmove(VGAscr* scr, Point p)
- {
- int x, y;
- uchar * dac4xx;
- if(scr->io == 0)
- return 1;
- dac4xx = KADDR(scr->io + 0x3C00);
- x = p.x + scr->offset.x;
- y = p.y + scr->offset.y;
- *(dac4xx+Cxlsb) = x & 0xFF;
- *(dac4xx+Cxmsb) = (x>>8) & 0x0F;
- *(dac4xx+Cylsb) = y & 0xFF;
- *(dac4xx+Cymsb) = (y>>8) & 0x0F;
- return 0;
- }
- static void
- dac4xxenable(VGAscr* scr)
- {
- uchar * dac4xx;
- ulong storage;
-
- if(scr->io == 0)
- return;
- dac4xx = KADDR(scr->io+0x3C00);
- dac4xxdisable(scr);
- storage = (scr->apsize - 4096) & ~0x3ff;
- *(dac4xx+Index) = Icuradrl;
- *(dac4xx+Data) = 0xff & (storage >> 10);
- *(dac4xx+Index) = Icuradrh;
- *(dac4xx+Data) = 0xff & (storage >> 18);
- scr->storage = (ulong) KADDR((ulong)scr->aperture + (ulong)storage);
- /* Show X11-Like Cursor */
- *(dac4xx+Index) = Icctl;
- *(dac4xx+Data) = 0x03;
- /* Cursor Color 0 : White */
- *(dac4xx+Index) = 0x08;
- *(dac4xx+Data) = 0xff;
- *(dac4xx+Index) = 0x09;
- *(dac4xx+Data) = 0xff;
- *(dac4xx+Index) = 0x0a;
- *(dac4xx+Data) = 0xff;
- /* Cursor Color 1 : Black */
- *(dac4xx+Index) = 0x0c;
- *(dac4xx+Data) = 0x00;
- *(dac4xx+Index) = 0x0d;
- *(dac4xx+Data) = 0x00;
- *(dac4xx+Index) = 0x0e;
- *(dac4xx+Data) = 0x00;
- /* Cursor Color 2 : Red */
- *(dac4xx+Index) = 0x10;
- *(dac4xx+Data) = 0xff;
- *(dac4xx+Index) = 0x11;
- *(dac4xx+Data) = 0x00;
- *(dac4xx+Index) = 0x12;
- *(dac4xx+Data) = 0x00;
- /*
- * Load, locate and enable the
- * 64x64 cursor in X11 mode.
- */
- dac4xxload(scr, &arrow);
- dac4xxmove(scr, ZP);
- }
- static void
- mga4xxblank(VGAscr* scr, int blank)
- {
- char * cp;
- uchar * mga;
- uchar seq1, crtcext1;
-
- /* blank = 0 -> turn screen on */
- /* blank = 1 -> turn screen off */
- if(scr->io == 0)
- return;
- mga = KADDR(scr->io);
- if (blank == 0) {
- seq1 = 0x00;
- crtcext1 = 0x00;
- } else {
- seq1 = 0x20;
- crtcext1 = 0x10; /* Default value ... : standby */
- cp = getconf("*dpms");
- if (cp) {
- if (cistrcmp(cp, "standby") == 0) {
- crtcext1 = 0x10;
- } else if (cistrcmp(cp, "suspend") == 0) {
- crtcext1 = 0x20;
- } else if (cistrcmp(cp, "off") == 0) {
- crtcext1 = 0x30;
- }
- }
- }
- *(mga + 0x1fc4) = 1;
- seq1 |= *(mga + 0x1fc5) & ~0x20;
- *(mga + 0x1fc5) = seq1;
- *(mga + 0x1fde) = 1;
- crtcext1 |= *(mga + 0x1fdf) & ~0x30;
- *(mga + 0x1fdf) = crtcext1;
- }
- static void
- mgawrite32(uchar * mga, ulong reg, ulong val)
- {
- ulong * l;
- l = (ulong *)(&mga[reg]);
- l[0] = val;
- }
- static ulong
- mgaread32(uchar * mga, ulong reg)
- {
- return *((ulong *)(&mga[reg]));
- }
- static int
- mga4xxfill(VGAscr* scr, Rectangle r, ulong color)
- {
- uchar * mga;
-
- /* Constant Shaded Trapezoids / Rectangle Fills */
- if(scr->io == 0)
- return 0;
- mga = KADDR(scr->io);
- mgawrite32(mga, DWGCTL, 0);
- mgawrite32(mga, FCOL, color);
- mgawrite32(mga, FXRIGHT, r.max.x);
- mgawrite32(mga, FXLEFT, r.min.x);
- mgawrite32(mga, YDST, r.min.y);
- mgawrite32(mga, YLEN, Dy(r));
- mgawrite32(mga, DWGCTL + GO, FILL_OPERAND);
- while (mgaread32(mga, STATUS) & 0x00010000)
- ;
- return 1;
- }
- #define mga_fifo(n) do {} while ((mgaread32(mga, FIFOSTATUS) & 0xFF) < (n))
- static int
- mga4xxscroll(VGAscr* scr, Rectangle r_dst, Rectangle r_src)
- {
- uchar * mga;
- ulong pitch, y;
- ulong width, height, start, end, scandir;
- int ydir;
-
- /* Two-operand Bitblts */
- if(scr->io == 0)
- return 0;
- mga = KADDR(scr->io);
- pitch = Dx(scr->gscreen->r);
- mgawrite32(mga, DWGCTL, 0);
- scandir = 0;
- height = abs(Dy(r_src));
- width = abs(Dx(r_src));
- assert(height == abs(Dy(r_dst)));
- assert(width == abs(Dx(r_dst)));
- if ((r_src.min.y == r_dst.min.y) && (r_src.min.x == r_dst.min.x))
- {
- if (0)
- print("move x,y to x,y !\n");
- return 1;
- }
- ydir = 1;
- if (r_dst.min.y > r_src.min.y)
- {
- if (0)
- print("ydir = -1\n");
- ydir = -1;
- scandir |= 4; // Blit UP
- }
- if (r_dst.min.x > r_src.min.x)
- {
- if (0)
- print("xdir = -1\n");
- scandir |= 1; // Blit Left
- }
- mga_fifo(4);
- if (scandir)
- {
- mgawrite32(mga, DWGCTL, DWG_BITBLT | DWG_SHIFTZERO |
- DWG_SGNZERO | DWG_BFCOL | DWG_REPLACE);
- mgawrite32(mga, SGN, scandir);
- } else
- {
- mgawrite32(mga, DWGCTL, DWG_BITBLT | DWG_SHIFTZERO |
- DWG_BFCOL | DWG_REPLACE);
- }
- mgawrite32(mga, AR5, ydir * pitch);
- width--;
- start = end = r_src.min.x + (r_src.min.y * pitch);
- if ((scandir & 1) == 1)
- {
- start += width;
- } else
- {
- end += width;
- }
- y = r_dst.min.y;
- if ((scandir & 4) == 4)
- {
- start += (height - 1) * pitch;
- end += (height - 1) * pitch;
- y += (height - 1);
- }
- mga_fifo(4);
- mgawrite32(mga, AR0, end);
- mgawrite32(mga, AR3, start);
- mgawrite32(mga, FXBNDRY, ((r_dst.min.x+width)<<16) | r_dst.min.x);
- mgawrite32(mga, YDSTLEN + GO, (y << 16) | height);
-
- if (1)
- {
- while (mgaread32(mga, STATUS) & 0x00010000)
- ;
- }
- return 1;
- }
- static void
- mga4xxdrawinit(VGAscr* scr)
- {
- uchar * mga;
- Pcidev* p;
- p = pcimatch(nil, MATROX, MGA4xx);
- if (p == nil)
- return ;
- if(scr->io == 0)
- return;
- mga = KADDR(scr->io);
- mgawrite32(mga, SRCORG, 0);
- mgawrite32(mga, DSTORG, 0);
- mgawrite32(mga, ZORG, 0);
- mgawrite32(mga, PLNWRT, ~0);
- mgawrite32(mga, FCOL, 0xffff0000);
- mgawrite32(mga, CXBNDRY, 0xFFFF0000);
- mgawrite32(mga, YTOP, 0);
- mgawrite32(mga, YBOT, 0x01FFFFFF);
- mgawrite32(mga, PITCH, Dx(scr->gscreen->r) & ((1 << 13) - 1));
- switch(scr->gscreen->depth) {
- case 8:
- mgawrite32(mga, MACCESS, 0);
- break;
- case 32:
- mgawrite32(mga, MACCESS, 2);
- break;
- default:
- return; /* depth not supported ! */
- }
- scr->fill = mga4xxfill;
- scr->scroll = mga4xxscroll;
- scr->blank = mga4xxblank;
- }
- VGAdev vgamga4xxdev = {
- "mga4xx",
- mga4xxenable, /* enable */
- 0, /* disable */
- 0, /* page */
- mga4xxlinear, /* linear */
- mga4xxdrawinit,
- };
- VGAcur vgamga4xxcur = {
- "mga4xxhwgc",
- dac4xxenable,
- dac4xxdisable,
- dac4xxload,
- dac4xxmove,
- };
|