]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgatvp3020.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / vgatvp3020.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  * TVP3020 Viewpoint Video Interface Pallette.
17  * Assumes hooked up to an S3 86C928.
18  */
19 enum {
20         Index           = 0x06,                         /* Index register */
21         Data            = 0x07,                         /* Data register */
22 };
23
24 /*
25  * Lower 2-bits of indirect DAC register
26  * addressing.
27  */
28 static ushort dacxreg[4] = {
29         PaddrW, Pdata, Pixmask, PaddrR
30 };
31
32 static uchar
33 tvp3020io(uchar reg, uchar data)
34 {
35         uchar crt55;
36
37         crt55 = vgaxi(Crtx, 0x55) & 0xFC;
38         vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
39         vgao(dacxreg[reg & 0x03], data);
40
41         return crt55;
42 }
43
44 static void
45 tvp3020xo(uchar index, uchar data)
46 {
47         uchar crt55;
48
49         crt55 = tvp3020io(Index, index);
50         vgao(dacxreg[Data & 0x03], data);
51         vgaxo(Crtx, 0x55, crt55);
52 }
53
54 static void
55 tvp3020disable(VGAscr*)
56 {
57         uchar r;
58
59         /*
60          * Disable 
61          *      cursor;
62          *      cursor control enable for Bt485 DAC (!);
63          *      the hardware cursor external operation mode.
64          */
65         tvp3020xo(0x06, 0x10);                          /* Cursor Control Register */
66
67         r = vgaxi(Crtx, 0x45) & ~0x20;
68         vgaxo(Crtx, 0x45, r);
69
70         r = vgaxi(Crtx, 0x55) & ~0x20;
71         vgaxo(Crtx, 0x55, r);
72 }
73
74 static void
75 tvp3020enable(VGAscr*)
76 {
77         uchar r;
78
79         /*
80          * Make sure cursor is off by initialising the cursor
81          * control to defaults + X-Windows cursor mode.
82          */
83         tvp3020xo(0x06, 0x10);                          /* Cursor Control Register */
84
85         /*
86          * Overscan colour,
87          * cursor colour 1 (white),
88          * cursor colour 2 (black).
89          */
90         tvp3020xo(0x20, Pwhite); tvp3020xo(0x21, Pwhite); tvp3020xo(0x22, Pwhite);
91         tvp3020xo(0x23, Pwhite); tvp3020xo(0x24, Pwhite); tvp3020xo(0x25, Pwhite);
92         tvp3020xo(0x26, Pblack); tvp3020xo(0x27, Pblack); tvp3020xo(0x28, Pblack);
93
94         /*
95          * Finally, enable
96          *      the hardware cursor external operation mode;
97          *      cursor control enable for Bt485 DAC (!).
98          */
99         r = vgaxi(Crtx, 0x55)|0x20;
100         vgaxo(Crtx, 0x55, r);
101
102         r = vgaxi(Crtx, 0x45)|0x20;
103         vgaxo(Crtx, 0x45, r);
104 }
105
106 static void
107 tvp3020load(VGAscr*, Cursor* curs)
108 {
109         uchar p, p0, p1;
110         int x, y;
111
112         /*
113          * Make sure cursor is off by initialising the cursor
114          * control to defaults + X-Windows cursor mode.
115          */
116         tvp3020xo(0x06, 0x10);                          /* Cursor Control Register */
117
118         /*
119          * Initialise the cursor RAM LS and MS address
120          * (LS must be first).
121          */
122         tvp3020xo(0x08, 0x00);                          /* Cursor RAM LS Address */
123         tvp3020xo(0x09, 0x00);                          /* Cursor RAM MS Address */
124
125         /*
126          * Initialise the 64x64 cursor RAM array. There are 2 planes,
127          * p0 and p1. Data is written 4 pixels per byte, with p1 the
128          * MS bit of each pixel.
129          * The cursor is set in X-Windows mode which gives the following
130          * truth table:
131          *      p1 p0   colour
132          *       0  0   underlying pixel colour
133          *       0  1   underlying pixel colour
134          *       1  0   cursor colour 1
135          *       1  1   cursor colour 2
136          * Put the cursor into the top-left of the 64x64 array.
137          */
138         for(y = 0; y < 64; y++){
139                 for(x = 0; x < 64/8; x++){
140                         if(x < 16/8 && y < 16){
141                                 p0 = curs->clr[x+y*2];
142                                 p1 = curs->set[x+y*2];
143
144                                 p = 0x00;
145                                 if(p1 & 0x10)
146                                         p |= 0x03;
147                                 else if(p0 & 0x10)
148                                         p |= 0x02;
149                                 if(p1 & 0x20)
150                                         p |= 0x0C;
151                                 else if(p0 & 0x20)
152                                         p |= 0x08;
153                                 if(p1 & 0x40)
154                                         p |= 0x30;
155                                 else if(p0 & 0x40)
156                                         p |= 0x20;
157                                 if(p1 & 0x80)
158                                         p |= 0xC0;
159                                 else if(p0 & 0x80)
160                                         p |= 0x80;
161                                 tvp3020xo(0x0A, p);     /* Cursor RAM Data */
162
163                                 p = 0x00;
164                                 if(p1 & 0x01)
165                                         p |= 0x03;
166                                 else if(p0 & 0x01)
167                                         p |= 0x02;
168                                 if(p1 & 0x02)
169                                         p |= 0x0C;
170                                 else if(p0 & 0x02)
171                                         p |= 0x08;
172                                 if(p1 & 0x04)
173                                         p |= 0x30;
174                                 else if(p0 & 0x04)
175                                         p |= 0x20;
176                                 if(p1 & 0x08)
177                                         p |= 0xC0;
178                                 else if(p0 & 0x08)
179                                         p |= 0x80;
180                                 tvp3020xo(0x0A, p);     /* Cursor RAM Data */
181                         }
182                         else{
183                                 tvp3020xo(0x0A, 0x00);  /* Cursor RAM Data */
184                                 tvp3020xo(0x0A, 0x00);
185                         }
186                 }
187         }
188
189         /*
190          * Initialise the cursor hotpoint
191          * and enable the cursor.
192          */
193         tvp3020xo(0x04, -curs->offset.x);               /* Sprite Origin X */
194         tvp3020xo(0x05, -curs->offset.y);               /* Sprite Origin Y */
195
196         tvp3020xo(0x06, 0x40|0x10);                     /* Cursor Control Register */
197 }
198
199 static int
200 tvp3020move(VGAscr*, Point p)
201 {
202         tvp3020xo(0x00, p.x & 0xFF);                    /* Cursor Position X LSB */
203         tvp3020xo(0x01, (p.x>>8) & 0x0F);               /* Cursor Position X MSB */
204         tvp3020xo(0x02, p.y & 0xFF);                    /* Cursor Position Y LSB */
205         tvp3020xo(0x03, (p.y>>8) & 0x0F);               /* Cursor Position Y MSB */
206
207         return 0;
208 }
209
210 VGAcur vgatvp3020cur = {
211         "tvp3020hwgc",
212
213         tvp3020enable,
214         tvp3020disable,
215         tvp3020load,
216         tvp3020move,
217 };