]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgacyber938x.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / vgacyber938x.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 enum {
16         CursorON        = 0xC8,
17         CursorOFF       = 0x00,
18 };
19
20 static int
21 cyber938xpageset(VGAscr*, int page)
22 {
23         int opage;
24
25         opage = inb(0x3D8);
26
27         outb(0x3D8, page);
28         outb(0x3D9, page);
29
30         return opage;
31 }
32
33 static void
34 cyber938xpage(VGAscr* scr, int page)
35 {
36         lock(&scr->devlock);
37         cyber938xpageset(scr, page);
38         unlock(&scr->devlock);
39 }
40
41 static void
42 cyber938xlinear(VGAscr* scr, int, int)
43 {
44         Pcidev *p;
45
46         if(scr->vaddr)
47                 return;
48         
49         p = scr->pci;
50         if(p == nil)
51                 return;
52
53         vgalinearpci(scr);
54
55         /*
56          * Heuristic to detect the MMIO space.  We're flying blind
57          * here, with only the XFree86 source to guide us.
58          */
59         if(p->mem[1].size == 0x20000)
60                 scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
61
62         if(scr->apsize)
63                 addvgaseg("cyber938xscreen", scr->paddr, scr->apsize);
64         if(scr->mmio)
65                 addvgaseg("cyber938xmmio", p->mem[1].bar&~0x0F, 0x20000);
66 }
67
68 static void
69 cyber938xcurdisable(VGAscr*)
70 {
71         vgaxo(Crtx, 0x50, CursorOFF);
72 }
73
74 static void
75 cyber938xcurload(VGAscr* scr, Cursor* curs)
76 {
77         uchar *p;
78         int islinear, opage, y;
79
80         cyber938xcurdisable(scr);
81
82         opage = 0;
83         p = scr->vaddr;
84         islinear = vgaxi(Crtx, 0x21) & 0x20;
85         if(!islinear){
86                 lock(&scr->devlock);
87                 opage = cyber938xpageset(scr, scr->storage>>16);
88                 p += (scr->storage & 0xFFFF);
89         }
90         else
91                 p += scr->storage;
92
93         for(y = 0; y < 16; y++){
94                 *p++ = curs->set[2*y]|curs->clr[2*y];
95                 *p++ = curs->set[2*y + 1]|curs->clr[2*y + 1];
96                 *p++ = 0x00;
97                 *p++ = 0x00;
98                 *p++ = curs->set[2*y];
99                 *p++ = curs->set[2*y + 1];
100                 *p++ = 0x00;
101                 *p++ = 0x00;
102         }
103         memset(p, 0, (32-y)*8);
104
105         if(!islinear){
106                 cyber938xpageset(scr, opage);
107                 unlock(&scr->devlock);
108         }
109
110         /*
111          * Save the cursor hotpoint and enable the cursor.
112          */
113         scr->offset = curs->offset;
114         vgaxo(Crtx, 0x50, CursorON);
115 }
116
117 static int
118 cyber938xcurmove(VGAscr* scr, Point p)
119 {
120         int x, xo, y, yo;
121
122         /*
123          * Mustn't position the cursor offscreen even partially,
124          * or it might disappear. Therefore, if x or y is -ve, adjust the
125          * cursor origins instead.
126          */
127         if((x = p.x+scr->offset.x) < 0){
128                 xo = -x;
129                 x = 0;
130         }
131         else
132                 xo = 0;
133         if((y = p.y+scr->offset.y) < 0){
134                 yo = -y;
135                 y = 0;
136         }
137         else
138                 yo = 0;
139
140         /*
141          * Load the new values.
142          */
143         vgaxo(Crtx, 0x46, xo);
144         vgaxo(Crtx, 0x47, yo);
145         vgaxo(Crtx, 0x40, x & 0xFF);
146         vgaxo(Crtx, 0x41, (x>>8) & 0xFF);
147         vgaxo(Crtx, 0x42, y & 0xFF);
148         vgaxo(Crtx, 0x43, (y>>8) & 0xFF);
149
150         return 0;
151 }
152
153 static void
154 cyber938xcurenable(VGAscr* scr)
155 {
156         int i;
157         ulong storage;
158
159         cyber938xcurdisable(scr);
160
161         /*
162          * Cursor colours.
163          */
164         for(i = 0x48; i < 0x4C; i++)
165                 vgaxo(Crtx, i, 0x00);
166         for(i = 0x4C; i < 0x50; i++)
167                 vgaxo(Crtx, i, 0xFF);
168
169         /*
170          * Find a place for the cursor data in display memory.
171          */
172         storage = ((scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y+1023)/1024);
173         vgaxo(Crtx, 0x44, storage & 0xFF);
174         vgaxo(Crtx, 0x45, (storage>>8) & 0xFF);
175         storage *= 1024;
176         scr->storage = storage;
177
178         /*
179          * Load, locate and enable the 32x32 cursor.
180          * (64x64 is bit 0, X11 format is bit 6 and cursor
181          * enable is bit 7). Bit 3 needs to be set on 9382
182          * chips otherwise even the white bits are black.
183          */
184         cyber938xcurload(scr, &cursor);
185         cyber938xcurmove(scr, ZP);
186         vgaxo(Crtx, 0x50, CursorON);
187 }
188
189 VGAdev vgacyber938xdev = {
190         "cyber938x",
191
192         nil,                            /* enable */
193         nil,                            /* disable */
194         cyber938xpage,                  /* page */
195         cyber938xlinear,                /* linear */
196         nil,                            /* drawinit */
197 };
198
199 VGAcur vgacyber938xcur = {
200         "cyber938xhwgc",
201
202         cyber938xcurenable,             /* enable */
203         cyber938xcurdisable,            /* disable */
204         cyber938xcurload,               /* load */
205         cyber938xcurmove,               /* move */
206 };