19a747e4fSDavid du Colombier #include "u.h"
29a747e4fSDavid du Colombier #include "../port/lib.h"
39a747e4fSDavid du Colombier #include "mem.h"
49a747e4fSDavid du Colombier #include "dat.h"
59a747e4fSDavid du Colombier #include "fns.h"
69a747e4fSDavid du Colombier #include "io.h"
79a747e4fSDavid du Colombier #include "../port/error.h"
89a747e4fSDavid du Colombier
99a747e4fSDavid du Colombier #define Image IMAGE
109a747e4fSDavid du Colombier #include <draw.h>
119a747e4fSDavid du Colombier #include <memdraw.h>
129a747e4fSDavid du Colombier #include <cursor.h>
139a747e4fSDavid du Colombier #include "screen.h"
149a747e4fSDavid du Colombier
159a747e4fSDavid du Colombier typedef struct
169a747e4fSDavid du Colombier {
179a747e4fSDavid du Colombier ushort ctl;
189a747e4fSDavid du Colombier ushort pad;
199a747e4fSDavid du Colombier ulong base;
209a747e4fSDavid du Colombier ulong pos;
219a747e4fSDavid du Colombier } CursorI81x;
229a747e4fSDavid du Colombier
239a747e4fSDavid du Colombier enum {
249a747e4fSDavid du Colombier Fbsize = 8*MB,
259a747e4fSDavid du Colombier
269a747e4fSDavid du Colombier hwCur = 0x70080,
27*74f16c81SDavid du Colombier SRX = 0x3c4,
28*74f16c81SDavid du Colombier DPMSsync = 0x5002,
299a747e4fSDavid du Colombier };
309a747e4fSDavid du Colombier
31*74f16c81SDavid du Colombier static void
i81xblank(VGAscr * scr,int blank)32*74f16c81SDavid du Colombier i81xblank(VGAscr *scr, int blank)
33*74f16c81SDavid du Colombier {
34*74f16c81SDavid du Colombier char *srx, *srxd, *dpms;
35*74f16c81SDavid du Colombier char sr01, mode;
36*74f16c81SDavid du Colombier
37*74f16c81SDavid du Colombier srx = (char *)scr->mmio+SRX;
38*74f16c81SDavid du Colombier srxd = srx+1;
39*74f16c81SDavid du Colombier dpms = (char *)scr->mmio+DPMSsync;
40*74f16c81SDavid du Colombier
41*74f16c81SDavid du Colombier *srx = 0x01;
42*74f16c81SDavid du Colombier sr01 = *srxd & ~0x20;
43*74f16c81SDavid du Colombier mode = *dpms & 0xf0;
44*74f16c81SDavid du Colombier
45*74f16c81SDavid du Colombier if(blank) {
46*74f16c81SDavid du Colombier sr01 |= 0x20;
47*74f16c81SDavid du Colombier mode |= 0x0a;
48*74f16c81SDavid du Colombier }
49*74f16c81SDavid du Colombier *srxd = sr01;
50*74f16c81SDavid du Colombier *dpms = mode;
51*74f16c81SDavid du Colombier }
52*74f16c81SDavid du Colombier
539a747e4fSDavid du Colombier static Pcidev *
i81xpcimatch(void)549a747e4fSDavid du Colombier i81xpcimatch(void)
559a747e4fSDavid du Colombier {
569a747e4fSDavid du Colombier Pcidev *p;
579a747e4fSDavid du Colombier
589a747e4fSDavid du Colombier p = nil;
599a747e4fSDavid du Colombier while((p = pcimatch(p, 0x8086, 0)) != nil){
609a747e4fSDavid du Colombier switch(p->did){
619a747e4fSDavid du Colombier default:
629a747e4fSDavid du Colombier continue;
639a747e4fSDavid du Colombier case 0x7121:
649a747e4fSDavid du Colombier case 0x7123:
659a747e4fSDavid du Colombier case 0x7125:
669a747e4fSDavid du Colombier case 0x1102:
679a747e4fSDavid du Colombier case 0x1112:
689a747e4fSDavid du Colombier case 0x1132:
693ff48bf5SDavid du Colombier case 0x3577: /* IBM R31 uses intel 830M chipset */
709a747e4fSDavid du Colombier return p;
719a747e4fSDavid du Colombier }
729a747e4fSDavid du Colombier }
739a747e4fSDavid du Colombier return nil;
749a747e4fSDavid du Colombier }
759a747e4fSDavid du Colombier
769a747e4fSDavid du Colombier static void
i81xenable(VGAscr * scr)779a747e4fSDavid du Colombier i81xenable(VGAscr* scr)
789a747e4fSDavid du Colombier {
799a747e4fSDavid du Colombier Pcidev *p;
804de34a7eSDavid du Colombier int size;
819a747e4fSDavid du Colombier Mach *mach0;
824de34a7eSDavid du Colombier ulong *pgtbl, *rp, cursor, *pte, fbuf, fbend;
839a747e4fSDavid du Colombier
844de34a7eSDavid du Colombier if(scr->mmio)
859a747e4fSDavid du Colombier return;
869a747e4fSDavid du Colombier p = i81xpcimatch();
879a747e4fSDavid du Colombier if(p == nil)
889a747e4fSDavid du Colombier return;
894de34a7eSDavid du Colombier scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
904de34a7eSDavid du Colombier if(scr->mmio == 0)
919a747e4fSDavid du Colombier return;
924de34a7eSDavid du Colombier addvgaseg("i81xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
939a747e4fSDavid du Colombier
949a747e4fSDavid du Colombier /* allocate page table */
954de34a7eSDavid du Colombier pgtbl = xspanalloc(64*1024, BY2PG, 0);
964de34a7eSDavid du Colombier scr->mmio[0x2020/4] = PADDR(pgtbl) | 1;
979a747e4fSDavid du Colombier
989a747e4fSDavid du Colombier size = p->mem[0].size;
994de34a7eSDavid du Colombier if(size > 0)
1004de34a7eSDavid du Colombier size = Fbsize;
1014de34a7eSDavid du Colombier vgalinearaddr(scr, p->mem[0].bar&~0xF, size);
1024de34a7eSDavid du Colombier addvgaseg("i81xscreen", p->mem[0].bar&~0xF, size);
1034de34a7eSDavid du Colombier
1044de34a7eSDavid du Colombier /*
1054de34a7eSDavid du Colombier * allocate backing store for frame buffer
1064de34a7eSDavid du Colombier * and populate device page tables.
1074de34a7eSDavid du Colombier */
1084de34a7eSDavid du Colombier fbuf = PADDR(xspanalloc(size, BY2PG, 0));
1094de34a7eSDavid du Colombier fbend = PGROUND(fbuf+size);
1104de34a7eSDavid du Colombier rp = scr->mmio+0x10000/4;
1114de34a7eSDavid du Colombier while(fbuf < fbend) {
1124de34a7eSDavid du Colombier *rp++ = fbuf | 1;
1134de34a7eSDavid du Colombier fbuf += BY2PG;
1149a747e4fSDavid du Colombier }
1159a747e4fSDavid du Colombier
1169a747e4fSDavid du Colombier /*
1179a747e4fSDavid du Colombier * allocate space for the cursor data in system memory.
1189a747e4fSDavid du Colombier * must be uncached.
1199a747e4fSDavid du Colombier */
1209a747e4fSDavid du Colombier cursor = (ulong)xspanalloc(BY2PG, BY2PG, 0);
1219a747e4fSDavid du Colombier mach0 = MACHP(0);
1229a747e4fSDavid du Colombier pte = mmuwalk(mach0->pdb, cursor, 2, 0);
1239a747e4fSDavid du Colombier if(pte == nil)
1244de34a7eSDavid du Colombier panic("i81x cursor mmuwalk");
1259a747e4fSDavid du Colombier *pte |= PTEUNCACHED;
1264de34a7eSDavid du Colombier scr->storage = cursor;
127*74f16c81SDavid du Colombier
128*74f16c81SDavid du Colombier scr->blank = i81xblank;
129*74f16c81SDavid du Colombier hwblank = 1;
1309a747e4fSDavid du Colombier }
1319a747e4fSDavid du Colombier
1329a747e4fSDavid du Colombier static void
i81xcurdisable(VGAscr * scr)1339a747e4fSDavid du Colombier i81xcurdisable(VGAscr* scr)
1349a747e4fSDavid du Colombier {
1359a747e4fSDavid du Colombier CursorI81x *hwcurs;
1369a747e4fSDavid du Colombier
1374de34a7eSDavid du Colombier if(scr->mmio == 0)
1389a747e4fSDavid du Colombier return;
1394de34a7eSDavid du Colombier hwcurs = (void*)((uchar*)scr->mmio+hwCur);
1409a747e4fSDavid du Colombier hwcurs->ctl = (1<<4);
1419a747e4fSDavid du Colombier }
1429a747e4fSDavid du Colombier
1439a747e4fSDavid du Colombier static void
i81xcurload(VGAscr * scr,Cursor * curs)1449a747e4fSDavid du Colombier i81xcurload(VGAscr* scr, Cursor* curs)
1459a747e4fSDavid du Colombier {
1469a747e4fSDavid du Colombier int y;
1479a747e4fSDavid du Colombier uchar *p;
1489a747e4fSDavid du Colombier CursorI81x *hwcurs;
1499a747e4fSDavid du Colombier
1504de34a7eSDavid du Colombier if(scr->mmio == 0)
1519a747e4fSDavid du Colombier return;
1524de34a7eSDavid du Colombier hwcurs = (void*)((uchar*)scr->mmio+hwCur);
1539a747e4fSDavid du Colombier
1549a747e4fSDavid du Colombier /*
1559a747e4fSDavid du Colombier * Disable the cursor then load the new image in
1569a747e4fSDavid du Colombier * the top-left of the 32x32 array.
1579a747e4fSDavid du Colombier * Unused portions of the image have been initialised to be
1589a747e4fSDavid du Colombier * transparent.
1599a747e4fSDavid du Colombier */
1609a747e4fSDavid du Colombier hwcurs->ctl = (1<<4);
1614de34a7eSDavid du Colombier p = (uchar*)scr->storage;
1629a747e4fSDavid du Colombier for(y = 0; y < 16; y += 2) {
1639a747e4fSDavid du Colombier *p++ = ~(curs->clr[2*y]|curs->set[2*y]);
1649a747e4fSDavid du Colombier *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
1659a747e4fSDavid du Colombier p += 2;
1669a747e4fSDavid du Colombier *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
1679a747e4fSDavid du Colombier *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
1689a747e4fSDavid du Colombier p += 2;
1699a747e4fSDavid du Colombier *p++ = curs->set[2*y];
1709a747e4fSDavid du Colombier *p++ = curs->set[2*y+1];
1719a747e4fSDavid du Colombier p += 2;
1729a747e4fSDavid du Colombier *p++ = curs->set[2*y+2];
1739a747e4fSDavid du Colombier *p++ = curs->set[2*y+3];
1749a747e4fSDavid du Colombier p += 2;
1759a747e4fSDavid du Colombier }
1769a747e4fSDavid du Colombier
1779a747e4fSDavid du Colombier /*
1789a747e4fSDavid du Colombier * Save the cursor hotpoint and enable the cursor.
1799a747e4fSDavid du Colombier * The 0,0 cursor point is top-left.
1809a747e4fSDavid du Colombier */
1819a747e4fSDavid du Colombier scr->offset.x = curs->offset.x;
1829a747e4fSDavid du Colombier scr->offset.y = curs->offset.y;
1839a747e4fSDavid du Colombier hwcurs->ctl = (1<<4)|1;
1849a747e4fSDavid du Colombier }
1859a747e4fSDavid du Colombier
1869a747e4fSDavid du Colombier static int
i81xcurmove(VGAscr * scr,Point p)1879a747e4fSDavid du Colombier i81xcurmove(VGAscr* scr, Point p)
1889a747e4fSDavid du Colombier {
1899a747e4fSDavid du Colombier int x, y;
1909a747e4fSDavid du Colombier ulong pos;
1919a747e4fSDavid du Colombier CursorI81x *hwcurs;
1929a747e4fSDavid du Colombier
1934de34a7eSDavid du Colombier if(scr->mmio == 0)
1949a747e4fSDavid du Colombier return 1;
1954de34a7eSDavid du Colombier hwcurs = (void*)((uchar*)scr->mmio+hwCur);
1969a747e4fSDavid du Colombier
1979a747e4fSDavid du Colombier x = p.x+scr->offset.x;
1989a747e4fSDavid du Colombier y = p.y+scr->offset.y;
1999a747e4fSDavid du Colombier pos = 0;
2009a747e4fSDavid du Colombier if(x < 0) {
2019a747e4fSDavid du Colombier pos |= (1<<15);
2029a747e4fSDavid du Colombier x = -x;
2039a747e4fSDavid du Colombier }
2049a747e4fSDavid du Colombier if(y < 0) {
2059a747e4fSDavid du Colombier pos |= (1<<31);
2069a747e4fSDavid du Colombier y = -y;
2079a747e4fSDavid du Colombier }
2089a747e4fSDavid du Colombier pos |= ((y&0x7ff)<<16)|(x&0x7ff);
2099a747e4fSDavid du Colombier hwcurs->pos = pos;
2109a747e4fSDavid du Colombier
2119a747e4fSDavid du Colombier return 0;
2129a747e4fSDavid du Colombier }
2139a747e4fSDavid du Colombier
2149a747e4fSDavid du Colombier static void
i81xcurenable(VGAscr * scr)2159a747e4fSDavid du Colombier i81xcurenable(VGAscr* scr)
2169a747e4fSDavid du Colombier {
2179a747e4fSDavid du Colombier int i;
2189a747e4fSDavid du Colombier uchar *p;
2199a747e4fSDavid du Colombier CursorI81x *hwcurs;
2209a747e4fSDavid du Colombier
2219a747e4fSDavid du Colombier i81xenable(scr);
2224de34a7eSDavid du Colombier if(scr->mmio == 0)
2239a747e4fSDavid du Colombier return;
2244de34a7eSDavid du Colombier hwcurs = (void*)((uchar*)scr->mmio+hwCur);
2259a747e4fSDavid du Colombier
2269a747e4fSDavid du Colombier /*
2279a747e4fSDavid du Colombier * Initialise the 32x32 cursor to be transparent in 2bpp mode.
2289a747e4fSDavid du Colombier */
2294de34a7eSDavid du Colombier hwcurs->base = PADDR(scr->storage);
2304de34a7eSDavid du Colombier p = (uchar*)scr->storage;
2319a747e4fSDavid du Colombier for(i = 0; i < 32/2; i++) {
2329a747e4fSDavid du Colombier memset(p, 0xff, 8);
2339a747e4fSDavid du Colombier memset(p+8, 0, 8);
2349a747e4fSDavid du Colombier p += 16;
2359a747e4fSDavid du Colombier }
2369a747e4fSDavid du Colombier /*
2379a747e4fSDavid du Colombier * Load, locate and enable the 32x32 cursor in 2bpp mode.
2389a747e4fSDavid du Colombier */
2399a747e4fSDavid du Colombier i81xcurload(scr, &arrow);
2409a747e4fSDavid du Colombier i81xcurmove(scr, ZP);
2419a747e4fSDavid du Colombier }
2429a747e4fSDavid du Colombier
2439a747e4fSDavid du Colombier VGAdev vgai81xdev = {
2449a747e4fSDavid du Colombier "i81x",
2459a747e4fSDavid du Colombier
2469a747e4fSDavid du Colombier i81xenable,
2479a747e4fSDavid du Colombier nil,
2489a747e4fSDavid du Colombier nil,
2494de34a7eSDavid du Colombier nil,
2509a747e4fSDavid du Colombier };
2519a747e4fSDavid du Colombier
2529a747e4fSDavid du Colombier VGAcur vgai81xcur = {
2539a747e4fSDavid du Colombier "i81xhwgc",
2549a747e4fSDavid du Colombier
2559a747e4fSDavid du Colombier i81xcurenable,
2569a747e4fSDavid du Colombier i81xcurdisable,
2579a747e4fSDavid du Colombier i81xcurload,
2589a747e4fSDavid du Colombier i81xcurmove,
2599a747e4fSDavid du Colombier };
260