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