]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vga3dfx.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / 9 / pc / vga3dfx.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 typedef struct Cursor3dfx Cursor3dfx;
16 struct Cursor3dfx {
17         int     vidProcCfg;
18         int     hwCurPatAddr;
19         int     hwCurLoc;
20         int     hwCurC0;
21         int     hwCurC1;
22 };
23
24 enum {
25         dramInit0       = 0x18,
26         dramInit1       = 0x1C,
27
28         hwCur           = 0x5C,
29 };
30
31 static void
32 tdfxenable(VGAscr* scr)
33 {
34         Pcidev *p;
35         int i, *mmio;
36
37         if(scr->mmio)
38                 return;
39         if(p = pcimatch(nil, 0x121A, 0)){
40                 switch(p->did){
41                 case 0x0003:            /* Banshee */
42                 case 0x0005:            /* Avenger (a.k.a. Voodoo3) */
43                         break;
44                 default:
45                         return;
46                 }
47         }
48         else
49                 return;
50         
51         scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
52         if(scr->mmio == nil)
53                 return;
54         scr->pci = p;
55         
56         addvgaseg("3dfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
57         vgalinearpci(scr);
58         if(scr->apsize)
59                 addvgaseg("3dfxscreen", scr->paddr, scr->apsize);
60
61         /*
62          * Find a place for the cursor data in display memory.
63          * If SDRAM then there's 16MB memory else it's SGRAM
64          * and can count it based on the power-on straps -
65          * chip size can be 8Mb or 16Mb, and there can be 4 or
66          * 8 of them.
67          * Use the last 1KB of the framebuffer.
68          */
69         mmio = (void*)((uchar*)scr->mmio+dramInit0);
70         if(*(mmio+1) & 0x40000000)
71                 i = 16*1024*1024;
72         else{
73                 if(*mmio & 0x08000000)
74                         i = 16*1024*1024/8;
75                 else
76                         i = 8*1024*1024/8;
77                 if(*mmio & 0x04000000)
78                         i *= 8;
79                 else
80                         i *= 4;
81         }
82         scr->storage = i - 1024;
83 }
84
85 static void
86 tdfxcurdisable(VGAscr* scr)
87 {
88         Cursor3dfx *cursor3dfx;
89
90         if(scr->mmio == 0)
91                 return;
92         cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
93         cursor3dfx->vidProcCfg &= ~0x08000000;
94 }
95
96 static void
97 tdfxcurload(VGAscr* scr, Cursor* curs)
98 {
99         int y;
100         uchar *p;
101         Cursor3dfx *cursor3dfx;
102
103         if(scr->mmio == 0)
104                 return;
105         cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
106
107         /*
108          * Disable the cursor then load the new image in
109          * the top-left of the 64x64 array.
110          * The cursor data is stored in memory as 128-bit
111          * words consisting of plane 0 in the least significant 64-bits
112          * and plane 1 in the most significant.
113          * The X11 cursor truth table is:
114          *      p0 p1   colour
115          *       0  0   transparent
116          *       0  1   transparent
117          *       1  0   hwCurC0
118          *       1  1   hwCurC1
119          * Unused portions of the image have been initialised to be
120          * transparent.
121          */
122         cursor3dfx->vidProcCfg &= ~0x08000000;
123         p = (uchar*)scr->vaddr + scr->storage;
124         for(y = 0; y < 16; y++){
125                 *p++ = curs->clr[2*y]|curs->set[2*y];
126                 *p++ = curs->clr[2*y+1]|curs->set[2*y+1];
127                 p += 6;
128                 *p++ = curs->set[2*y];
129                 *p++ = curs->set[2*y+1];
130                 p += 6;
131         }
132
133         /*
134          * Save the cursor hotpoint and enable the cursor.
135          * The 0,0 cursor point is bottom-right.
136          */
137         scr->offset.x = 63+curs->offset.x;
138         scr->offset.y = 63+curs->offset.y;
139         cursor3dfx->vidProcCfg |= 0x08000000;
140 }
141
142 static int
143 tdfxcurmove(VGAscr* scr, Point p)
144 {
145         Cursor3dfx *cursor3dfx;
146
147         if(scr->mmio == 0)
148                 return 1;
149         cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
150
151         cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x);
152
153         return 0;
154 }
155
156 static void
157 tdfxcurenable(VGAscr* scr)
158 {
159         Cursor3dfx *cursor3dfx;
160
161         tdfxenable(scr);
162         if(scr->mmio == 0)
163                 return;
164         cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
165
166         /*
167          * Cursor colours.
168          */
169         cursor3dfx->hwCurC0 = 0xFFFFFFFF;
170         cursor3dfx->hwCurC1 = 0x00000000;
171
172         /*
173          * Initialise the 64x64 cursor to be transparent (X11 mode).
174          */
175         cursor3dfx->hwCurPatAddr = scr->storage;
176         memset((uchar*)scr->vaddr + scr->storage, 0, 64*16);
177
178         /*
179          * Load, locate and enable the 64x64 cursor in X11 mode.
180          */
181         tdfxcurload(scr, &arrow);
182         tdfxcurmove(scr, ZP);
183         cursor3dfx->vidProcCfg |= 0x08000002;
184 }
185
186 VGAdev vga3dfxdev = {
187         "3dfx",
188
189         tdfxenable,
190         nil,
191         nil,
192         nil,
193 };
194
195 VGAcur vga3dfxcur = {
196         "3dfxhwgc",
197
198         tdfxcurenable,
199         tdfxcurdisable,
200         tdfxcurload,
201         tdfxcurmove,
202 };