]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgai81x.c
Import sources from 2011-03-30 iso image
[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 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 };