Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <ndb.h>
5
 
6
#include "pci.h"
7
#include "vga.h"
8
 
9
static Ndb*
10
dbopen(char* dbname)
11
{
12
	Ndb *db;
13
 
14
	if((db = ndbopen(dbname)) == 0)
15
		error("dbopen: %s: %r\n", dbname);
16
	return db;
17
}
18
 
19
static void
20
addattr(Attr** app, Ndbtuple* t)
21
{
22
	Attr *attr, *l;
23
 
24
	attr = alloc(sizeof(Attr));
25
	attr->attr = alloc(strlen(t->attr)+1);
26
	strcpy(attr->attr, t->attr);
27
	attr->val = alloc(strlen(t->val)+1);
28
	strcpy(attr->val, t->val);
29
 
30
	for(l = *app; l; l = l->next)
31
		app = &l->next;
32
	*app = attr;
33
}
34
 
35
char*
36
dbattr(Attr* ap, char* attr)
37
{
38
	while(ap){
39
		if(strcmp(ap->attr, attr) == 0)
40
			return ap->val;
41
		ap = ap->next;
42
	}
43
 
44
	return 0;
45
}
46
 
47
static Ctlr*
48
addctlr(Vga* vga, char* val)
49
{
50
	Ctlr **ctlr;
51
	char name[Namelen+1], *p;
52
	int i;
53
 
54
	/*
55
	 * A controller name may have an extension on the end
56
	 * following a '-' which can be used as a speed grade or
57
	 * subtype.  Do the match without the extension.
58
	 * The linked copy of the controller struct gets the
59
	 * full name with extension.
60
	 */
61
	strncpy(name, val, Namelen);
62
	name[Namelen] = 0;
63
	if(p = strchr(name, '-'))
64
		*p = 0;
65
 
66
	for(i = 0; ctlrs[i]; i++){
67
		if(strcmp(ctlrs[i]->name, name))
68
			continue;
69
		for(ctlr = &vga->link; *ctlr; ctlr = &((*ctlr)->link))
70
			;
71
		*ctlr = alloc(sizeof(Ctlr));
72
		**ctlr = *ctlrs[i];
73
		strncpy((*ctlr)->name, val, Namelen);
74
		return *ctlr;	
75
	}
76
 
77
	fprint(2, "dbctlr: unknown controller \"%s\" ctlr\n", val);
78
	return 0;
79
}
80
 
81
int
82
dbbios(Vga *vga, Ndbtuple *tuple)
83
{
84
	char *bios, *p, *string;
85
	int len;
86
	long offset, offset1;
87
	Ndbtuple *t;
88
 
89
	for(t = tuple->entry; t; t = t->entry){
90
		if((offset = strtol(t->attr, 0, 0)) == 0)
91
			continue;
92
 
93
		string = t->val;
94
		len = strlen(string);
95
 
96
		if(p = strchr(t->attr, '-')) {
97
			if((offset1 = strtol(p+1, 0, 0)) < offset+len)
98
				continue;
99
		} else
100
			offset1 = offset+len;
101
 
102
		if(vga->offset) {
103
			if(offset > vga->offset || vga->offset+len > offset1)
104
				continue;
105
			offset = vga->offset;
106
			offset1 = offset+len;
107
		}
108
 
109
		for(; offset+len<=offset1; offset++) {
110
			if(vga->bios)
111
				bios = vga->bios;
112
			else
113
				bios = readbios(len, offset);
114
			if(strncmp(bios, string, len) == 0){
115
				if(vga->bios == 0){
116
					vga->bios = alloc(len+1);
117
					strncpy(vga->bios, bios, len);
118
				}
119
				addattr(&vga->attr, t);
120
				return 1;
121
			}
122
		}
123
	}
124
	return 0;
125
}
126
 
127
int
128
dbpci(Vga *vga, Ndbtuple *tuple)
129
{
130
	int did, vid;
131
	Ndbtuple *t, *td;
132
	Pcidev *pci;
133
 
134
	for(t = tuple->entry; t; t = t->entry){
135
		if(strcmp(t->attr, "vid") != 0 || (vid=atoi(t->val)) == 0)
136
			continue;
137
		for(td = t->line; td != t; td = td->line){
138
			if(strcmp(td->attr, "did") != 0)
139
				continue;
140
			if(strcmp(td->val, "*") == 0)
141
				did = 0;
142
			else if((did=atoi(td->val)) == 0)
143
				continue;
144
			for(pci=nil; pci=pcimatch(pci, vid, did);)
145
				if((pci->ccru>>8) == 3)
146
					break;
147
			if(pci == nil)
148
				continue;
149
			vga->pci = pci;
150
			addattr(&vga->attr, t);
151
			addattr(&vga->attr, td);
152
			return 1;
153
		}
154
	}
155
	return 0;
156
}
157
 
158
static void
159
save(Vga *vga, Ndbtuple *tuple)
160
{
161
	Ctlr *c;
162
	Ndbtuple *t;
163
 
164
	for(t = tuple->entry; t; t = t->entry){
165
		if(strcmp(t->attr, "ctlr") == 0){
166
			vga->ctlr = addctlr(vga, t->val);
167
			if(strcmp(t->val, "vesa") == 0)
168
				vga->vesa = vga->ctlr;
169
		}else if(strcmp(t->attr, "ramdac") == 0)
170
			vga->ramdac = addctlr(vga, t->val);
171
		else if(strcmp(t->attr, "clock") == 0)
172
			vga->clock = addctlr(vga, t->val);
173
		else if(strcmp(t->attr, "hwgc") == 0)
174
			vga->hwgc = addctlr(vga, t->val);
175
		else if(strcmp(t->attr, "link") == 0){
176
			c = addctlr(vga, t->val);
177
			if(strcmp(t->val, "vesa") == 0)
178
				vga->vesa = c;
179
		}else if(strcmp(t->attr, "linear") == 0)
180
			vga->linear = strtol(t->val, 0, 0);
181
		else if(strcmp(t->attr, "membw") == 0)
182
			vga->membw = strtol(t->val, 0, 0)*1000000;
183
		else if(strcmp(t->attr, "vid")==0 || strcmp(t->attr, "did")==0)
184
			{}
185
		else if(strtol(t->attr, 0, 0) == 0)
186
			addattr(&vga->attr, t);
187
	}
188
}
189
 
190
int
191
dbctlr(char* name, Vga* vga)
192
{
193
	Ndb *db;
194
	Ndbs s;
195
	Ndbtuple *tuple;
196
	Ndbtuple *pcituple;
197
 
198
	db = dbopen(name);
199
 
200
	/*
201
	 * Search vgadb for a matching BIOS string or PCI id.
202
	 * If we have both, the BIOS string wins.
203
	 */
204
	pcituple = nil;
205
	for(tuple = ndbsearch(db, &s, "ctlr", ""); tuple; tuple = ndbsnext(&s, "ctlr", "")){
206
		if(!pcituple && dbpci(vga, tuple))
207
			pcituple = tuple;
208
		if(dbbios(vga, tuple)){
209
			save(vga, tuple);
210
			if(pcituple && pcituple != tuple)
211
				ndbfree(pcituple);
212
			ndbfree(tuple);
213
			ndbclose(db);
214
			return 1;
215
		}
216
		if(tuple != pcituple)
217
			ndbfree(tuple);
218
	}
219
 
220
	if(pcituple){
221
		save(vga, pcituple);
222
		ndbfree(pcituple);
223
	}
224
	ndbclose(db);
225
	if(pcituple)
226
		return 1;
227
	return 0;
228
}
229
 
230
static int
231
dbmonitor(Ndb* db, Mode* mode, char* type, char* size)
232
{
233
	Ndbs s;
234
	Ndbtuple *t, *tuple;
235
	char *p, attr[Namelen+1], val[Namelen+1], buf[2*Namelen+1];
236
	int clock, x, i;
237
 
238
	/*
239
	 * Clock rate hack.
240
	 * If the size is 'XxYxZ@NMHz' then override the database entry's
241
	 * 'clock=' with 'N*1000000'.
242
	 */
243
	clock = 0;
244
	strcpy(buf, size);
245
	if(p = strchr(buf, '@')){
246
		*p++ = 0;
247
		if((clock = strtol(p, &p, 0)) && strcmp(p, "MHz") == 0)
248
			clock *= 1000000;
249
	}
250
 
251
	memset(mode, 0, sizeof(Mode));
252
 
253
	if((p = strchr(buf, 'x')) && (p = strchr(p+1, 'x'))){
254
		*p++ = 0;
255
		mode->z = atoi(p);
256
	}
257
 
258
	strcpy(attr, type);
259
	strcpy(val, buf);
260
 
261
	if(p = ndbgetvalue(db, &s, attr, "", "videobw", nil)){
262
		mode->videobw = atol(p)*1000000UL;
263
		free(p);
264
	}
265
 
266
	if(mode->x == 0 && ((mode->x = strtol(val, &p, 0)) == 0 || *p++ != 'x'))
267
		return 0;
268
	if(mode->y == 0 && (mode->y = strtol(p, &p, 0)) == 0)
269
		return 0;
270
	i = 0;
271
buggery:
272
	if((tuple = ndbsearch(db, &s, attr, val)) == 0)
273
		return 0;
274
 
275
	for(t = tuple->entry; t; t = t->entry){
276
		if(strcmp(t->attr, "clock") == 0 && mode->frequency == 0)
277
			mode->frequency = strtod(t->val, 0)*1000000;
278
		else if(strcmp(t->attr, "defaultclock") == 0 && mode->deffrequency == 0)
279
			mode->deffrequency = strtod(t->val, 0)*1000000;
280
		else if(strcmp(t->attr, "ht") == 0 && mode->ht == 0)
281
			mode->ht = strtol(t->val, 0, 0);
282
		else if(strcmp(t->attr, "shb") == 0 && mode->shb == 0)
283
			mode->shb = strtol(t->val, 0, 0);
284
		else if(strcmp(t->attr, "ehb") == 0 && mode->ehb == 0)
285
			mode->ehb = strtol(t->val, 0, 0);
286
		else if(strcmp(t->attr, "shs") == 0 && mode->shs == 0)
287
			mode->shs = strtol(t->val, 0, 0);
288
		else if(strcmp(t->attr, "ehs") == 0 && mode->ehs == 0)
289
			mode->ehs = strtol(t->val, 0, 0);
290
		else if(strcmp(t->attr, "vt") == 0 && mode->vt == 0)
291
			mode->vt = strtol(t->val, 0, 0);
292
		else if(strcmp(t->attr, "vrs") == 0 && mode->vrs == 0)
293
			mode->vrs = strtol(t->val, 0, 0);
294
		else if(strcmp(t->attr, "vre") == 0 && mode->vre == 0)
295
			mode->vre = strtol(t->val, 0, 0);
296
		else if(strcmp(t->attr, "hsync") == 0)
297
			mode->hsync = *t->val;
298
		else if(strcmp(t->attr, "vsync") == 0)
299
			mode->vsync = *t->val;
300
		else if(strcmp(t->attr, "interlace") == 0)
301
			mode->interlace = *t->val;
302
		else if(strcmp(t->attr, "include") == 0 /*&& strcmp(t->val, val) != 0*/){
303
			strcpy(attr, t->attr);
304
			strcpy(val, t->val);
305
			ndbfree(tuple);
306
			if(i++ > 5)
307
				error("dbmonitor: implausible include depth at %s=%s\n", attr, val);
308
			goto buggery;
309
		}
310
		else if(strcmp(t->attr, "include") == 0){
311
			print("warning: bailed out of infinite loop in attr %s=%s\n", attr, val);
312
		}
313
		else
314
			addattr(&mode->attr, t);
315
	}
316
	ndbfree(tuple);
317
 
318
	if((x = strtol(size, &p, 0)) == 0 || x != mode->x || *p++ != 'x')
319
		return 0;
320
	if((x = strtol(p, &p, 0)) == 0 || x != mode->y || *p++ != 'x')
321
		return 0;
322
	if((x = strtol(p, &p, 0)) == 0 || x != mode->z)
323
		return 0;
324
 
325
	if(clock)
326
		mode->frequency = clock;
327
 
328
	return 1;
329
}
330
 
331
Mode*
332
dbmode(char* name, char* type, char* size)
333
{
334
	Ndb *db;
335
	Ndbs s;
336
	Ndbtuple *t, *tuple;
337
	Mode *mode;
338
	char attr[Namelen+1];
339
	ulong videobw;
340
 
341
	db = dbopen(name);
342
	mode = alloc(sizeof(Mode));
343
	strcpy(attr, type);
344
 
345
	videobw = 0;
346
	/*
347
	 * Look for the attr=size entry.
348
	 */
349
	if(dbmonitor(db, mode, attr, size)){
350
		strcpy(mode->type, type);
351
		strcpy(mode->size, size);
352
		ndbclose(db);
353
		return mode;
354
	}
355
 
356
	if(mode->videobw && videobw == 0)	/* we at least found that; save it away */
357
		videobw = mode->videobw;
358
 
359
	/*
360
	 * Not found. Look for an attr="" entry and then
361
	 * for an alias=attr within.
362
	 */
363
buggery:
364
	for(tuple = ndbsearch(db, &s, attr, ""); tuple; tuple = ndbsnext(&s, attr, "")){
365
		for(t = tuple->entry; t; t = t->entry){
366
			if(strcmp(t->attr, "alias"))
367
				continue;
368
			strcpy(attr, t->val);
369
			if(dbmonitor(db, mode, attr, size)){
370
				strcpy(mode->type, type);
371
				strcpy(mode->size, size);
372
				ndbfree(tuple);
373
				ndbclose(db);
374
				if(videobw)
375
					mode->videobw = videobw;
376
				return mode;
377
			}
378
 
379
			/*
380
			 * Found an alias but no match for size,
381
			 * restart looking for attr="" with the
382
			 * new attr.
383
			 */
384
			ndbfree(tuple);
385
			goto buggery;
386
		}
387
		ndbfree(tuple);
388
	}
389
 
390
	free(mode);
391
	ndbclose(db);
392
	return 0;
393
}
394
 
395
void
396
dbdumpmode(Mode* mode)
397
{
398
	Attr *attr;
399
 
400
	Bprint(&stdout, "dbdumpmode\n");
401
 
402
	Bprint(&stdout, "type=%s, size=%s\n", mode->type, mode->size);
403
	Bprint(&stdout, "frequency=%d\n", mode->frequency);
404
	Bprint(&stdout, "x=%d (0x%X), y=%d (0x%X), z=%d (0x%X)\n",
405
		mode->x, mode->x, mode->y,  mode->y, mode->z, mode->z);
406
	Bprint(&stdout, "ht=%d (0x%X), shb=%d (0x%X), ehb=%d (0x%X)\n",
407
		mode->ht, mode->ht, mode->shb, mode->shb, mode->ehb, mode->ehb);
408
	Bprint(&stdout, "shs=%d (0x%X), ehs=%d (0x%X)\n",
409
		mode->shs, mode->shs, mode->ehs, mode->ehs);
410
	Bprint(&stdout, "vt=%d (0x%X), vrs=%d (0x%X), vre=%d (0x%X)\n",
411
		mode->vt, mode->vt, mode->vrs, mode->vrs, mode->vre, mode->vre);
412
	Bprint(&stdout, "hsync=%d, vsync=%d, interlace=%d\n",
413
		mode->hsync, mode->vsync, mode->interlace);
414
 
415
	for(attr = mode->attr; attr; attr = attr->next)
416
		Bprint(&stdout, "mode->attr: %s=%s\n", attr->attr, attr->val);
417
}