|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "../port/error.h"
7:
8: #include <libg.h>
9: #include <gnot.h>
10: #include "screen.h"
11: #include "vga.h"
12:
13: /*
14: * Hardware graphics cursor support for
15: * generic S3 chipset.
16: * Assume we're in enhanced mode.
17: */
18: static Lock s3pagelock;
19: static ulong storage;
20: static Point hotpoint;
21:
22: extern GBitmap gscreen;
23: extern GBitmap vgascreen;
24: extern Cursor curcursor;
25:
26: static void
27: sets3page(int page)
28: {
29: uchar crt51;
30:
31: if(vgascreen.ldepth == 3){
32: /*
33: * The S3 registers need to be unlocked for this.
34: * Let's hope they are already:
35: * vgaxo(Crtx, 0x38, 0x48);
36: * vgaxo(Crtx, 0x39, 0xA0);
37: *
38: * The page is 6 bits, the lower 4 bits in Crt35<3:0>,
39: * the upper 2 in Crt51<3:2>.
40: */
41: vgaxo(Crtx, 0x35, page & 0x0F);
42: crt51 = vgaxi(Crtx, 0x51) & 0xF3;
43: vgaxo(Crtx, 0x51, crt51|((page & 0x30)>>2));
44: }
45: else
46: vgaxo(Crtx, 0x35, (page<<2) & 0x0C);
47: }
48:
49: static void
50: vsyncactive(void)
51: {
52: /*
53: * Hardware cursor information is fetched from display memory
54: * during the horizontal blank active time. The 80x chips may hang
55: * if the cursor is turned on or off during this period.
56: */
57: while((vgai(Status1) & 0x08) == 0)
58: ;
59: }
60:
61: static void
62: disable(void)
63: {
64: uchar crt45;
65:
66: /*
67: * Turn cursor off.
68: */
69: crt45 = vgaxi(Crtx, 0x45) & 0xFE;
70: vsyncactive();
71: vgaxo(Crtx, 0x45, crt45);
72: }
73:
74: static void
75: enable(void)
76: {
77: int i;
78:
79: disable();
80:
81: /*
82: * Cursor colours. Set both the CR0[EF] and the colour
83: * stack in case we are using a 16-bit RAMDAC.
84: * Why are these colours reversed?
85: */
86: vgaxo(Crtx, 0x0E, 0x00);
87: vgaxo(Crtx, 0x0F, 0xFF);
88: vgaxi(Crtx, 0x45);
89: for(i = 0; i < 4; i++)
90: vgaxo(Crtx, 0x4A, 0x00);
91: vgaxi(Crtx, 0x45);
92: for(i = 0; i < 4; i++)
93: vgaxo(Crtx, 0x4B, 0xFF);
94:
95: /*
96: * Find a place for the cursor data in display memory.
97: * Must be on a 1024-byte boundary.
98: */
99: storage = (gscreen.width*BY2WD*gscreen.r.max.y+1023)/1024;
100: vgaxo(Crtx, 0x4C, (storage>>8) & 0x0F);
101: vgaxo(Crtx, 0x4D, storage & 0xFF);
102: storage *= 1024;
103:
104: /*
105: * Enable the cursor in X11 mode.
106: */
107: vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55)|0x10);
108: vsyncactive();
109: vgaxo(Crtx, 0x45, 0x01);
110: }
111:
112: static void
113: load(Cursor *c)
114: {
115: uchar *p;
116: int x, y;
117: uchar clr[2*16], set[2*16];
118:
119: /*
120: * Lock the display memory so we can update the
121: * cursor bitmap if necessary.
122: * If it's the same as the last cursor we loaded,
123: * just make sure it's enabled.
124: */
125: lock(&s3pagelock);
126: /*
127: if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){
128: vsyncactive();
129: vgaxo(Crtx, 0x45, 0x01);
130: unlock(&s3pagelock);
131: return;
132: }
133: memmove(&curcursor, c, sizeof(Cursor));
134: */
135:
136: /*
137: * Disable the cursor.
138: * Set the display page (do we need to restore
139: * the current contents when done?) and the
140: * pointer to the two planes. What if this crosses
141: * into a new page?
142: */
143: disable();
144:
145: sets3page(storage>>16);
146: p = ((uchar*)vgascreen.base) + (storage & 0xFFFF);
147:
148: /*
149: * The cursor is set in X11 mode which gives the following
150: * truth table:
151: * and xor colour
152: * 0 0 underlying pixel colour
153: * 0 1 underlying pixel colour
154: * 1 0 background colour
155: * 1 1 foreground colour
156: * Put the cursor into the top-left of the 64x64 array.
157: *
158: * The cursor pattern in memory is interleaved words of
159: * AND and XOR patterns.
160: */
161: memmove(clr, c->clr, sizeof(clr));
162: pixreverse(clr, sizeof(clr), 0);
163: memmove(set, c->set, sizeof(set));
164: pixreverse(set, sizeof(set), 0);
165: for(y = 0; y < 64; y++){
166: for(x = 0; x < 64/8; x += 2){
167: if(x < 16/8 && y < 16){
168: *p++ = clr[2*y + x]|set[2*y + x];
169: *p++ = clr[2*y + x+1]|set[2*y + x+1];
170: *p++ = set[2*y + x];
171: *p++ = set[2*y + x+1];
172: }
173: else {
174: *p++ = 0x00;
175: *p++ = 0x00;
176: *p++ = 0x00;
177: *p++ = 0x00;
178: }
179: }
180: }
181:
182: /*
183: * Set the cursor hotpoint and enable the cursor.
184: */
185: hotpoint = c->offset;
186: vsyncactive();
187: vgaxo(Crtx, 0x45, 0x01);
188:
189: unlock(&s3pagelock);
190: }
191:
192: static int
193: move(Point p)
194: {
195: int x, xo, y, yo;
196:
197: if(canlock(&s3pagelock) == 0)
198: return 1;
199:
200: /*
201: * Mustn't position the cursor offscreen even partially,
202: * or it disappears. Therefore, if x or y is -ve, adjust the
203: * cursor offset instead.
204: * There seems to be a bug in that if the offset is 1, the
205: * cursor doesn't disappear off the left edge properly, so
206: * round it up to be even.
207: */
208: if((x = p.x+hotpoint.x) < 0){
209: xo = -x;
210: xo = ((xo+1)/2)*2;
211: x = 0;
212: }
213: else
214: xo = 0;
215: if((y = p.y+hotpoint.y) < 0){
216: yo = -y;
217: y = 0;
218: }
219: else
220: yo = 0;
221:
222: vgaxo(Crtx, 0x46, (x>>8) & 0x07);
223: vgaxo(Crtx, 0x47, x & 0xFF);
224: vgaxo(Crtx, 0x49, y & 0xFF);
225: vgaxo(Crtx, 0x4E, xo);
226: vgaxo(Crtx, 0x4F, yo);
227: vgaxo(Crtx, 0x48, (y>>8) & 0x07);
228:
229: unlock(&s3pagelock);
230: return 0;
231: }
232:
233: static Hwgc s3hwgc = {
234: "s3hwgc",
235: enable,
236: load,
237: move,
238: disable,
239:
240: 0,
241: };
242:
243: static void
244: s3page(int page)
245: {
246: if(hwgc == &s3hwgc){
247: lock(&s3pagelock);
248: sets3page(page);
249: unlock(&s3pagelock);
250: }
251: else
252: sets3page(page);
253: }
254:
255: static Vgac s3 = {
256: "s3",
257: s3page,
258:
259: 0,
260: };
261:
262: void
263: vgas3link(void)
264: {
265: addvgaclink(&s3);
266: addhwgclink(&s3hwgc);
267: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.