FreeBSD/Linux Kernel Cross Reference
sys/pc/vgat2r4.c
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 /*
16 * #9 Ticket to Ride IV.
17 */
18 enum {
19 IndexLo = 0x10/4,
20 IndexHi = 0x14/4,
21 Data = 0x18/4,
22 IndexCtl = 0x1C/4,
23
24 Zoom = 0x54/4,
25 };
26
27 enum { /* index registers */
28 CursorSyncCtl = 0x03,
29 HsyncHi = 0x01,
30 HsyncLo = 0x02,
31 VsyncHi = 0x04,
32 VsyncLo = 0x08,
33
34 CursorCtl = 0x30,
35 CursorXLo = 0x31,
36 CursorXHi = 0x32,
37 CursorYLo = 0x33,
38 CursorYHi = 0x34,
39 CursorHotX = 0x35,
40 CursorHotY = 0x36,
41
42 CursorR1 = 0x40,
43 CursorG1 = 0x41,
44 CursorB1 = 0x42,
45 CursorR2 = 0x43,
46 CursorG2 = 0x44,
47 CursorB2 = 0x45,
48 CursorR3 = 0x46,
49 CursorG3 = 0x47,
50 CursorB3 = 0x48,
51
52 CursorArray = 0x100,
53
54 CursorMode32x32 = 0x23,
55 CursorMode64x64 = 0x27,
56 CursorMode = CursorMode32x32,
57 };
58
59 static void
60 t2r4enable(VGAscr* scr)
61 {
62 Pcidev *p;
63 void *mmio;
64
65 if(scr->mmio)
66 return;
67 if(p = pcimatch(nil, 0x105D, 0)){
68 switch(p->did){
69 case 0x5348:
70 break;
71 default:
72 return;
73 }
74 }
75 else
76 return;
77 scr->pci = p;
78
79 mmio = vmap(p->mem[4].bar & ~0x0F, p->mem[4].size);
80 if(mmio == nil)
81 return;
82 addvgaseg("t2r4mmio", p->mem[4].bar & ~0x0F, p->mem[4].size);
83
84 scr->mmio = mmio;
85 vgalinearpci(scr);
86 if(scr->paddr)
87 addvgaseg("t2r4screen", scr->paddr, scr->apsize);
88 }
89
90 static uchar
91 t2r4xi(VGAscr* scr, int index)
92 {
93 ulong *mmio;
94
95 mmio = scr->mmio;
96 mmio[IndexLo] = index & 0xFF;
97 mmio[IndexHi] = (index>>8) & 0xFF;
98
99 return mmio[Data];
100 }
101
102 static void
103 t2r4xo(VGAscr* scr, int index, uchar data)
104 {
105 ulong *mmio;
106
107 mmio = scr->mmio;
108 mmio[IndexLo] = index & 0xFF;
109 mmio[IndexHi] = (index>>8) & 0xFF;
110
111 mmio[Data] = data;
112 }
113
114 static void
115 t2r4curdisable(VGAscr* scr)
116 {
117 if(scr->mmio == 0)
118 return;
119 t2r4xo(scr, CursorCtl, 0x00);
120 }
121
122 static void
123 t2r4curload(VGAscr* scr, Cursor* curs)
124 {
125 uchar *data;
126 int size, x, y, zoom;
127 ulong clr, *mmio, pixels, set;
128
129 mmio = scr->mmio;
130 if(mmio == 0)
131 return;
132
133 /*
134 * Make sure cursor is off by initialising the cursor
135 * control to defaults.
136 */
137 t2r4xo(scr, CursorCtl, 0x00);
138
139 /*
140 * Set auto-increment mode for index-register addressing
141 * and initialise the cursor array index.
142 */
143 mmio[IndexCtl] = 0x01;
144 mmio[IndexLo] = CursorArray & 0xFF;
145 mmio[IndexHi] = (CursorArray>>8) & 0xFF;
146
147 /*
148 * Initialise the cursor RAM array. There are 2 planes,
149 * p0 and p1. Data is written 4 pixels per byte, with p1 the
150 * MS bit of each pixel.
151 * The cursor is set in X-Windows mode which gives the following
152 * truth table:
153 * p1 p0 colour
154 * 0 0 underlying pixel colour
155 * 0 1 underlying pixel colour
156 * 1 0 cursor colour 1
157 * 1 1 cursor colour 2
158 * Put the cursor into the top-left of the array.
159 *
160 * Although this looks a lot like the IBM RGB524 cursor, the
161 * scanlines appear to be twice as long as they should be and
162 * some of the other features are missing.
163 */
164 if(mmio[Zoom] & 0x0F)
165 zoom = 32;
166 else
167 zoom = 16;
168 data = (uchar*)&mmio[Data];
169 for(y = 0; y < zoom; y++){
170 clr = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1];
171 set = (curs->set[2*y]<<8)|curs->set[y*2 + 1];
172 pixels = 0;
173 for(x = 0; x < 16; x++){
174 if(set & (1<<x))
175 pixels |= 0x03<<(x*2);
176 else if(clr & (1<<x))
177 pixels |= 0x02<<(x*2);
178 }
179
180 *data = pixels>>24;
181 *data = pixels>>16;
182 *data = pixels>>8;
183 *data = pixels;
184
185 *data = 0x00;
186 *data = 0x00;
187 *data = 0x00;
188 *data = 0x00;
189
190 if(CursorMode == CursorMode32x32 && zoom == 16)
191 continue;
192 *data = pixels>>24;
193 *data = pixels>>16;
194 *data = pixels>>8;
195 *data = pixels;
196
197 *data = 0x00;
198 *data = 0x00;
199 *data = 0x00;
200 *data = 0x00;
201 }
202 if(CursorMode == CursorMode32x32)
203 size = 32;
204 else
205 size = 64;
206 while(y < size){
207 for(x = 0; x < size/8; x++){
208 *data = 0x00;
209 *data = 0x00;
210 }
211 y++;
212 }
213 mmio[IndexCtl] = 0x00;
214
215 /*
216 * Initialise the hotpoint and enable the cursor.
217 */
218 t2r4xo(scr, CursorHotX, -curs->offset.x);
219 zoom = (scr->mmio[Zoom] & 0x0F)+1;
220 t2r4xo(scr, CursorHotY, -curs->offset.y*zoom);
221
222 t2r4xo(scr, CursorCtl, CursorMode);
223 }
224
225 static int
226 t2r4curmove(VGAscr* scr, Point p)
227 {
228 int y, zoom;
229
230 if(scr->mmio == 0)
231 return 1;
232
233 t2r4xo(scr, CursorXLo, p.x & 0xFF);
234 t2r4xo(scr, CursorXHi, (p.x>>8) & 0x0F);
235
236 zoom = (scr->mmio[Zoom] & 0x0F)+1;
237 y = p.y*zoom;
238 t2r4xo(scr, CursorYLo, y & 0xFF);
239 t2r4xo(scr, CursorYHi, (y>>8) & 0x0F);
240
241 return 0;
242 }
243
244 static void
245 t2r4curenable(VGAscr* scr)
246 {
247 t2r4enable(scr);
248 if(scr->mmio == 0)
249 return;
250
251 /*
252 * Make sure cursor is off by initialising the cursor
253 * control to defaults.
254 */
255 t2r4xo(scr, CursorCtl, 0x00);
256
257 /*
258 * Cursor colour 1 (white),
259 * cursor colour 2 (black).
260 */
261 t2r4xo(scr, CursorR1, Pwhite);
262 t2r4xo(scr, CursorG1, Pwhite);
263 t2r4xo(scr, CursorB1, Pwhite);
264
265 t2r4xo(scr, CursorR2, Pblack);
266 t2r4xo(scr, CursorG2, Pblack);
267 t2r4xo(scr, CursorB2, Pblack);
268
269 /*
270 * Load, locate and enable the cursor, 64x64, mode 2.
271 */
272 t2r4curload(scr, &arrow);
273 t2r4curmove(scr, ZP);
274 t2r4xo(scr, CursorCtl, CursorMode);
275 }
276
277 enum {
278 Flow = 0x08/4,
279 Busy = 0x0C/4,
280 BufCtl = 0x20/4,
281 DeSorg = 0x28/4,
282 DeDorg = 0x2C/4,
283 DeSptch = 0x40/4,
284 DeDptch = 0x44/4,
285 CmdOpc = 0x50/4,
286 CmdRop = 0x54/4,
287 CmdStyle = 0x58/4,
288 CmdPatrn = 0x5C/4,
289 CmdClp = 0x60/4,
290 CmdPf = 0x64/4,
291 Fore = 0x68/4,
292 Back = 0x6C/4,
293 Mask = 0x70/4,
294 DeKey = 0x74/4,
295 Lpat = 0x78/4,
296 Pctrl = 0x7C/4,
297 Clptl = 0x80/4,
298 Clpbr = 0x84/4,
299 XY0 = 0x88/4,
300 XY1 = 0x8C/4,
301 XY2 = 0x90/4,
302 XY3 = 0x94/4,
303 XY4 = 0x98/4,
304 Alpha = 0x128/4,
305 ACtl = 0x16C/4,
306
307 RBaseD = 0x4000/4,
308 };
309
310 /* wait until pipeline ready for new command */
311 static void
312 waitforfifo(VGAscr *scr)
313 {
314 int x;
315 ulong *d;
316 x = 0;
317
318 d = scr->mmio + RBaseD;
319 while((d[Busy]&1) && x++ < 1000000)
320 ;
321 if(x >= 1000000) /* shouldn't happen */
322 iprint("busy %8lux\n", d[Busy]);
323 }
324
325 /* wait until command has finished executing */
326 static void
327 waitforcmd(VGAscr *scr)
328 {
329 int x;
330 ulong *d;
331 x = 0;
332
333 d = scr->mmio + RBaseD;
334 while((d[Flow]&0x1B) && x++ < 1000000)
335 ;
336 if(x >= 1000000) /* shouldn't happen */
337 iprint("flow %8lux\n", d[Flow]);
338 }
339
340 /* wait until memory controller not busy (i.e. wait for writes to flush) */
341 static void
342 waitformem(VGAscr *scr)
343 {
344 int x;
345 ulong *d;
346 x = 0;
347
348 d = scr->mmio + RBaseD;
349 while((d[Flow]&2)&& x++ < 1000000)
350 ;
351 if(x >= 1000000) /* shouldn't happen */
352 iprint("mem %8lux\n", d[Busy]);
353 }
354
355 static int
356 t2r4hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
357 {
358 int ctl;
359 Point dp, sp;
360 ulong *d;
361 int depth;
362
363 if(r.min.y == sr.min.y){ /* a purely horizontal scroll */
364 depth = scr->gscreen->depth;
365 switch(depth){
366 case 32:
367 /*
368 * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
369 * 32-bit scrolls don't work perfectly on rectangles of width <= 24.
370 * we bail on a bigger bound for padding.
371 */
372 if(Dx(r) < 32)
373 return 0;
374 break;
375 case 16:
376 /*
377 * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
378 * 16-bit scrolls don't work perfectly on rectangles of width <= 96.
379 * we bail on a bigger bound for padding.
380 */
381 if(Dx(r) < 104)
382 return 0;
383 break;
384 }
385 }
386 waitformem(scr);
387 waitforfifo(scr);
388 d = scr->mmio + RBaseD;
389 ctl = 0;
390 if(r.min.x <= sr.min.x){
391 dp.x = r.min.x;
392 sp.x = sr.min.x;
393 }else{
394 ctl |= 2;
395 dp.x = r.max.x-1;
396 sp.x = sr.max.x-1;
397 }
398
399 if(r.min.y < sr.min.y){
400 dp.y = r.min.y;
401 sp.y = sr.min.y;
402 }else{
403 ctl |= 1;
404 dp.y = r.max.y-1;
405 sp.y = sr.max.y-1;
406 }
407
408 d[CmdOpc] = 0x1; /* bitblt */
409 d[CmdRop] = 0xC; /* copy source */
410 d[CmdStyle] = 0;
411 d[CmdPatrn] = 0;
412 d[Fore] = 0;
413 d[Back] = 0;
414
415 /* writing XY1 executes cmd */
416 d[XY3] = ctl;
417 d[XY0] = (sp.x<<16)|sp.y;
418 d[XY2] = (Dx(r)<<16)|Dy(r);
419 d[XY4] = 0;
420 d[XY1] = (dp.x<<16)|dp.y;
421 waitforcmd(scr);
422
423 return 1;
424 }
425
426 static int
427 t2r4hwfill(VGAscr *scr, Rectangle r, ulong sval)
428 {
429 ulong *d;
430
431 d = scr->mmio + RBaseD;
432
433 waitformem(scr);
434 waitforfifo(scr);
435 d[CmdOpc] = 0x1; /* bitblt */
436 d[CmdRop] = 0xC; /* copy source */
437 d[CmdStyle] = 1; /* use source from Fore register */
438 d[CmdPatrn] = 0; /* no stipple */
439 d[Fore] = sval;
440 d[Back] = sval;
441
442 /* writing XY1 executes cmd */
443 d[XY3] = 0;
444 d[XY0] = (r.min.x<<16)|r.min.y;
445 d[XY2] = (Dx(r)<<16)|Dy(r);
446 d[XY4] = 0;
447 d[XY1] = (r.min.x<<16)|r.min.y;
448 waitforcmd(scr);
449
450 return 1;
451 }
452
453 static void
454 t2r4blank(VGAscr *scr, int blank)
455 {
456 uchar x;
457
458 x = t2r4xi(scr, CursorSyncCtl);
459 x &= ~0x0F;
460 if(blank)
461 x |= HsyncLo | VsyncLo;
462 t2r4xo(scr, CursorSyncCtl, x);
463 }
464
465 static void
466 t2r4drawinit(VGAscr *scr)
467 {
468 ulong pitch;
469 int depth;
470 int fmt;
471 ulong *d;
472
473 pitch = Dx(scr->gscreen->r);
474 depth = scr->gscreen->depth;
475
476 switch(scr->gscreen->chan){
477 case RGB16:
478 fmt = 3;
479 break;
480 case XRGB32:
481 fmt = 2;
482 break;
483 case RGB15:
484 fmt = 1;
485 break;
486 default:
487 scr->fill = nil;
488 scr->scroll = nil;
489 return;
490 }
491
492 d = scr->mmio + RBaseD;
493
494 d[BufCtl] = fmt<<24;
495 d[DeSorg] = 0;
496 d[DeDorg] = 0;
497 d[DeSptch] = (pitch*depth)/8;
498 d[DeDptch] = (pitch*depth)/8;
499 d[CmdClp] = 0; /* 2 = inside rectangle */
500 d[Mask] = ~0;
501 d[DeKey] = 0;
502 d[Clptl] = 0;
503 d[Clpbr] = 0xFFF0FFF0;
504 d[Alpha] = 0;
505 d[ACtl] = 0;
506
507 scr->fill = t2r4hwfill;
508 scr->scroll = t2r4hwscroll;
509 scr->blank = t2r4blank;
510 hwblank = 1;
511 }
512
513 VGAdev vgat2r4dev = {
514 "t2r4",
515
516 t2r4enable,
517 nil,
518 nil,
519 nil,
520 t2r4drawinit,
521 };
522
523 VGAcur vgat2r4cur = {
524 "t2r4hwgc",
525
526 t2r4curenable,
527 t2r4curdisable,
528 t2r4curload,
529 t2r4curmove,
530 };
531
Cache object: f051b30db1425bc0e6acf1db78c03f1e
|