diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/pc/vgaclgd542x.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/pc/vgaclgd542x.c')
-rwxr-xr-x | sys/src/9/pc/vgaclgd542x.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/sys/src/9/pc/vgaclgd542x.c b/sys/src/9/pc/vgaclgd542x.c new file mode 100755 index 000000000..2a980c3da --- /dev/null +++ b/sys/src/9/pc/vgaclgd542x.c @@ -0,0 +1,277 @@ +#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" + +static int +clgd542xpageset(VGAscr*, int page) +{ + uchar gr09; + int opage; + + if(vgaxi(Seqx, 0x07) & 0xF0) + page = 0; + gr09 = vgaxi(Grx, 0x09); + if(vgaxi(Grx, 0x0B) & 0x20){ + vgaxo(Grx, 0x09, page<<2); + opage = gr09>>2; + } + else{ + vgaxo(Grx, 0x09, page<<4); + opage = gr09>>4; + } + + return opage; +} + +static void +clgd542xpage(VGAscr* scr, int page) +{ + lock(&scr->devlock); + clgd542xpageset(scr, page); + unlock(&scr->devlock); +} + +static void +clgd542xlinear(VGAscr* scr, int, int) +{ + vgalinearpciid(scr, 0x1013, 0); +} + +static void +clgd542xdisable(VGAscr*) +{ + uchar sr12; + + sr12 = vgaxi(Seqx, 0x12); + vgaxo(Seqx, 0x12, sr12 & ~0x01); +} + +static void +clgd542xenable(VGAscr* scr) +{ + uchar sr12; + int mem, x; + + /* + * Disable the cursor. + */ + sr12 = vgaxi(Seqx, 0x12); + vgaxo(Seqx, 0x12, sr12 & ~0x01); + + /* + * Cursor colours. + * Can't call setcolor here as cursor is already locked. + */ + vgaxo(Seqx, 0x12, sr12|0x02); + vgao(PaddrW, 0x00); + vgao(Pdata, Pwhite); + vgao(Pdata, Pwhite); + vgao(Pdata, Pwhite); + vgao(PaddrW, 0x0F); + vgao(Pdata, Pblack); + vgao(Pdata, Pblack); + vgao(Pdata, Pblack); + vgaxo(Seqx, 0x12, sr12); + + mem = 0; + switch(vgaxi(Crtx, 0x27) & ~0x03){ + + case 0x88: /* CL-GD5420 */ + case 0x8C: /* CL-GD5422 */ + case 0x94: /* CL-GD5424 */ + case 0x80: /* CL-GD5425 */ + case 0x90: /* CL-GD5426 */ + case 0x98: /* CL-GD5427 */ + case 0x9C: /* CL-GD5429 */ + /* + * The BIOS leaves the memory size in Seq0A, bits 4 and 3. + * See Technical Reference Manual Appendix E1, Section 1.3.2. + * + * The storage area for the 64x64 cursors is the last 16Kb of + * display memory. + */ + mem = (vgaxi(Seqx, 0x0A)>>3) & 0x03; + break; + + case 0xA0: /* CL-GD5430 */ + case 0xA8: /* CL-GD5434 */ + case 0xAC: /* CL-GD5436 */ + case 0xB8: /* CL-GD5446 */ + case 0x30: /* CL-GD7543 */ + /* + * Attempt to intuit the memory size from the DRAM control + * register. Minimum is 512KB. + * If DRAM bank switching is on then there's double. + */ + x = vgaxi(Seqx, 0x0F); + mem = (x>>3) & 0x03; + if(x & 0x80) + mem++; + break; + + case 0xBC: /* CL-GD5480 */ + mem = 2; /* 1024 = 256<<2 */ + x = vgaxi(Seqx, 0x0F); + if((x & 0x18) == 0x18){ + mem <<= 1; /* 2048 = 256<<3 */ + if(x & 0x80) + mem <<= 2; /* 2048 = 256<<4 */ + } + if(vgaxi(Seqx, 0x17) & 0x80) + mem <<= 1; + break; + + default: /* uh, ah dunno */ + break; + } + scr->storage = ((256<<mem)-16)*1024; + + /* + * Set the current cursor to index 0 + * and turn the 64x64 cursor on. + */ + vgaxo(Seqx, 0x13, 0); + vgaxo(Seqx, 0x12, sr12|0x05); +} + +static void +clgd542xinitcursor(VGAscr* scr, int xo, int yo, int index) +{ + uchar *p, seq07; + uint p0, p1; + int opage, x, y; + + /* + * Is linear addressing turned on? This will determine + * how we access the cursor storage. + */ + seq07 = vgaxi(Seqx, 0x07); + opage = 0; + p = scr->vaddr; + if(!(seq07 & 0xF0)){ + lock(&scr->devlock); + opage = clgd542xpageset(scr, scr->storage>>16); + p += (scr->storage & 0xFFFF); + } + else + p += scr->storage; + p += index*1024; + + for(y = yo; y < 16; y++){ + p0 = scr->set[2*y]; + p1 = scr->set[2*y+1]; + if(xo){ + p0 = (p0<<xo)|(p1>>(8-xo)); + p1 <<= xo; + } + *p++ = p0; + *p++ = p1; + + for(x = 16; x < 64; x += 8) + *p++ = 0x00; + + p0 = scr->clr[2*y]|scr->set[2*y]; + p1 = scr->clr[2*y+1]|scr->set[2*y+1]; + if(xo){ + p0 = (p0<<xo)|(p1>>(8-xo)); + p1 <<= xo; + } + *p++ = p0; + *p++ = p1; + + for(x = 16; x < 64; x += 8) + *p++ = 0x00; + } + while(y < 64+yo){ + for(x = 0; x < 64; x += 8){ + *p++ = 0x00; + *p++ = 0x00; + } + y++; + } + + if(!(seq07 & 0xF0)){ + clgd542xpageset(scr, opage); + unlock(&scr->devlock); + } +} + +static void +clgd542xload(VGAscr* scr, Cursor* curs) +{ + uchar sr12; + + /* + * Disable the cursor. + */ + sr12 = vgaxi(Seqx, 0x12); + vgaxo(Seqx, 0x12, sr12 & ~0x01); + + memmove(&scr->Cursor, curs, sizeof(Cursor)); + clgd542xinitcursor(scr, 0, 0, 0); + + /* + * Enable the cursor. + */ + vgaxo(Seqx, 0x13, 0); + vgaxo(Seqx, 0x12, sr12|0x05); +} + +static int +clgd542xmove(VGAscr* scr, Point p) +{ + int index, x, xo, y, yo; + + index = 0; + if((x = p.x+scr->offset.x) < 0){ + xo = -x; + x = 0; + } + else + xo = 0; + if((y = p.y+scr->offset.y) < 0){ + yo = -y; + y = 0; + } + else + yo = 0; + + if(xo || yo){ + clgd542xinitcursor(scr, xo, yo, 1); + index = 1; + } + vgaxo(Seqx, 0x13, index<<2); + + vgaxo(Seqx, 0x10|((x & 0x07)<<5), (x>>3) & 0xFF); + vgaxo(Seqx, 0x11|((y & 0x07)<<5), (y>>3) & 0xFF); + + return 0; +} + +VGAdev vgaclgd542xdev = { + "clgd542x", + + 0, + 0, + clgd542xpage, + clgd542xlinear, +}; + +VGAcur vgaclgd542xcur = { + "clgd542xhwgc", + + clgd542xenable, + clgd542xdisable, + clgd542xload, + clgd542xmove, +}; |