1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 /*
9 * #9 Ticket to Ride IV.
10 */
11 typedef struct {
12 Pcidev* pci;
13 ulong io;
14 uchar* mmio;
15
16 ulong ioreg[13];
17 ulong g[25];
18 ulong w[25];
19 } T2r4;
20
21 enum { /* memory mapped global registers */
22 IntVcnt = 0x20/4, /* vertical interrupt counter */
23 IntHcnt = 0x24/4, /* horizontal interrupt counter */
24 DbAdr = 0x28/4, /* display start address */
25 DbPtch = 0x2C/4, /* display pitch */
26 CrtHac = 0x30/4, /* horizontal active line width */
27 CrtHbl = 0x34/4, /* horizontal blank width */
28 CrtHfp = 0x38/4, /* horizontal front porch */
29 CrtHs = 0x3C/4, /* horizontal sync width */
30 CrtVac = 0x40/4, /* vertical active field width */
31 CrtVbl = 0x44/4, /* vertical blank width */
32 CrtVfp = 0x48/4, /* vertical front porch */
33 CrtVs = 0x4C/4, /* vertical sync width */
34 CrtLcnt = 0x50/4, /* CRT line counter */
35 CrtZoom = 0x54/4, /* display zoom factor */
36 Crt1con = 0x58/4, /* CRT configuration register 1 */
37 Crt2con = 0x5C/4, /* CRT configuration register 2 */
38 DbAdr2 = 0x60/4, /* CRT display start address 2 */
39 };
40
41 enum { /* memory windows registers */
42 Mw0Ctrl = 0x00/4, /* memory window 0 control */
43 Mw0Ad = 0x04/4, /* memory window 0 address */
44 Mw0Sz = 0x08/4, /* memory window 0 size */
45 Mw0Org = 0x10/4, /* memory window 0 origin */
46 Mw0Mask = 0x24/4, /* Memory window 0 plane mask */
47 Mw1Ctlr = 0x28/4, /* memory window 1 control */
48 Mw1Ad = 0x2C/4, /* memory window 1 address */
49 Mw1Sz = 0x30/4, /* memory window 1 size */
50 Mw1Org = 0x38/4, /* memory window 1 origin */
51 Mw1Mask = 0x4C/4, /* Memory window 1 plane mask */
52 MwcFcnt = 0x50/4, /* memory window cache flush counter */
53 MwcFlsh = 0x54/4, /* manual cache flush */
54 YuvLi = 0x58/4, /* YUV LUT index */
55 YuvLa = 0x5C/4, /* YUV LUT address */
56 MwCtrl = 0x60/4, /* memory window 0 and 1 control */
57 };
58
59 enum {
60 IndexLo = 4,
61 IndexHi = 5,
62 Data = 6,
63 IndexCtl = 7,
64 };
65
66 static uchar
_rgb524xi(Vga * vga,int index)67 _rgb524xi(Vga* vga, int index)
68 {
69 ulong *mmio;
70
71 mmio = (ulong*)((T2r4*)vga->private)->mmio;
72 mmio[IndexLo] = index & 0xFF;
73 mmio[IndexHi] = (index>>8) & 0xFF;
74
75 return mmio[Data];
76 }
77
78 static void
_rgb524xo(Vga * vga,int index,uchar data)79 _rgb524xo(Vga* vga, int index, uchar data)
80 {
81 ulong *mmio;
82
83 mmio = (ulong*)((T2r4*)vga->private)->mmio;
84 mmio[IndexLo] = index & 0xFF;
85 mmio[IndexHi] = (index>>8) & 0xFF;
86
87 mmio[Data] = data;
88 }
89
90 static void
snarf(Vga * vga,Ctlr * ctlr)91 snarf(Vga* vga, Ctlr* ctlr)
92 {
93 ulong *mmio;
94 int f, i, x;
95 Pcidev *p;
96 T2r4 *t2r4;
97 ulong *rp;
98
99 if(vga->private == nil){
100 vga->private = alloc(sizeof(T2r4));
101 if((p = pcimatch(0, 0x105D, 0)) == nil)
102 error("%s: not found\n", ctlr->name);
103 switch(p->did){
104 case 0x5348: /* */
105 break;
106 default:
107 error("%s: not found\n", ctlr->name);
108 }
109
110 if((f = open("#v/vgactl", OWRITE)) < 0)
111 error("%s: can't open vgactl\n", ctlr->name);
112 if(write(f, "type t2r4", 9) != 9)
113 error("%s: can't set type\n", ctlr->name);
114 close(f);
115
116 mmio = segattach(0, "t2r4mmio", 0, p->mem[4].size);
117 if(mmio == (void*)-1)
118 error("%s: can't attach mmio segment\n", ctlr->name);
119
120 t2r4 = vga->private;
121 t2r4->pci = p;
122 t2r4->io = p->mem[5].bar & ~0x0F;
123 t2r4->mmio = (uchar*)mmio;
124 }
125 t2r4 = vga->private;
126 for(i = 0; i < nelem(t2r4->ioreg); i++)
127 t2r4->ioreg[i] = inportl(t2r4->io+(i*4));
128
129 x = t2r4->ioreg[7] & 0xFF00001F; /* config1 */
130 outportl(t2r4->io+0x1C, x|0x00331F10);
131
132 x = t2r4->ioreg[8] & 0xFF0FFFFF; /* config2 */
133 outportl(t2r4->io+0x20, x|0x00100000);
134
135 x = inportl(t2r4->io+0x30) & 0xFF; /* vgactl */
136 outportl(t2r4->io+0x30, x|0x82);
137
138 rp = (ulong*)t2r4->mmio;
139 for(i = 0; i < nelem(t2r4->g); i++)
140 t2r4->g[i] = *rp++;
141 rp = (ulong*)(t2r4->mmio+8192);
142 for(i = 0; i < nelem(t2r4->w); i++)
143 t2r4->w[i] = *rp++;
144
145 vga->vma = vga->vmz = t2r4->pci->mem[0].size;
146 ctlr->flag |= Hlinear;
147
148 /*
149 * Currently, the RGB524 has no need of a snarf
150 * routine so this will be called before any RGB524 code.
151 */
152 if(vga->ramdac && strncmp(vga->ramdac->name, "rgb524mn", 8) == 0){
153 rgb524mnxi = _rgb524xi;
154 rgb524mnxo = _rgb524xo;
155 }
156
157 ctlr->flag |= Fsnarf;
158 }
159
160 static void
options(Vga * vga,Ctlr * ctlr)161 options(Vga* vga, Ctlr* ctlr)
162 {
163 USED(vga);
164 ctlr->flag |= Foptions;
165 }
166
167 static void
init(Vga * vga,Ctlr * ctlr)168 init(Vga* vga, Ctlr* ctlr)
169 {
170 char *val;
171 T2r4 *t2r4;
172 int crtclocks, zoom;
173
174 t2r4 = vga->private;
175 crtclocks = 64/vga->mode->z;
176
177 zoom = 1;
178 if((val = dbattr(vga->mode->attr, "zoom")) && strtol(val, 0, 0))
179 zoom = 2;
180
181 t2r4->g[DbAdr] = 0;
182 switch(vga->mode->z){
183 case 8:
184 t2r4->g[DbPtch] = vga->mode->x*1;
185 break;
186 case 16:
187 t2r4->g[DbPtch] = vga->mode->x*2;
188 break;
189 case 32:
190 t2r4->g[DbPtch] = vga->mode->x*4;
191 break;
192 }
193 t2r4->g[CrtHac] = vga->mode->x/crtclocks;
194 t2r4->g[CrtHbl] = (vga->mode->ht-vga->mode->x)/crtclocks;
195 if(vga->mode->shs == 0)
196 vga->mode->shs = vga->mode->shb;
197 t2r4->g[CrtHfp] = (vga->mode->shs-vga->mode->x)/crtclocks;
198 if(vga->mode->ehs == 0)
199 vga->mode->ehs = vga->mode->ehb;
200 t2r4->g[CrtHs] = (vga->mode->ehs-vga->mode->shs)/crtclocks;
201 t2r4->g[CrtVac] = vga->mode->y * zoom;
202 t2r4->g[CrtVbl] = (vga->mode->vt-vga->mode->y) * zoom;
203 t2r4->g[CrtVfp] = (vga->mode->vrs-vga->mode->y) * zoom;
204 t2r4->g[CrtVs] = (vga->mode->vre-vga->mode->vrs) * zoom;
205 t2r4->g[CrtZoom] = 0;
206
207 /*
208 * Turn on the syncs and video.
209 * Bts (bit 0x100) is digital RGB output enable. If there's
210 * a flat-panel then this is hopefully already set by the BIOS,
211 * so don't touch it. (It's possible that bit 0 of SoftSw
212 * indicates flat-panel or CRT).
213 */
214 t2r4->g[Crt1con] &= 0x00000100;
215 t2r4->g[Crt1con] |= 0x70;
216 t2r4->g[Crt2con] = 0x20000100;
217
218 if(zoom == 2)
219 t2r4->g[CrtZoom] = 1;
220
221 t2r4->w[Mw0Ctrl] = 0;
222 t2r4->w[Mw0Sz] = 0x0D; /* 32MB */
223 t2r4->w[Mw0Org] = 0;
224 t2r4->w[Mw0Mask] = 0xFFFFFFFF;
225
226 if(vga->linear && (ctlr->flag & Hlinear))
227 ctlr->flag |= Ulinear;
228
229 ctlr->flag |= Finit;
230 }
231
232 static void
load(Vga * vga,Ctlr * ctlr)233 load(Vga* vga, Ctlr* ctlr)
234 {
235 T2r4 *t2r4;
236 ulong *g, *w;
237
238 t2r4 = vga->private;
239
240 g = (ulong*)t2r4->mmio;
241 g[DbAdr] = t2r4->g[DbAdr];
242 g[DbPtch] = t2r4->g[DbPtch];
243 g[CrtHac] = t2r4->g[CrtHac];
244 g[CrtHbl] = t2r4->g[CrtHbl];
245 g[CrtHfp] = t2r4->g[CrtHfp];
246 g[CrtHs] = t2r4->g[CrtHs];
247 g[CrtVac] = t2r4->g[CrtVac];
248 g[CrtVbl] = t2r4->g[CrtVbl];
249 g[CrtVfp] = t2r4->g[CrtVfp];
250 g[CrtVs] = t2r4->g[CrtVs];
251 g[Crt1con] = t2r4->g[Crt1con];
252 g[Crt2con] = t2r4->g[Crt2con];
253 g[CrtZoom] = t2r4->g[CrtZoom];
254
255 w = (ulong*)(t2r4->mmio+8192);
256 w[Mw0Ctrl] = t2r4->w[Mw0Ctrl];
257 w[Mw0Sz] = t2r4->w[Mw0Sz];
258 w[Mw0Org] = t2r4->w[Mw0Org];
259 w[Mw0Mask] = t2r4->w[Mw0Mask];
260
261 if(t2r4->g[CrtZoom])
262 outportl(t2r4->io+0x30, 0xA2); /* vgactl */
263 else
264 outportl(t2r4->io+0x30, 0x82); /* vgactl */
265 outportl(t2r4->io+0x24, 0x211BF030); /* sgram */
266 sleep(500);
267 outportl(t2r4->io+0x24, 0xA11BF030); /* sgram */
268
269 ctlr->flag |= Fload;
270 }
271
272 static void
dump(Vga * vga,Ctlr * ctlr)273 dump(Vga* vga, Ctlr* ctlr)
274 {
275 int i;
276 T2r4 *t2r4;
277
278 t2r4 = vga->private;
279 Bprint(&stdout, "\n");
280 Bprint(&stdout, "%s ioreg\t\t%8.8luX\n", ctlr->name, t2r4->io);
281 Bprint(&stdout, "%s rbase_g\t%8.8luX\n", ctlr->name, t2r4->ioreg[0]);
282 Bprint(&stdout, "%s rbase_w\t%8.8luX\n", ctlr->name, t2r4->ioreg[1]);
283 Bprint(&stdout, "%s rbase_d\t%8.8luX\n", ctlr->name, t2r4->ioreg[2]);
284 Bprint(&stdout, "%s rbase_i\t%8.8luX\n", ctlr->name, t2r4->ioreg[4]);
285 Bprint(&stdout, "%s rbase_e\t%8.8luX\n", ctlr->name, t2r4->ioreg[5]);
286 Bprint(&stdout, "%s id\t\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[6]);
287 Bprint(&stdout, "%s config1\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[7]);
288 Bprint(&stdout, "%s config2\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[8]);
289 Bprint(&stdout, "%s sgram\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[9]);
290 Bprint(&stdout, "%s softsw\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[10]);
291 Bprint(&stdout, "%s ddc\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[11]);
292 Bprint(&stdout, "%s vgactl\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[12]);
293
294 Bprint(&stdout, "\n");
295 for(i = 0; i < nelem(t2r4->g); i++)
296 Bprint(&stdout, "%s g reg0x%2.2uX\t\t%8.8luX\n",
297 ctlr->name, i*4, t2r4->g[i]);
298 Bprint(&stdout, "\n");
299 for(i = 0; i < nelem(t2r4->w); i++)
300 Bprint(&stdout, "%s w reg0x%2.2uX\t\t%8.8luX\n",
301 ctlr->name, i*4, t2r4->w[i]);
302 }
303
304 Ctlr t2r4 = {
305 "t2r4", /* name */
306 snarf, /* snarf */
307 options, /* options */
308 init, /* init */
309 load, /* load */
310 dump, /* dump */
311 };
312
313 Ctlr t2r4hwgc = {
314 "t2r4hwgc", /* name */
315 0, /* snarf */
316 0, /* options */
317 0, /* init */
318 0, /* load */
319 0, /* dump */
320 };
321