]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgaet4000.c
devdraw: get rid of softscreen==0xa110c hack and make attachscreen() return Memdata*
[plan9front.git] / sys / src / 9 / pc / vgaet4000.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 void
16 setet4000page(int page)
17 {
18         uchar p;
19
20         p = page & 0x0F;
21         p |= p<<4;
22         outb(0x3CD, p);
23
24         p = (page & 0x30);
25         p |= p>>4;
26         outb(0x3CB, p);
27 }
28
29 static void
30 et4000page(VGAscr *scr, int page)
31 {
32         lock(&scr->devlock);
33         setet4000page(page);
34         unlock(&scr->devlock);
35 }
36
37 static void
38 et4000disable(VGAscr*)
39 {
40         uchar imaF7;
41
42         outb(0x217A, 0xF7);
43         imaF7 = inb(0x217B) & ~0x80;
44         outb(0x217B, imaF7);
45 }
46
47 static void
48 et4000enable(VGAscr *scr)
49 {
50         uchar imaF7;
51
52         et4000disable(scr);
53
54         /*
55          * Configure CRTCB for Sprite, 64x64,
56          * CRTC pixel overlay.
57          */
58         outb(0x217A, 0xEF);
59         outb(0x217B, 0x02);
60
61         /*
62          * Cursor goes in the top left corner
63          * of the Sprite area, so the horizontal and
64          * vertical presets are 0.
65          */
66         outb(0x217A, 0xE2);
67         outb(0x217B, 0x00);
68         outb(0x217A, 0xE3);
69         outb(0x217B, 0x00);
70
71         outb(0x217A, 0xE6);
72         outb(0x217B, 0x00);
73         outb(0x217A, 0xE7);
74         outb(0x217B, 0x00);
75
76         /*
77          * Find a place for the cursor data in display memory.
78          * Must be on a "doubleword" boundary, but put it on a
79          * 1024-byte boundary so that there's no danger of it
80          * crossing a page.
81          */
82         scr->storage = (scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y+1023)/1024;
83         scr->storage *= 1024/4;
84         outb(0x217A, 0xE8);
85         outb(0x217B, scr->storage & 0xFF);
86         outb(0x217A, 0xE9);
87         outb(0x217B, (scr->storage>>8) & 0xFF);
88         outb(0x217A, 0xEA);
89         outb(0x217B, (scr->storage>>16) & 0x0F);
90         scr->storage *= 4;
91
92         /*
93          * Row offset in "quadwords". Must be 2 for Sprite.
94          * Bag the pixel-panning.
95          * Colour depth, must be 2 for Sprite.
96          */
97         outb(0x217A, 0xEB);
98         outb(0x217B, 0x02);
99         outb(0x217A, 0xEC);
100         outb(0x217B, 0x00);
101
102         outb(0x217A, 0xED);
103         outb(0x217B, 0x00);
104
105         outb(0x217A, 0xEE);
106 //      if(vgascreen.ldepth == 3)
107                 outb(0x217B, 0x01);
108 //      else
109 //              outb(0x217B, 0x00);
110
111         /*
112          * Enable the CRTCB/Sprite.
113          */
114         outb(0x217A, 0xF7);
115         imaF7 = inb(0x217B);
116         outb(0x217B, 0x80|imaF7);
117 }
118
119 static void
120 et4000load(VGAscr *scr, Cursor *c)
121 {
122         uchar p0, p1, *mem;
123         int i, x, y;
124         ushort p;
125         uchar clr[2*16], set[2*16];
126
127         /*
128          * Lock the display memory so we can update the
129          * cursor bitmap if necessary.
130          */
131         lock(&scr->devlock);
132
133         /*
134          * Disable the cursor.
135          * Set the display page (do we need to restore
136          * the current contents when done?) and the
137          * pointer to the two planes. What if this crosses
138          * into a new page?
139          */
140         et4000disable(scr);
141
142         setet4000page(scr->storage>>16);
143         mem = (uchar*)scr->vaddr + (scr->storage & 0xFFFF);
144
145         /*
146          * Initialise the 64x64 cursor RAM array. There are 2 planes,
147          * p0 and p1. Data is written 4 pixels per byte, with p1 the
148          * MS bit of each pixel.
149          * The cursor mode gives the following truth table:
150          *      p1 p0   colour
151          *       0  0   Sprite Colour 0 (defined as 0x00)
152          *       0  1   Sprite Colour 1 (defined as 0xFF)
153          *       1  0   Transparent (allow CRTC pixel pass through)
154          *       1  1   Invert (allow CRTC pixel invert through)
155          * Put the cursor into the top-left of the 64x64 array.
156          *
157          * This is almost certainly wrong, since it has not
158          * been updated for the 3rd edition color values.
159          */
160         memmove(clr, c->clr, sizeof(clr));
161 //      pixreverse(clr, sizeof(clr), 0);
162         memmove(set, c->set, sizeof(set));
163 //      pixreverse(set, sizeof(set), 0);
164         for(y = 0; y < 64; y++){
165                 for(x = 0; x < 64/8; x++){
166                         if(x < 16/8 && y < 16){
167                                 p0 = clr[x+y*2];
168                                 p1 = set[x+y*2];
169
170                                 p = 0x0000;
171                                 for(i = 0; i < 8; i++){
172                                         if(p1 & (1<<(7-i))){
173                                                 /* nothing to do */
174                                         }
175                                         else if(p0 & (1<<(7-i)))
176                                                 p |= 0x01<<(2*i);
177                                         else
178                                                 p |= 0x02<<(2*i);
179                                 }
180                                 *mem++ = p & 0xFF;
181                                 *mem++ = (p>>8) & 0xFF;
182                         }
183                         else {
184                                 *mem++ = 0xAA;
185                                 *mem++ = 0xAA;
186                         }
187                 }
188         }
189
190         /*
191          * enable the cursor.
192          */
193         outb(0x217A, 0xF7);
194         p = inb(0x217B)|0x80;
195         outb(0x217B, p);
196
197         unlock(&scr->devlock);
198 }
199
200 static int
201 et4000move(VGAscr *scr, Point p)
202 {
203         int x, xo, y, yo;
204
205         if(canlock(&scr->devlock) == 0)
206                 return 1;
207
208         /*
209          * Mustn't position the cursor offscreen even partially,
210          * or it disappears. Therefore, if x or y is -ve, adjust the
211          * cursor presets instead.
212          */
213         if((x = p.x+scr->offset.x) < 0){
214                 xo = -x;
215                 x = 0;
216         }
217         else
218                 xo = 0;
219         if((y = p.y+scr->offset.y) < 0){
220                 yo = -y;
221                 y = 0;
222         }
223         else
224                 yo = 0;
225
226         /*
227          * The cursor image is jerky if we don't do this.
228          * The cursor information is probably fetched from
229          * display memory during the horizontal blank active
230          * time and it doesn't like it if the coordinates
231          * are changed underneath.
232          */
233         while((vgai(Status1) & 0x08) == 0)
234                 ;
235
236         outb(0x217A, 0xE2);
237         outb(0x217B, xo);
238
239         outb(0x217A, 0xE6);
240         outb(0x217B, yo);
241
242         outb(0x217A, 0xE1);
243         outb(0x217B, (x>>8) & 0xFF);
244         outb(0x217A, 0xE0);
245         outb(0x217B, x & 0xFF);
246         outb(0x217A, 0xE5);
247         outb(0x217B, (y>>8) & 0xFF);
248         outb(0x217A, 0xE4);
249         outb(0x217B, y & 0xFF);
250
251         unlock(&scr->devlock);
252         return 0;
253 }
254
255 VGAcur vgaet4000cur = {
256         "et4000hwgc",
257
258         et4000enable,
259         et4000disable,
260         et4000load,
261         et4000move,
262 };
263
264 VGAdev vgaet4000dev = {
265         "et4000",
266
267         0,
268         0,
269         et4000page,
270         0
271 };