xref: /plan9/sys/src/9/pc/vgai81x.c (revision 74f16c8187aab477889167f2422d0597b1b7d0ff)
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