xref: /plan9/sys/src/9/pc/vgaet4000.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8 
9 #define	Image	IMAGE
10 #include <draw.h>
11 #include <memdraw.h>
12 #include <cursor.h>
13 #include "screen.h"
14 
15 static void
setet4000page(int page)16 setet4000page(int page)
17 {
18 	uchar p;
19 
20 	p = page & 0x0F;
21 	p |= p<<4;
22 	outb(0x3CD, p);
23 
24 	p = (page & 0x30);
25 	p |= p>>4;
26 	outb(0x3CB, p);
27 }
28 
29 static void
et4000page(VGAscr * scr,int page)30 et4000page(VGAscr *scr, int page)
31 {
32 	lock(&scr->devlock);
33 	setet4000page(page);
34 	unlock(&scr->devlock);
35 }
36 
37 static void
et4000disable(VGAscr *)38 et4000disable(VGAscr*)
39 {
40 	uchar imaF7;
41 
42 	outb(0x217A, 0xF7);
43 	imaF7 = inb(0x217B) & ~0x80;
44 	outb(0x217B, imaF7);
45 }
46 
47 static void
et4000enable(VGAscr * scr)48 et4000enable(VGAscr *scr)
49 {
50 	uchar imaF7;
51 
52 	et4000disable(scr);
53 
54 	/*
55 	 * Configure CRTCB for Sprite, 64x64,
56 	 * CRTC pixel overlay.
57 	 */
58 	outb(0x217A, 0xEF);
59 	outb(0x217B, 0x02);
60 
61 	/*
62 	 * Cursor goes in the top left corner
63 	 * of the Sprite area, so the horizontal and
64 	 * vertical presets are 0.
65 	 */
66 	outb(0x217A, 0xE2);
67 	outb(0x217B, 0x00);
68 	outb(0x217A, 0xE3);
69 	outb(0x217B, 0x00);
70 
71 	outb(0x217A, 0xE6);
72 	outb(0x217B, 0x00);
73 	outb(0x217A, 0xE7);
74 	outb(0x217B, 0x00);
75 
76 	/*
77 	 * Find a place for the cursor data in display memory.
78 	 * Must be on a "doubleword" boundary, but put it on a
79 	 * 1024-byte boundary so that there's no danger of it
80 	 * crossing a page.
81 	 */
82 	scr->storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024;
83 	scr->storage *= 1024/4;
84 	outb(0x217A, 0xE8);
85 	outb(0x217B, scr->storage & 0xFF);
86 	outb(0x217A, 0xE9);
87 	outb(0x217B, (scr->storage>>8) & 0xFF);
88 	outb(0x217A, 0xEA);
89 	outb(0x217B, (scr->storage>>16) & 0x0F);
90 	scr->storage *= 4;
91 
92 	/*
93 	 * Row offset in "quadwords". Must be 2 for Sprite.
94 	 * Bag the pixel-panning.
95 	 * Colour depth, must be 2 for Sprite.
96 	 */
97 	outb(0x217A, 0xEB);
98 	outb(0x217B, 0x02);
99 	outb(0x217A, 0xEC);
100 	outb(0x217B, 0x00);
101 
102 	outb(0x217A, 0xED);
103 	outb(0x217B, 0x00);
104 
105 	outb(0x217A, 0xEE);
106 //	if(vgascreen.ldepth == 3)
107 		outb(0x217B, 0x01);
108 //	else
109 //		outb(0x217B, 0x00);
110 
111 	/*
112 	 * Enable the CRTCB/Sprite.
113 	 */
114 	outb(0x217A, 0xF7);
115 	imaF7 = inb(0x217B);
116 	outb(0x217B, 0x80|imaF7);
117 }
118 
119 static void
et4000load(VGAscr * scr,Cursor * c)120 et4000load(VGAscr *scr, Cursor *c)
121 {
122 	uchar p0, p1, *mem;
123 	int i, x, y;
124 	ushort p;
125 	uchar clr[2*16], set[2*16];
126 
127 	/*
128 	 * Lock the display memory so we can update the
129 	 * cursor bitmap if necessary.
130 	 */
131 	lock(&scr->devlock);
132 
133 	/*
134 	 * Disable the cursor.
135 	 * Set the display page (do we need to restore
136 	 * the current contents when done?) and the
137 	 * pointer to the two planes. What if this crosses
138 	 * into a new page?
139 	 */
140 	et4000disable(scr);
141 
142 	setet4000page(scr->storage>>16);
143 	mem = (uchar*)scr->vaddr + (scr->storage & 0xFFFF);
144 
145 	/*
146 	 * Initialise the 64x64 cursor RAM array. There are 2 planes,
147 	 * p0 and p1. Data is written 4 pixels per byte, with p1 the
148 	 * MS bit of each pixel.
149 	 * The cursor mode gives the following truth table:
150 	 *	p1 p0	colour
151 	 *	 0  0	Sprite Colour 0 (defined as 0x00)
152 	 *	 0  1	Sprite Colour 1 (defined as 0xFF)
153 	 *	 1  0	Transparent (allow CRTC pixel pass through)
154 	 *	 1  1	Invert (allow CRTC pixel invert through)
155 	 * Put the cursor into the top-left of the 64x64 array.
156 	 *
157 	 * This is almost certainly wrong, since it has not
158 	 * been updated for the 3rd edition color values.
159 	 */
160 	memmove(clr, c->clr, sizeof(clr));
161 //	pixreverse(clr, sizeof(clr), 0);
162 	memmove(set, c->set, sizeof(set));
163 //	pixreverse(set, sizeof(set), 0);
164 	for(y = 0; y < 64; y++){
165 		for(x = 0; x < 64/8; x++){
166 			if(x < 16/8 && y < 16){
167 				p0 = clr[x+y*2];
168 				p1 = set[x+y*2];
169 
170 				p = 0x0000;
171 				for(i = 0; i < 8; i++){
172 					if(p1 & (1<<(7-i))){
173 						/* nothing to do */
174 					}
175 					else if(p0 & (1<<(7-i)))
176 						p |= 0x01<<(2*i);
177 					else
178 						p |= 0x02<<(2*i);
179 				}
180 				*mem++ = p & 0xFF;
181 				*mem++ = (p>>8) & 0xFF;
182 			}
183 			else {
184 				*mem++ = 0xAA;
185 				*mem++ = 0xAA;
186 			}
187 		}
188 	}
189 
190 	/*
191 	 * enable the cursor.
192 	 */
193 	outb(0x217A, 0xF7);
194 	p = inb(0x217B)|0x80;
195 	outb(0x217B, p);
196 
197 	unlock(&scr->devlock);
198 }
199 
200 static int
et4000move(VGAscr * scr,Point p)201 et4000move(VGAscr *scr, Point p)
202 {
203 	int x, xo, y, yo;
204 
205 	if(canlock(&scr->devlock) == 0)
206 		return 1;
207 
208 	/*
209 	 * Mustn't position the cursor offscreen even partially,
210 	 * or it disappears. Therefore, if x or y is -ve, adjust the
211 	 * cursor presets instead.
212 	 */
213 	if((x = p.x+scr->offset.x) < 0){
214 		xo = -x;
215 		x = 0;
216 	}
217 	else
218 		xo = 0;
219 	if((y = p.y+scr->offset.y) < 0){
220 		yo = -y;
221 		y = 0;
222 	}
223 	else
224 		yo = 0;
225 
226 	/*
227 	 * The cursor image is jerky if we don't do this.
228 	 * The cursor information is probably fetched from
229 	 * display memory during the horizontal blank active
230 	 * time and it doesn't like it if the coordinates
231 	 * are changed underneath.
232 	 */
233 	while((vgai(Status1) & 0x08) == 0)
234 		;
235 
236 	outb(0x217A, 0xE2);
237 	outb(0x217B, xo);
238 
239 	outb(0x217A, 0xE6);
240 	outb(0x217B, yo);
241 
242 	outb(0x217A, 0xE1);
243 	outb(0x217B, (x>>8) & 0xFF);
244 	outb(0x217A, 0xE0);
245 	outb(0x217B, x & 0xFF);
246 	outb(0x217A, 0xE5);
247 	outb(0x217B, (y>>8) & 0xFF);
248 	outb(0x217A, 0xE4);
249 	outb(0x217B, y & 0xFF);
250 
251 	unlock(&scr->devlock);
252 	return 0;
253 }
254 
255 VGAcur vgaet4000cur = {
256 	"et4000hwgc",
257 
258 	et4000enable,
259 	et4000disable,
260 	et4000load,
261 	et4000move,
262 };
263 
264 VGAdev vgaet4000dev = {
265 	"et4000",
266 
267 	0,
268 	0,
269 	et4000page,
270 	0
271 };
272