]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgat2r4.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / 9 / 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