summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/vgaark2000pv.c
blob: 542a7b3a2fcf63d3004737959d541122c9fd3092 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#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
ark2000pvpageset(VGAscr*, int page)
{
	uchar seq15;

	seq15 = vgaxi(Seqx, 0x15);
	vgaxo(Seqx, 0x15, page);
	vgaxo(Seqx, 0x16, page);

	return seq15;
}

static void
ark2000pvpage(VGAscr* scr, int page)
{
	lock(&scr->devlock);
	ark2000pvpageset(scr, page);
	unlock(&scr->devlock);
}

static void
ark2000pvdisable(VGAscr*)
{
	uchar seq20;

	seq20 = vgaxi(Seqx, 0x20) & ~0x08;
	vgaxo(Seqx, 0x20, seq20);
}

static void
ark2000pvenable(VGAscr* scr)
{
	uchar seq20;
	ulong storage;

	/*
	 * Disable the cursor then configure for X-Windows style,
	 * 32x32 and 4/8-bit colour depth.
	 * Set cursor colours for 4/8-bit.
	 */
	seq20 = vgaxi(Seqx, 0x20) & ~0x1F;
	vgaxo(Seqx, 0x20, seq20);
	seq20 |= 0x18;

	vgaxo(Seqx, 0x26, 0x00);
	vgaxo(Seqx, 0x27, 0x00);
	vgaxo(Seqx, 0x28, 0x00);
	vgaxo(Seqx, 0x29, 0xFF);
	vgaxo(Seqx, 0x2A, 0xFF);
	vgaxo(Seqx, 0x2B, 0xFF);

	/*
	 * Cursor storage is a 256 byte or 1Kb block located in the last
	 * 16Kb of video memory. Crt25 is the index of which block.
	 */
	storage = (vgaxi(Seqx, 0x10)>>6) & 0x03;
	storage = (1024*1024)<<storage;
	storage -= 256;
	scr->storage = storage;
	vgaxo(Seqx, 0x25, 0x3F);

	/*
	 * Enable the cursor.
	 */
	vgaxo(Seqx, 0x20, seq20);
}

static void
ark2000pvload(VGAscr* scr, Cursor* curs)
{
	uchar *p, seq10;
	int opage, x, y;

	/*
	 * Is linear addressing turned on? This will determine
	 * how we access the cursor storage.
	 */
	seq10 = vgaxi(Seqx, 0x10);
	opage = 0;
	p = scr->vaddr;
	if(!(seq10 & 0x10)){
		lock(&scr->devlock);
		opage = ark2000pvpageset(scr, scr->storage>>16);
		p += (scr->storage & 0xFFFF);
	}
	else
		p += scr->storage;

	/*
	 * The cursor is set in X11 mode which gives the following
	 * truth table:
	 *	and xor	colour
	 *	 0   0	underlying pixel colour
	 *	 0   1	underlying pixel colour
	 *	 1   0	background colour
	 *	 1   1	foreground colour
	 * Put the cursor into the top-left of the 32x32 array.
	 * The manual doesn't say what the data layout in memory is -
	 * this worked out by trial and error.
	 */
	for(y = 0; y < 32; y++){
		for(x = 0; x < 32/8; x++){
			if(x < 16/8 && y < 16){
				*p++ = curs->clr[2*y + x]|curs->set[2*y + x];
				*p++ = curs->set[2*y + x];
			}
			else {
				*p++ = 0x00;
				*p++ = 0x00;
			}
		}
	}

	if(!(seq10 & 0x10)){
		ark2000pvpageset(scr, opage);
		unlock(&scr->devlock);
	}

	/*
	 * Save the cursor hotpoint.
	 */
	scr->offset = curs->offset;
}

static int
ark2000pvmove(VGAscr* scr, Point p)
{
	int x, xo, y, yo;

	/*
	 * Mustn't position the cursor offscreen even partially,
	 * or it might disappear. Therefore, if x or y is -ve, adjust the
	 * cursor origins instead.
	 */
	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;

	/*
	 * Load the new values.
	 */
	vgaxo(Seqx, 0x2C, xo);
	vgaxo(Seqx, 0x2D, yo);
	vgaxo(Seqx, 0x21, (x>>8) & 0x0F);
	vgaxo(Seqx, 0x22, x & 0xFF);
	vgaxo(Seqx, 0x23, (y>>8) & 0x0F);
	vgaxo(Seqx, 0x24, y & 0xFF);

	return 0;
}

VGAdev vgaark2000pvdev = {
	"ark2000pv",

	0,
	0,
	ark2000pvpage,
	0,
};

VGAcur vgaark2000pvcur = {
	"ark2000pvhwgc",

	ark2000pvenable,
	ark2000pvdisable,
	ark2000pvload,
	ark2000pvmove,
};