FreeBSD/Linux Kernel Cross Reference
sys/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 Pcidev *
54 i81xpcimatch(void)
55 {
56 Pcidev *p;
57
58 p = nil;
59 while((p = pcimatch(p, 0x8086, 0)) != nil){
60 switch(p->did){
61 default:
62 continue;
63 case 0x7121:
64 case 0x7123:
65 case 0x7125:
66 case 0x1102:
67 case 0x1112:
68 case 0x1132:
69 case 0x3577: /* IBM R31 uses intel 830M chipset */
70 return p;
71 }
72 }
73 return nil;
74 }
75
76 static void
77 i81xenable(VGAscr* scr)
78 {
79 Pcidev *p;
80 int size;
81 Mach *mach0;
82 ulong *pgtbl, *rp, cursor, *pte, fbuf, fbend;
83
84 if(scr->mmio)
85 return;
86 p = i81xpcimatch();
87 if(p == nil)
88 return;
89 scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
90 if(scr->mmio == 0)
91 return;
92 addvgaseg("i81xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
93
94 /* allocate page table */
95 pgtbl = xspanalloc(64*1024, BY2PG, 0);
96 scr->mmio[0x2020/4] = PADDR(pgtbl) | 1;
97
98 size = p->mem[0].size;
99 if(size > 0)
100 size = Fbsize;
101 vgalinearaddr(scr, p->mem[0].bar&~0xF, size);
102 addvgaseg("i81xscreen", p->mem[0].bar&~0xF, size);
103
104 /*
105 * allocate backing store for frame buffer
106 * and populate device page tables.
107 */
108 fbuf = PADDR(xspanalloc(size, BY2PG, 0));
109 fbend = PGROUND(fbuf+size);
110 rp = scr->mmio+0x10000/4;
111 while(fbuf < fbend) {
112 *rp++ = fbuf | 1;
113 fbuf += BY2PG;
114 }
115
116 /*
117 * allocate space for the cursor data in system memory.
118 * must be uncached.
119 */
120 cursor = (ulong)xspanalloc(BY2PG, BY2PG, 0);
121 mach0 = MACHP(0);
122 pte = mmuwalk(mach0->pdb, cursor, 2, 0);
123 if(pte == nil)
124 panic("i81x cursor mmuwalk");
125 *pte |= PTEUNCACHED;
126 scr->storage = cursor;
127
128 scr->blank = i81xblank;
129 hwblank = 1;
130 }
131
132 static void
133 i81xcurdisable(VGAscr* scr)
134 {
135 CursorI81x *hwcurs;
136
137 if(scr->mmio == 0)
138 return;
139 hwcurs = (void*)((uchar*)scr->mmio+hwCur);
140 hwcurs->ctl = (1<<4);
141 }
142
143 static void
144 i81xcurload(VGAscr* scr, Cursor* curs)
145 {
146 int y;
147 uchar *p;
148 CursorI81x *hwcurs;
149
150 if(scr->mmio == 0)
151 return;
152 hwcurs = (void*)((uchar*)scr->mmio+hwCur);
153
154 /*
155 * Disable the cursor then load the new image in
156 * the top-left of the 32x32 array.
157 * Unused portions of the image have been initialised to be
158 * transparent.
159 */
160 hwcurs->ctl = (1<<4);
161 p = (uchar*)scr->storage;
162 for(y = 0; y < 16; y += 2) {
163 *p++ = ~(curs->clr[2*y]|curs->set[2*y]);
164 *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
165 p += 2;
166 *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
167 *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
168 p += 2;
169 *p++ = curs->set[2*y];
170 *p++ = curs->set[2*y+1];
171 p += 2;
172 *p++ = curs->set[2*y+2];
173 *p++ = curs->set[2*y+3];
174 p += 2;
175 }
176
177 /*
178 * Save the cursor hotpoint and enable the cursor.
179 * The 0,0 cursor point is top-left.
180 */
181 scr->offset.x = curs->offset.x;
182 scr->offset.y = curs->offset.y;
183 hwcurs->ctl = (1<<4)|1;
184 }
185
186 static int
187 i81xcurmove(VGAscr* scr, Point p)
188 {
189 int x, y;
190 ulong pos;
191 CursorI81x *hwcurs;
192
193 if(scr->mmio == 0)
194 return 1;
195 hwcurs = (void*)((uchar*)scr->mmio+hwCur);
196
197 x = p.x+scr->offset.x;
198 y = p.y+scr->offset.y;
199 pos = 0;
200 if(x < 0) {
201 pos |= (1<<15);
202 x = -x;
203 }
204 if(y < 0) {
205 pos |= (1<<31);
206 y = -y;
207 }
208 pos |= ((y&0x7ff)<<16)|(x&0x7ff);
209 hwcurs->pos = pos;
210
211 return 0;
212 }
213
214 static void
215 i81xcurenable(VGAscr* scr)
216 {
217 int i;
218 uchar *p;
219 CursorI81x *hwcurs;
220
221 i81xenable(scr);
222 if(scr->mmio == 0)
223 return;
224 hwcurs = (void*)((uchar*)scr->mmio+hwCur);
225
226 /*
227 * Initialise the 32x32 cursor to be transparent in 2bpp mode.
228 */
229 hwcurs->base = PADDR(scr->storage);
230 p = (uchar*)scr->storage;
231 for(i = 0; i < 32/2; i++) {
232 memset(p, 0xff, 8);
233 memset(p+8, 0, 8);
234 p += 16;
235 }
236 /*
237 * Load, locate and enable the 32x32 cursor in 2bpp mode.
238 */
239 i81xcurload(scr, &arrow);
240 i81xcurmove(scr, ZP);
241 }
242
243 VGAdev vgai81xdev = {
244 "i81x",
245
246 i81xenable,
247 nil,
248 nil,
249 nil,
250 };
251
252 VGAcur vgai81xcur = {
253 "i81xhwgc",
254
255 i81xcurenable,
256 i81xcurdisable,
257 i81xcurload,
258 i81xcurmove,
259 };
Cache object: 302d232246b4634665f152c24908e157
|