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