xref: /plan9/sys/src/9/pc/vgaet4000.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
159cc4ca5SDavid du Colombier #include "u.h"
259cc4ca5SDavid du Colombier #include "../port/lib.h"
359cc4ca5SDavid du Colombier #include "mem.h"
459cc4ca5SDavid du Colombier #include "dat.h"
559cc4ca5SDavid du Colombier #include "fns.h"
6*4de34a7eSDavid du Colombier #include "io.h"
759cc4ca5SDavid du Colombier #include "../port/error.h"
859cc4ca5SDavid du Colombier 
959cc4ca5SDavid du Colombier #define	Image	IMAGE
1059cc4ca5SDavid du Colombier #include <draw.h>
1159cc4ca5SDavid du Colombier #include <memdraw.h>
1259cc4ca5SDavid du Colombier #include <cursor.h>
1359cc4ca5SDavid du Colombier #include "screen.h"
1459cc4ca5SDavid du Colombier 
1559cc4ca5SDavid du Colombier static void
setet4000page(int page)1659cc4ca5SDavid du Colombier setet4000page(int page)
1759cc4ca5SDavid du Colombier {
1859cc4ca5SDavid du Colombier 	uchar p;
1959cc4ca5SDavid du Colombier 
2059cc4ca5SDavid du Colombier 	p = page & 0x0F;
2159cc4ca5SDavid du Colombier 	p |= p<<4;
2259cc4ca5SDavid du Colombier 	outb(0x3CD, p);
2359cc4ca5SDavid du Colombier 
2459cc4ca5SDavid du Colombier 	p = (page & 0x30);
2559cc4ca5SDavid du Colombier 	p |= p>>4;
2659cc4ca5SDavid du Colombier 	outb(0x3CB, p);
2759cc4ca5SDavid du Colombier }
2859cc4ca5SDavid du Colombier 
2959cc4ca5SDavid du Colombier static void
et4000page(VGAscr * scr,int page)3059cc4ca5SDavid du Colombier et4000page(VGAscr *scr, int page)
3159cc4ca5SDavid du Colombier {
3259cc4ca5SDavid du Colombier 	lock(&scr->devlock);
3359cc4ca5SDavid du Colombier 	setet4000page(page);
3459cc4ca5SDavid du Colombier 	unlock(&scr->devlock);
3559cc4ca5SDavid du Colombier }
3659cc4ca5SDavid du Colombier 
3759cc4ca5SDavid du Colombier static void
et4000disable(VGAscr *)3859cc4ca5SDavid du Colombier et4000disable(VGAscr*)
3959cc4ca5SDavid du Colombier {
4059cc4ca5SDavid du Colombier 	uchar imaF7;
4159cc4ca5SDavid du Colombier 
4259cc4ca5SDavid du Colombier 	outb(0x217A, 0xF7);
4359cc4ca5SDavid du Colombier 	imaF7 = inb(0x217B) & ~0x80;
4459cc4ca5SDavid du Colombier 	outb(0x217B, imaF7);
4559cc4ca5SDavid du Colombier }
4659cc4ca5SDavid du Colombier 
4759cc4ca5SDavid du Colombier static void
et4000enable(VGAscr * scr)4859cc4ca5SDavid du Colombier et4000enable(VGAscr *scr)
4959cc4ca5SDavid du Colombier {
5059cc4ca5SDavid du Colombier 	uchar imaF7;
5159cc4ca5SDavid du Colombier 
5259cc4ca5SDavid du Colombier 	et4000disable(scr);
5359cc4ca5SDavid du Colombier 
5459cc4ca5SDavid du Colombier 	/*
5559cc4ca5SDavid du Colombier 	 * Configure CRTCB for Sprite, 64x64,
5659cc4ca5SDavid du Colombier 	 * CRTC pixel overlay.
5759cc4ca5SDavid du Colombier 	 */
5859cc4ca5SDavid du Colombier 	outb(0x217A, 0xEF);
5959cc4ca5SDavid du Colombier 	outb(0x217B, 0x02);
6059cc4ca5SDavid du Colombier 
6159cc4ca5SDavid du Colombier 	/*
6259cc4ca5SDavid du Colombier 	 * Cursor goes in the top left corner
6359cc4ca5SDavid du Colombier 	 * of the Sprite area, so the horizontal and
6459cc4ca5SDavid du Colombier 	 * vertical presets are 0.
6559cc4ca5SDavid du Colombier 	 */
6659cc4ca5SDavid du Colombier 	outb(0x217A, 0xE2);
6759cc4ca5SDavid du Colombier 	outb(0x217B, 0x00);
6859cc4ca5SDavid du Colombier 	outb(0x217A, 0xE3);
6959cc4ca5SDavid du Colombier 	outb(0x217B, 0x00);
7059cc4ca5SDavid du Colombier 
7159cc4ca5SDavid du Colombier 	outb(0x217A, 0xE6);
7259cc4ca5SDavid du Colombier 	outb(0x217B, 0x00);
7359cc4ca5SDavid du Colombier 	outb(0x217A, 0xE7);
7459cc4ca5SDavid du Colombier 	outb(0x217B, 0x00);
7559cc4ca5SDavid du Colombier 
7659cc4ca5SDavid du Colombier 	/*
7759cc4ca5SDavid du Colombier 	 * Find a place for the cursor data in display memory.
7859cc4ca5SDavid du Colombier 	 * Must be on a "doubleword" boundary, but put it on a
7959cc4ca5SDavid du Colombier 	 * 1024-byte boundary so that there's no danger of it
8059cc4ca5SDavid du Colombier 	 * crossing a page.
8159cc4ca5SDavid du Colombier 	 */
8259cc4ca5SDavid du Colombier 	scr->storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024;
8359cc4ca5SDavid du Colombier 	scr->storage *= 1024/4;
8459cc4ca5SDavid du Colombier 	outb(0x217A, 0xE8);
8559cc4ca5SDavid du Colombier 	outb(0x217B, scr->storage & 0xFF);
8659cc4ca5SDavid du Colombier 	outb(0x217A, 0xE9);
8759cc4ca5SDavid du Colombier 	outb(0x217B, (scr->storage>>8) & 0xFF);
8859cc4ca5SDavid du Colombier 	outb(0x217A, 0xEA);
8959cc4ca5SDavid du Colombier 	outb(0x217B, (scr->storage>>16) & 0x0F);
9059cc4ca5SDavid du Colombier 	scr->storage *= 4;
9159cc4ca5SDavid du Colombier 
9259cc4ca5SDavid du Colombier 	/*
9359cc4ca5SDavid du Colombier 	 * Row offset in "quadwords". Must be 2 for Sprite.
9459cc4ca5SDavid du Colombier 	 * Bag the pixel-panning.
9559cc4ca5SDavid du Colombier 	 * Colour depth, must be 2 for Sprite.
9659cc4ca5SDavid du Colombier 	 */
9759cc4ca5SDavid du Colombier 	outb(0x217A, 0xEB);
9859cc4ca5SDavid du Colombier 	outb(0x217B, 0x02);
9959cc4ca5SDavid du Colombier 	outb(0x217A, 0xEC);
10059cc4ca5SDavid du Colombier 	outb(0x217B, 0x00);
10159cc4ca5SDavid du Colombier 
10259cc4ca5SDavid du Colombier 	outb(0x217A, 0xED);
10359cc4ca5SDavid du Colombier 	outb(0x217B, 0x00);
10459cc4ca5SDavid du Colombier 
10559cc4ca5SDavid du Colombier 	outb(0x217A, 0xEE);
10659cc4ca5SDavid du Colombier //	if(vgascreen.ldepth == 3)
10759cc4ca5SDavid du Colombier 		outb(0x217B, 0x01);
10859cc4ca5SDavid du Colombier //	else
10959cc4ca5SDavid du Colombier //		outb(0x217B, 0x00);
11059cc4ca5SDavid du Colombier 
11159cc4ca5SDavid du Colombier 	/*
11259cc4ca5SDavid du Colombier 	 * Enable the CRTCB/Sprite.
11359cc4ca5SDavid du Colombier 	 */
11459cc4ca5SDavid du Colombier 	outb(0x217A, 0xF7);
11559cc4ca5SDavid du Colombier 	imaF7 = inb(0x217B);
11659cc4ca5SDavid du Colombier 	outb(0x217B, 0x80|imaF7);
11759cc4ca5SDavid du Colombier }
11859cc4ca5SDavid du Colombier 
11959cc4ca5SDavid du Colombier static void
et4000load(VGAscr * scr,Cursor * c)12059cc4ca5SDavid du Colombier et4000load(VGAscr *scr, Cursor *c)
12159cc4ca5SDavid du Colombier {
12259cc4ca5SDavid du Colombier 	uchar p0, p1, *mem;
12359cc4ca5SDavid du Colombier 	int i, x, y;
12459cc4ca5SDavid du Colombier 	ushort p;
12559cc4ca5SDavid du Colombier 	uchar clr[2*16], set[2*16];
12659cc4ca5SDavid du Colombier 
12759cc4ca5SDavid du Colombier 	/*
12859cc4ca5SDavid du Colombier 	 * Lock the display memory so we can update the
12959cc4ca5SDavid du Colombier 	 * cursor bitmap if necessary.
13059cc4ca5SDavid du Colombier 	 */
13159cc4ca5SDavid du Colombier 	lock(&scr->devlock);
13259cc4ca5SDavid du Colombier 
13359cc4ca5SDavid du Colombier 	/*
13459cc4ca5SDavid du Colombier 	 * Disable the cursor.
13559cc4ca5SDavid du Colombier 	 * Set the display page (do we need to restore
13659cc4ca5SDavid du Colombier 	 * the current contents when done?) and the
13759cc4ca5SDavid du Colombier 	 * pointer to the two planes. What if this crosses
13859cc4ca5SDavid du Colombier 	 * into a new page?
13959cc4ca5SDavid du Colombier 	 */
14059cc4ca5SDavid du Colombier 	et4000disable(scr);
14159cc4ca5SDavid du Colombier 
14259cc4ca5SDavid du Colombier 	setet4000page(scr->storage>>16);
143*4de34a7eSDavid du Colombier 	mem = (uchar*)scr->vaddr + (scr->storage & 0xFFFF);
14459cc4ca5SDavid du Colombier 
14559cc4ca5SDavid du Colombier 	/*
14659cc4ca5SDavid du Colombier 	 * Initialise the 64x64 cursor RAM array. There are 2 planes,
14759cc4ca5SDavid du Colombier 	 * p0 and p1. Data is written 4 pixels per byte, with p1 the
14859cc4ca5SDavid du Colombier 	 * MS bit of each pixel.
14959cc4ca5SDavid du Colombier 	 * The cursor mode gives the following truth table:
15059cc4ca5SDavid du Colombier 	 *	p1 p0	colour
15159cc4ca5SDavid du Colombier 	 *	 0  0	Sprite Colour 0 (defined as 0x00)
15259cc4ca5SDavid du Colombier 	 *	 0  1	Sprite Colour 1 (defined as 0xFF)
15359cc4ca5SDavid du Colombier 	 *	 1  0	Transparent (allow CRTC pixel pass through)
15459cc4ca5SDavid du Colombier 	 *	 1  1	Invert (allow CRTC pixel invert through)
15559cc4ca5SDavid du Colombier 	 * Put the cursor into the top-left of the 64x64 array.
15659cc4ca5SDavid du Colombier 	 *
15759cc4ca5SDavid du Colombier 	 * This is almost certainly wrong, since it has not
15859cc4ca5SDavid du Colombier 	 * been updated for the 3rd edition color values.
15959cc4ca5SDavid du Colombier 	 */
16059cc4ca5SDavid du Colombier 	memmove(clr, c->clr, sizeof(clr));
16159cc4ca5SDavid du Colombier //	pixreverse(clr, sizeof(clr), 0);
16259cc4ca5SDavid du Colombier 	memmove(set, c->set, sizeof(set));
16359cc4ca5SDavid du Colombier //	pixreverse(set, sizeof(set), 0);
16459cc4ca5SDavid du Colombier 	for(y = 0; y < 64; y++){
16559cc4ca5SDavid du Colombier 		for(x = 0; x < 64/8; x++){
16659cc4ca5SDavid du Colombier 			if(x < 16/8 && y < 16){
16759cc4ca5SDavid du Colombier 				p0 = clr[x+y*2];
16859cc4ca5SDavid du Colombier 				p1 = set[x+y*2];
16959cc4ca5SDavid du Colombier 
17059cc4ca5SDavid du Colombier 				p = 0x0000;
17159cc4ca5SDavid du Colombier 				for(i = 0; i < 8; i++){
1729a747e4fSDavid du Colombier 					if(p1 & (1<<(7-i))){
1739a747e4fSDavid du Colombier 						/* nothing to do */
1749a747e4fSDavid du Colombier 					}
17559cc4ca5SDavid du Colombier 					else if(p0 & (1<<(7-i)))
17659cc4ca5SDavid du Colombier 						p |= 0x01<<(2*i);
17759cc4ca5SDavid du Colombier 					else
17859cc4ca5SDavid du Colombier 						p |= 0x02<<(2*i);
17959cc4ca5SDavid du Colombier 				}
18059cc4ca5SDavid du Colombier 				*mem++ = p & 0xFF;
18159cc4ca5SDavid du Colombier 				*mem++ = (p>>8) & 0xFF;
18259cc4ca5SDavid du Colombier 			}
18359cc4ca5SDavid du Colombier 			else {
18459cc4ca5SDavid du Colombier 				*mem++ = 0xAA;
18559cc4ca5SDavid du Colombier 				*mem++ = 0xAA;
18659cc4ca5SDavid du Colombier 			}
18759cc4ca5SDavid du Colombier 		}
18859cc4ca5SDavid du Colombier 	}
18959cc4ca5SDavid du Colombier 
19059cc4ca5SDavid du Colombier 	/*
19159cc4ca5SDavid du Colombier 	 * enable the cursor.
19259cc4ca5SDavid du Colombier 	 */
19359cc4ca5SDavid du Colombier 	outb(0x217A, 0xF7);
19459cc4ca5SDavid du Colombier 	p = inb(0x217B)|0x80;
19559cc4ca5SDavid du Colombier 	outb(0x217B, p);
19659cc4ca5SDavid du Colombier 
19759cc4ca5SDavid du Colombier 	unlock(&scr->devlock);
19859cc4ca5SDavid du Colombier }
19959cc4ca5SDavid du Colombier 
20059cc4ca5SDavid du Colombier static int
et4000move(VGAscr * scr,Point p)20159cc4ca5SDavid du Colombier et4000move(VGAscr *scr, Point p)
20259cc4ca5SDavid du Colombier {
20359cc4ca5SDavid du Colombier 	int x, xo, y, yo;
20459cc4ca5SDavid du Colombier 
20559cc4ca5SDavid du Colombier 	if(canlock(&scr->devlock) == 0)
20659cc4ca5SDavid du Colombier 		return 1;
20759cc4ca5SDavid du Colombier 
20859cc4ca5SDavid du Colombier 	/*
20959cc4ca5SDavid du Colombier 	 * Mustn't position the cursor offscreen even partially,
21059cc4ca5SDavid du Colombier 	 * or it disappears. Therefore, if x or y is -ve, adjust the
21159cc4ca5SDavid du Colombier 	 * cursor presets instead.
21259cc4ca5SDavid du Colombier 	 */
21359cc4ca5SDavid du Colombier 	if((x = p.x+scr->offset.x) < 0){
21459cc4ca5SDavid du Colombier 		xo = -x;
21559cc4ca5SDavid du Colombier 		x = 0;
21659cc4ca5SDavid du Colombier 	}
21759cc4ca5SDavid du Colombier 	else
21859cc4ca5SDavid du Colombier 		xo = 0;
21959cc4ca5SDavid du Colombier 	if((y = p.y+scr->offset.y) < 0){
22059cc4ca5SDavid du Colombier 		yo = -y;
22159cc4ca5SDavid du Colombier 		y = 0;
22259cc4ca5SDavid du Colombier 	}
22359cc4ca5SDavid du Colombier 	else
22459cc4ca5SDavid du Colombier 		yo = 0;
22559cc4ca5SDavid du Colombier 
22659cc4ca5SDavid du Colombier 	/*
22759cc4ca5SDavid du Colombier 	 * The cursor image is jerky if we don't do this.
22859cc4ca5SDavid du Colombier 	 * The cursor information is probably fetched from
22959cc4ca5SDavid du Colombier 	 * display memory during the horizontal blank active
23059cc4ca5SDavid du Colombier 	 * time and it doesn't like it if the coordinates
23159cc4ca5SDavid du Colombier 	 * are changed underneath.
23259cc4ca5SDavid du Colombier 	 */
23359cc4ca5SDavid du Colombier 	while((vgai(Status1) & 0x08) == 0)
23459cc4ca5SDavid du Colombier 		;
23559cc4ca5SDavid du Colombier 
23659cc4ca5SDavid du Colombier 	outb(0x217A, 0xE2);
23759cc4ca5SDavid du Colombier 	outb(0x217B, xo);
23859cc4ca5SDavid du Colombier 
23959cc4ca5SDavid du Colombier 	outb(0x217A, 0xE6);
24059cc4ca5SDavid du Colombier 	outb(0x217B, yo);
24159cc4ca5SDavid du Colombier 
24259cc4ca5SDavid du Colombier 	outb(0x217A, 0xE1);
24359cc4ca5SDavid du Colombier 	outb(0x217B, (x>>8) & 0xFF);
24459cc4ca5SDavid du Colombier 	outb(0x217A, 0xE0);
24559cc4ca5SDavid du Colombier 	outb(0x217B, x & 0xFF);
24659cc4ca5SDavid du Colombier 	outb(0x217A, 0xE5);
24759cc4ca5SDavid du Colombier 	outb(0x217B, (y>>8) & 0xFF);
24859cc4ca5SDavid du Colombier 	outb(0x217A, 0xE4);
24959cc4ca5SDavid du Colombier 	outb(0x217B, y & 0xFF);
25059cc4ca5SDavid du Colombier 
25159cc4ca5SDavid du Colombier 	unlock(&scr->devlock);
25259cc4ca5SDavid du Colombier 	return 0;
25359cc4ca5SDavid du Colombier }
25459cc4ca5SDavid du Colombier 
25559cc4ca5SDavid du Colombier VGAcur vgaet4000cur = {
25659cc4ca5SDavid du Colombier 	"et4000hwgc",
25759cc4ca5SDavid du Colombier 
25859cc4ca5SDavid du Colombier 	et4000enable,
25959cc4ca5SDavid du Colombier 	et4000disable,
26059cc4ca5SDavid du Colombier 	et4000load,
26159cc4ca5SDavid du Colombier 	et4000move,
26259cc4ca5SDavid du Colombier };
26359cc4ca5SDavid du Colombier 
26459cc4ca5SDavid du Colombier VGAdev vgaet4000dev = {
26559cc4ca5SDavid du Colombier 	"et4000",
26659cc4ca5SDavid du Colombier 
26759cc4ca5SDavid du Colombier 	0,
26859cc4ca5SDavid du Colombier 	0,
26959cc4ca5SDavid du Colombier 	et4000page,
27059cc4ca5SDavid du Colombier 	0
27159cc4ca5SDavid du Colombier };
272