]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgaark2000pv.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / vgaark2000pv.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 static int
16 ark2000pvpageset(VGAscr*, int page)
17 {
18         uchar seq15;
19
20         seq15 = vgaxi(Seqx, 0x15);
21         vgaxo(Seqx, 0x15, page);
22         vgaxo(Seqx, 0x16, page);
23
24         return seq15;
25 }
26
27 static void
28 ark2000pvpage(VGAscr* scr, int page)
29 {
30         lock(&scr->devlock);
31         ark2000pvpageset(scr, page);
32         unlock(&scr->devlock);
33 }
34
35 static void
36 ark2000pvdisable(VGAscr*)
37 {
38         uchar seq20;
39
40         seq20 = vgaxi(Seqx, 0x20) & ~0x08;
41         vgaxo(Seqx, 0x20, seq20);
42 }
43
44 static void
45 ark2000pvenable(VGAscr* scr)
46 {
47         uchar seq20;
48         ulong storage;
49
50         /*
51          * Disable the cursor then configure for X-Windows style,
52          * 32x32 and 4/8-bit colour depth.
53          * Set cursor colours for 4/8-bit.
54          */
55         seq20 = vgaxi(Seqx, 0x20) & ~0x1F;
56         vgaxo(Seqx, 0x20, seq20);
57         seq20 |= 0x18;
58
59         vgaxo(Seqx, 0x26, 0x00);
60         vgaxo(Seqx, 0x27, 0x00);
61         vgaxo(Seqx, 0x28, 0x00);
62         vgaxo(Seqx, 0x29, 0xFF);
63         vgaxo(Seqx, 0x2A, 0xFF);
64         vgaxo(Seqx, 0x2B, 0xFF);
65
66         /*
67          * Cursor storage is a 256 byte or 1Kb block located in the last
68          * 16Kb of video memory. Crt25 is the index of which block.
69          */
70         storage = (vgaxi(Seqx, 0x10)>>6) & 0x03;
71         storage = (1024*1024)<<storage;
72         storage -= 256;
73         scr->storage = storage;
74         vgaxo(Seqx, 0x25, 0x3F);
75
76         /*
77          * Enable the cursor.
78          */
79         vgaxo(Seqx, 0x20, seq20);
80 }
81
82 static void
83 ark2000pvload(VGAscr* scr, Cursor* curs)
84 {
85         uchar *p, seq10;
86         int opage, x, y;
87
88         /*
89          * Is linear addressing turned on? This will determine
90          * how we access the cursor storage.
91          */
92         seq10 = vgaxi(Seqx, 0x10);
93         opage = 0;
94         p = scr->vaddr;
95         if(!(seq10 & 0x10)){
96                 lock(&scr->devlock);
97                 opage = ark2000pvpageset(scr, scr->storage>>16);
98                 p += (scr->storage & 0xFFFF);
99         }
100         else
101                 p += scr->storage;
102
103         /*
104          * The cursor is set in X11 mode which gives the following
105          * truth table:
106          *      and xor colour
107          *       0   0  underlying pixel colour
108          *       0   1  underlying pixel colour
109          *       1   0  background colour
110          *       1   1  foreground colour
111          * Put the cursor into the top-left of the 32x32 array.
112          * The manual doesn't say what the data layout in memory is -
113          * this worked out by trial and error.
114          */
115         for(y = 0; y < 32; y++){
116                 for(x = 0; x < 32/8; x++){
117                         if(x < 16/8 && y < 16){
118                                 *p++ = curs->clr[2*y + x]|curs->set[2*y + x];
119                                 *p++ = curs->set[2*y + x];
120                         }
121                         else {
122                                 *p++ = 0x00;
123                                 *p++ = 0x00;
124                         }
125                 }
126         }
127
128         if(!(seq10 & 0x10)){
129                 ark2000pvpageset(scr, opage);
130                 unlock(&scr->devlock);
131         }
132
133         /*
134          * Save the cursor hotpoint.
135          */
136         scr->offset = curs->offset;
137 }
138
139 static int
140 ark2000pvmove(VGAscr* scr, Point p)
141 {
142         int x, xo, y, yo;
143
144         /*
145          * Mustn't position the cursor offscreen even partially,
146          * or it might disappear. Therefore, if x or y is -ve, adjust the
147          * cursor origins instead.
148          */
149         if((x = p.x+scr->offset.x) < 0){
150                 xo = -x;
151                 x = 0;
152         }
153         else
154                 xo = 0;
155         if((y = p.y+scr->offset.y) < 0){
156                 yo = -y;
157                 y = 0;
158         }
159         else
160                 yo = 0;
161
162         /*
163          * Load the new values.
164          */
165         vgaxo(Seqx, 0x2C, xo);
166         vgaxo(Seqx, 0x2D, yo);
167         vgaxo(Seqx, 0x21, (x>>8) & 0x0F);
168         vgaxo(Seqx, 0x22, x & 0xFF);
169         vgaxo(Seqx, 0x23, (y>>8) & 0x0F);
170         vgaxo(Seqx, 0x24, y & 0xFF);
171
172         return 0;
173 }
174
175 VGAdev vgaark2000pvdev = {
176         "ark2000pv",
177
178         0,
179         0,
180         ark2000pvpage,
181         0,
182 };
183
184 VGAcur vgaark2000pvcur = {
185         "ark2000pvhwgc",
186
187         ark2000pvenable,
188         ark2000pvdisable,
189         ark2000pvload,
190         ark2000pvmove,
191 };