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