xref: /plan9/sys/src/9/pc/vgaark2000pv.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 int
ark2000pvpageset(VGAscr *,int page)16 ark2000pvpageset(VGAscr*, int page)
17 {
18 	uchar seq15;
19 
20 	seq15 = vgaxi(Seqx, 0x15);
21 	vgaxo(Seqx, 0x15, page);
22 	vgaxo(Seqx, 0x16, page);
23 
24 	return seq15;
25 }
26 
27 static void
ark2000pvpage(VGAscr * scr,int page)28 ark2000pvpage(VGAscr* scr, int page)
29 {
30 	lock(&scr->devlock);
31 	ark2000pvpageset(scr, page);
32 	unlock(&scr->devlock);
33 }
34 
35 static void
ark2000pvdisable(VGAscr *)36 ark2000pvdisable(VGAscr*)
37 {
38 	uchar seq20;
39 
40 	seq20 = vgaxi(Seqx, 0x20) & ~0x08;
41 	vgaxo(Seqx, 0x20, seq20);
42 }
43 
44 static void
ark2000pvenable(VGAscr * scr)45 ark2000pvenable(VGAscr* scr)
46 {
47 	uchar seq20;
48 	ulong storage;
49 
50 	/*
51 	 * Disable the cursor then configure for X-Windows style,
52 	 * 32x32 and 4/8-bit colour depth.
53 	 * Set cursor colours for 4/8-bit.
54 	 */
55 	seq20 = vgaxi(Seqx, 0x20) & ~0x1F;
56 	vgaxo(Seqx, 0x20, seq20);
57 	seq20 |= 0x18;
58 
59 	vgaxo(Seqx, 0x26, 0x00);
60 	vgaxo(Seqx, 0x27, 0x00);
61 	vgaxo(Seqx, 0x28, 0x00);
62 	vgaxo(Seqx, 0x29, 0xFF);
63 	vgaxo(Seqx, 0x2A, 0xFF);
64 	vgaxo(Seqx, 0x2B, 0xFF);
65 
66 	/*
67 	 * Cursor storage is a 256 byte or 1Kb block located in the last
68 	 * 16Kb of video memory. Crt25 is the index of which block.
69 	 */
70 	storage = (vgaxi(Seqx, 0x10)>>6) & 0x03;
71 	storage = (1024*1024)<<storage;
72 	storage -= 256;
73 	scr->storage = storage;
74 	vgaxo(Seqx, 0x25, 0x3F);
75 
76 	/*
77 	 * Enable the cursor.
78 	 */
79 	vgaxo(Seqx, 0x20, seq20);
80 }
81 
82 static void
ark2000pvload(VGAscr * scr,Cursor * curs)83 ark2000pvload(VGAscr* scr, Cursor* curs)
84 {
85 	uchar *p, seq10;
86 	int opage, x, y;
87 
88 	/*
89 	 * Is linear addressing turned on? This will determine
90 	 * how we access the cursor storage.
91 	 */
92 	seq10 = vgaxi(Seqx, 0x10);
93 	opage = 0;
94 	p = scr->vaddr;
95 	if(!(seq10 & 0x10)){
96 		lock(&scr->devlock);
97 		opage = ark2000pvpageset(scr, scr->storage>>16);
98 		p += (scr->storage & 0xFFFF);
99 	}
100 	else
101 		p += scr->storage;
102 
103 	/*
104 	 * The cursor is set in X11 mode which gives the following
105 	 * truth table:
106 	 *	and xor	colour
107 	 *	 0   0	underlying pixel colour
108 	 *	 0   1	underlying pixel colour
109 	 *	 1   0	background colour
110 	 *	 1   1	foreground colour
111 	 * Put the cursor into the top-left of the 32x32 array.
112 	 * The manual doesn't say what the data layout in memory is -
113 	 * this worked out by trial and error.
114 	 */
115 	for(y = 0; y < 32; y++){
116 		for(x = 0; x < 32/8; x++){
117 			if(x < 16/8 && y < 16){
118 				*p++ = curs->clr[2*y + x]|curs->set[2*y + x];
119 				*p++ = curs->set[2*y + x];
120 			}
121 			else {
122 				*p++ = 0x00;
123 				*p++ = 0x00;
124 			}
125 		}
126 	}
127 
128 	if(!(seq10 & 0x10)){
129 		ark2000pvpageset(scr, opage);
130 		unlock(&scr->devlock);
131 	}
132 
133 	/*
134 	 * Save the cursor hotpoint.
135 	 */
136 	scr->offset = curs->offset;
137 }
138 
139 static int
ark2000pvmove(VGAscr * scr,Point p)140 ark2000pvmove(VGAscr* scr, Point p)
141 {
142 	int x, xo, y, yo;
143 
144 	/*
145 	 * Mustn't position the cursor offscreen even partially,
146 	 * or it might disappear. Therefore, if x or y is -ve, adjust the
147 	 * cursor origins instead.
148 	 */
149 	if((x = p.x+scr->offset.x) < 0){
150 		xo = -x;
151 		x = 0;
152 	}
153 	else
154 		xo = 0;
155 	if((y = p.y+scr->offset.y) < 0){
156 		yo = -y;
157 		y = 0;
158 	}
159 	else
160 		yo = 0;
161 
162 	/*
163 	 * Load the new values.
164 	 */
165 	vgaxo(Seqx, 0x2C, xo);
166 	vgaxo(Seqx, 0x2D, yo);
167 	vgaxo(Seqx, 0x21, (x>>8) & 0x0F);
168 	vgaxo(Seqx, 0x22, x & 0xFF);
169 	vgaxo(Seqx, 0x23, (y>>8) & 0x0F);
170 	vgaxo(Seqx, 0x24, y & 0xFF);
171 
172 	return 0;
173 }
174 
175 VGAdev vgaark2000pvdev = {
176 	"ark2000pv",
177 
178 	0,
179 	0,
180 	ark2000pvpage,
181 	0,
182 };
183 
184 VGAcur vgaark2000pvcur = {
185 	"ark2000pvhwgc",
186 
187 	ark2000pvenable,
188 	ark2000pvdisable,
189 	ark2000pvload,
190 	ark2000pvmove,
191 };
192