]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgai81x.c
devkbd: bits bad! revert repeat/delay, better patches welcome
[plan9front.git] / sys / src / 9 / pc / vgai81x.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
16 {
17         ushort  ctl;
18         ushort  pad;
19         ulong   base;
20         ulong   pos;
21 } CursorI81x;
22
23 enum {
24         Fbsize          = 8*MB,
25
26         hwCur           = 0x70080,
27         SRX             = 0x3c4,
28         DPMSsync        = 0x5002,
29 };
30
31 static void
32 i81xblank(VGAscr *scr, int blank)
33 {
34         char *srx, *srxd, *dpms;
35         char sr01, mode;
36
37         srx = (char *)scr->mmio+SRX;
38         srxd = srx+1;
39         dpms = (char *)scr->mmio+DPMSsync;
40
41         *srx = 0x01;
42         sr01 = *srxd & ~0x20;
43         mode = *dpms & 0xf0;
44
45         if(blank) {
46                 sr01 |= 0x20;
47                 mode |= 0x0a;
48         }
49         *srxd = sr01;
50         *dpms = mode;
51 }
52
53 static void
54 i81xenable(VGAscr* scr)
55 {
56         Pcidev *p;
57         int size;
58         ulong *pgtbl, *rp, fbuf, fbend;
59         
60         if(scr->mmio)
61                 return;
62         p = scr->pci;
63         if(p == nil)
64                 return;
65         scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
66         if(scr->mmio == 0)
67                 return;
68         addvgaseg("i81xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
69
70         /* allocate page table */
71         pgtbl = xspanalloc(64*1024, BY2PG, 0);
72         scr->mmio[0x2020/4] = PADDR(pgtbl) | 1;
73
74         size = p->mem[0].size;
75         if(size > 0)
76                 size = Fbsize;
77         vgalinearaddr(scr, p->mem[0].bar&~0xF, size);
78         addvgaseg("i81xscreen", p->mem[0].bar&~0xF, size);
79
80         /*
81          * allocate backing store for frame buffer
82          * and populate device page tables.
83          */
84         fbuf = PADDR(xspanalloc(size, BY2PG, 0));
85         fbend = PGROUND(fbuf+size);
86         rp = scr->mmio+0x10000/4;
87         while(fbuf < fbend) {
88                 *rp++ = fbuf | 1;
89                 fbuf += BY2PG;
90         }
91
92         scr->storage = 0;
93         scr->blank = i81xblank;
94 }
95
96 static void
97 i81xcurdisable(VGAscr* scr)
98 {
99         CursorI81x *hwcurs;
100
101         if(scr->mmio == 0)
102                 return;
103         hwcurs = (void*)((uchar*)scr->mmio+hwCur);
104         hwcurs->ctl = (1<<4);
105 }
106
107 static void
108 i81xcurload(VGAscr* scr, Cursor* curs)
109 {
110         int y;
111         uchar *p;
112         CursorI81x *hwcurs;
113
114         if(scr->mmio == 0 || scr->storage == 0)
115                 return;
116         hwcurs = (void*)((uchar*)scr->mmio+hwCur);
117
118         /*
119          * Disable the cursor then load the new image in
120          * the top-left of the 32x32 array.
121          * Unused portions of the image have been initialised to be
122          * transparent.
123          */
124         hwcurs->ctl = (1<<4);
125         p = (uchar*)scr->storage;
126         for(y = 0; y < 16; y += 2) {
127                 *p++ = ~(curs->clr[2*y]|curs->set[2*y]);
128                 *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
129                 p += 2;
130                 *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
131                 *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
132                 p += 2;
133                 *p++ = curs->set[2*y];
134                 *p++ = curs->set[2*y+1];
135                 p += 2;
136                 *p++ = curs->set[2*y+2];
137                 *p++ = curs->set[2*y+3];
138                 p += 2;
139         }
140
141         /*
142          * Save the cursor hotpoint and enable the cursor.
143          * The 0,0 cursor point is top-left.
144          */
145         scr->offset.x = curs->offset.x;
146         scr->offset.y = curs->offset.y;
147         hwcurs->ctl = (1<<4)|1;
148 }
149
150 static int
151 i81xcurmove(VGAscr* scr, Point p)
152 {
153         int x, y;
154         ulong pos;
155         CursorI81x *hwcurs;
156
157         if(scr->mmio == 0)
158                 return 1;
159         hwcurs = (void*)((uchar*)scr->mmio+hwCur);
160
161         x = p.x+scr->offset.x;
162         y = p.y+scr->offset.y;
163         pos = 0;
164         if(x < 0) {
165                 pos |= (1<<15);
166                 x = -x;
167         }
168         if(y < 0) {
169                 pos |= (1<<31);
170                 y = -y;
171         }
172         pos |= ((y&0x7ff)<<16)|(x&0x7ff);
173         hwcurs->pos = pos;
174
175         return 0;
176 }
177
178 static void
179 i81xcurenable(VGAscr* scr)
180 {
181         int i;
182         uchar *p;
183
184         i81xenable(scr);
185         if(scr->mmio == 0)
186                 return;
187
188         if(scr->storage == 0){
189                 CursorI81x *hwcurs;
190                 Page *pg = newpage(0, nil, 0);
191                 scr->storage = (uintptr)vmap(pg->pa, BY2PG);
192                 if(scr->storage == 0){
193                         putpage(pg);
194                         return;
195                 }
196                 hwcurs = (void*)((uchar*)scr->mmio+hwCur);
197                 hwcurs->base = pg->pa;
198         }
199
200         /*
201          * Initialise the 32x32 cursor to be transparent in 2bpp mode.
202          */
203         p = (uchar*)scr->storage;
204         for(i = 0; i < 32/2; i++) {
205                 memset(p, 0xff, 8);
206                 memset(p+8, 0, 8);
207                 p += 16;
208         }
209
210         /*
211          * Load, locate and enable the 32x32 cursor in 2bpp mode.
212          */
213         i81xcurload(scr, &arrow);
214         i81xcurmove(scr, ZP);
215 }
216
217 VGAdev vgai81xdev = {
218         "i81x",
219
220         i81xenable,
221         nil,
222         nil,
223         nil,
224 };
225
226 VGAcur vgai81xcur = {
227         "i81xhwgc",
228
229         i81xcurenable,
230         i81xcurdisable,
231         i81xcurload,
232         i81xcurmove,
233 };