]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgaclgd546x.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / vgaclgd546x.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 Cursor546x Cursor546x;
16 struct Cursor546x {
17         ushort  x;
18         ushort  y;
19         ushort  preset;
20         ushort  enable;
21         ushort  addr;
22 };
23
24 enum {
25         PaletteState    = 0xB0,
26         CursorMMIO      = 0xE0,
27 };
28
29 static void
30 clgd546xlinear(VGAscr* scr, int, int)
31 {
32         vgalinearpci(scr);
33 }
34
35 static void
36 clgd546xenable(VGAscr* scr)
37 {
38         Pcidev *p;
39
40         if(scr->mmio)
41                 return;
42         p = scr->pci;
43         if(p == nil)
44                 return;
45         scr->mmio = vmap(p->mem[1].bar&~0x0F, p->mem[1].size);
46         if(scr->mmio == 0)
47                 return;
48         addvgaseg("clgd546xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
49 }
50
51 static void
52 clgd546xcurdisable(VGAscr* scr)
53 {
54         Cursor546x *cursor546x;
55
56         if(scr->mmio == 0)
57                 return;
58         cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
59         cursor546x->enable = 0;
60 }
61
62 static void
63 clgd546xcurload(VGAscr* scr, Cursor* curs)
64 {
65         int c, i, m, y;
66         uchar *p;
67         Cursor546x *cursor546x;
68
69         if(scr->mmio == 0)
70                 return;
71         cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
72
73         /*
74          * Disable the cursor then change only the bits
75          * that need it.
76          */
77         cursor546x->enable = 0;
78         p = (uchar*)scr->vaddr + scr->storage;
79         for(y = 0; y < 16; y++){
80                 c = curs->set[2*y];
81                 m = 0;
82                 for(i = 0; i < 8; i++){
83                         if(c & (1<<(7-i)))
84                                 m |= 1<<i;
85                 }
86                 *p++ = m;
87                 c = curs->set[2*y + 1];
88                 m = 0;
89                 for(i = 0; i < 8; i++){
90                         if(c & (1<<(7-i)))
91                                 m |= 1<<i;
92                 }
93                 *p++ = m;
94                 p += 6;
95                 c = curs->set[2*y]|curs->clr[2*y];
96                 m = 0;
97                 for(i = 0; i < 8; i++){
98                         if(c & (1<<(7-i)))
99                                 m |= 1<<i;
100                 }
101                 *p++ = m;
102                 c = curs->set[2*y + 1]|curs->clr[2*y + 1];
103                 m = 0;
104                 for(i = 0; i < 8; i++){
105                         if(c & (1<<(7-i)))
106                                 m |= 1<<i;
107                 }
108                 *p++ = m;
109                 p += 6;
110         }
111
112         /*
113          * Save the cursor hotpoint and enable the cursor.
114          */
115         scr->offset = curs->offset;
116         cursor546x->enable = 1;
117 }
118
119 static int
120 clgd546xcurmove(VGAscr* scr, Point p)
121 {
122         int x, xo, y, yo;
123         Cursor546x *cursor546x;
124
125         if(scr->mmio == 0)
126                 return 1;
127         cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
128
129         if((x = p.x+scr->offset.x) < 0){
130                 xo = -x;
131                 x = 0;
132         }
133         else
134                 xo = 0;
135         if((y = p.y+scr->offset.y) < 0){
136                 yo = -y;
137                 y = 0;
138         }
139         else
140                 yo = 0;
141
142         cursor546x->preset = (xo<<8)|yo;
143         cursor546x->x = x;
144         cursor546x->y = y;
145
146         return 0;
147 }
148
149 static void
150 clgd546xcurenable(VGAscr* scr)
151 {
152         uchar *p;
153         Cursor546x *cursor546x;
154
155         clgd546xenable(scr);
156         if(scr->mmio == 0)
157                 return;
158         cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
159
160         /*
161          * Cursor colours.
162          * Can't call setcolor here as cursor is already locked.
163          */
164         p = (uchar*)scr->mmio+PaletteState;
165         *p |= 0x08;
166         vgao(PaddrW, 0x00);
167         vgao(Pdata, Pwhite);
168         vgao(Pdata, Pwhite);
169         vgao(Pdata, Pwhite);
170         vgao(PaddrW, 0x0F);
171         vgao(Pdata, Pblack);
172         vgao(Pdata, Pblack);
173         vgao(Pdata, Pblack);
174         *p &= ~0x08;
175
176         /*
177          * Find a place for the cursor data in display memory.
178          * 2 cursor images might be needed, 1KB each so use the last
179          * 2KB of the framebuffer and initialise them to be
180          * transparent.
181          */
182         scr->storage = ((vgaxi(Seqx, 0x14) & 0x07)+1)*1024*1022;
183         cursor546x->addr = (scr->storage>>10)<<2;
184         memset((uchar*)scr->vaddr + scr->storage, 0, 2*64*16);
185
186         /*
187          * Load, locate and enable the 64x64 cursor.
188          */
189         clgd546xcurload(scr, &cursor);
190         clgd546xcurmove(scr, ZP);
191         cursor546x->enable = 1;
192 }
193
194 VGAdev vgaclgd546xdev = {
195         "clgd546x",
196
197         clgd546xenable,
198         nil,
199         nil,
200         clgd546xlinear,
201 };
202
203 VGAcur vgaclgd546xcur = {
204         "clgd546xhwgc",
205
206         clgd546xcurenable,
207         clgd546xcurdisable,
208         clgd546xcurload,
209         clgd546xcurmove,
210 };