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