]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/hwinfo/src/hd/hddb.c
Signierten GPG-Schluessel importiert.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / hd / hddb.c
CommitLineData
93afd047
MT
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <sys/utsname.h>
6
7#include "hd.h"
8#include "hd_int.h"
9#include "hddb.h"
10#include "isdn.h"
11#include "hddb_int.h"
12
13extern hddb2_data_t hddb_internal;
14
15/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
16// #define HDDB_TRACE
17// #define HDDB_TEST
18// #define HDDB_EXTERNAL_ONLY
19
20static char *hid_tag_names[] = { "", "pci ", "eisa ", "usb ", "special ", "pcmcia " };
21// just experimenting...
22static char *hid_tag_names2[] = { "", "pci ", "eisa ", "usb ", "int ", "pcmcia " };
23
24typedef enum {
25 pref_empty, pref_new, pref_and, pref_or, pref_add
26} prefix_t;
27
28typedef struct line_s {
29 prefix_t prefix;
30 hddb_entry_t key;
31 char *value;
32} line_t;
33
34typedef struct {
35 int len;
36 unsigned val[32]; /* arbitrary (approx. max. number of modules/xf86 config lines) */
37} tmp_entry_t;
38
39/* except for driver, all strings are static and _must not_ be freed */
40typedef struct {
41 hddb_entry_mask_t key;
42 hddb_entry_mask_t value;
43 hddb_entry_mask_t value_mask[he_nomask];
44 hd_id_t bus;
45 hd_id_t base_class;
46 hd_id_t sub_class;
47 hd_id_t prog_if;
48 hd_id_t vendor;
49 hd_id_t device;
50 hd_id_t sub_vendor;
51 hd_id_t sub_device;
52 hd_id_t revision;
53 hd_id_t cu_model;
54 char *serial;
55 str_list_t *driver;
56 char *requires;
57} hddb_search_t;
58
59
60/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
61static void hddb_init_pci(hd_data_t *hd_data);
62static hddb_pci_t *parse_pcimap(str_list_t *file);
63static driver_info_t *hd_pcidb(hd_data_t *hd_data, hddb_pci_t *pci_db, hd_t *hd, driver_info_t *drv_info);
64static void hddb_init_external(hd_data_t *hd_data);
65
66static line_t *parse_line(char *str);
67static unsigned store_string(hddb2_data_t *x, char *str);
68static unsigned store_list(hddb2_data_t *x, hddb_list_t *list);
69static unsigned store_value(hddb2_data_t *x, unsigned val);
70static unsigned store_entry(hddb2_data_t *x, tmp_entry_t *te);
71static void clear_entry(tmp_entry_t *te);
72static void add_value(tmp_entry_t *te, hddb_entry_t idx, unsigned val);
73static hddb_entry_mask_t add_entry(hddb2_data_t *hddb2, tmp_entry_t *te, hddb_entry_t idx, char *str);
74static int compare_ids(hddb2_data_t *hddb, hddb_search_t *hs, hddb_entry_mask_t mask, unsigned key);
75static void complete_ids(hddb2_data_t *hddb, hddb_search_t *hs, hddb_entry_mask_t key_mask, hddb_entry_mask_t mask, unsigned val_idx);
76static int hddb_search(hd_data_t *hd_data, hddb_search_t *hs, int max_recursions);
77#ifdef HDDB_TEST
78static void test_db(hd_data_t *hd_data);
79#endif
80static driver_info_t *hddb_to_device_driver(hd_data_t *hd_data, hddb_search_t *hs);
81static driver_info_t *kbd_driver(hd_data_t *hd_data, hd_t *hd);
82static driver_info_t *monitor_driver(hd_data_t *hd_data, hd_t *hd);
83
84#if WITH_ISDN
85/* static int chk_free_biosmem(hd_data_t *hd_data, unsigned addr, unsigned len); */
86/* static isdn_parm_t *new_isdn_parm(isdn_parm_t **ip); */
87static driver_info_t *isdn_driver(hd_data_t *hd_data, hd_t *hd, cdb_isdn_card *cic);
88static driver_info_t *dsl_driver(hd_data_t *hd_data, hd_t *hd, cdb_isdn_card *cic);
89#endif
90
91static hd_res_t *get_res(hd_t *h, enum resource_types t, unsigned index);
92static driver_info_t *reorder_x11(driver_info_t *di0, char *info);
93static void expand_driver_info(hd_data_t *hd_data, hd_t *hd);
94static char *module_cmd(hd_t *hd, char *cmd);
95
96
97/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
98void hddb_init_pci(hd_data_t *hd_data)
99{
100 str_list_t *sl = NULL;
101 char *s = NULL, *r;
102 struct utsname ubuf;
103
104 if(!hd_data->hddb_pci) {
105 if(!uname(&ubuf)) {
106 r = getenv("LIBHD_KERNELVERSION");
107 if(!r || !*r) r = ubuf.release;
108 str_printf(&s, 0, "/lib/modules/%s/modules.pcimap", r);
109 sl = read_file(s, 0, 0);
110 s = free_mem(s);
111 }
112
113 hd_data->hddb_pci = parse_pcimap(sl);
114
115 sl = free_str_list(sl);
116 }
117
118 if(!hd_data->hddb_pci_hm) {
119 sl = read_file("/etc/hotplug/pci.handmap", 0, 0);
120 hd_data->hddb_pci_hm = parse_pcimap(sl);
121 sl = free_str_list(sl);
122 }
123}
124
125
126hddb_pci_t *parse_pcimap(str_list_t *file)
127{
128 str_list_t *sl;
129 unsigned len;
130 hddb_pci_t *pci, *p;
131 char buf[64];
132 unsigned u0, u1, u2, u3, u4, u5;
133
134 for(len = 1, sl = file; sl; sl = sl->next) len++;
135
136 pci = new_mem(len * sizeof *pci);
137
138 for(p = pci, sl = file; sl; sl = sl->next) {
139 if(sscanf(sl->str, "%63s %x %x %x %x %x %x", buf, &u0, &u1, &u2, &u3, &u4, &u5) == 7) {
140 p->module = new_str(buf);
141 p->vendor = u0;
142 p->device = u1;
143 p->subvendor = u2;
144 p->subdevice = u3;
145 p->pciclass = u4;
146 p->classmask = u5;
147
148 p++;
149 }
150 }
151
152#if 0
153 fprintf(stderr, "--- pcimap ---\n");
154 for(p = pci; p->module; p++) {
155 fprintf(stderr, "%s, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
156 p->module, p->vendor, p->device, p->subvendor, p->subdevice,
157 p->pciclass, p->classmask
158 );
159 }
160#endif
161
162 return pci;
163}
164
165
166driver_info_t *hd_pcidb(hd_data_t *hd_data, hddb_pci_t *pci_db, hd_t *hd, driver_info_t *drv_info)
167{
168 unsigned vendor, device, subvendor, subdevice, pciclass;
169 driver_info_t **di = NULL, *di2;
170 pci_t *pci;
171 char *mod_list[16 /* arbitrary */];
172 int mod_prio[sizeof mod_list / sizeof *mod_list];
173 int i, prio, mod_list_len;
174
175 if(!pci_db) return drv_info;
176
177 if(ID_TAG(hd->vendor.id) != TAG_PCI) return drv_info;
178
179 /* don't add module info if driver info of some other type exists */
180 for(di = &drv_info; *di; di = &(*di)->next) {
181 if((*di)->any.type != di_module) return drv_info;
182 }
183
184 vendor = ID_VALUE(hd->vendor.id);
185 device = ID_VALUE(hd->device.id);
186 subvendor = ID_VALUE(hd->sub_vendor.id);
187 subdevice = ID_VALUE(hd->sub_device.id);
188 pciclass = (hd->base_class.id << 16) + ((hd->sub_class.id & 0xff) << 8) + (hd->prog_if.id & 0xff);
189
190 if(
191 hd->detail &&
192 hd->detail->type == hd_detail_pci &&
193 (pci = hd->detail->pci.data)
194 ) {
195 pciclass = (pci->base_class << 16) + ((pci->sub_class & 0xff) << 8) + (pci->prog_if & 0xff);
196 }
197
198 for(mod_list_len = 0; pci_db->module; pci_db++) {
199 if(
200 (pci_db->vendor == 0xffffffff || pci_db->vendor == vendor) &&
201 (pci_db->device == 0xffffffff || pci_db->device == device) &&
202 (pci_db->subvendor == 0xffffffff || pci_db->subvendor == subvendor) &&
203 (pci_db->subdevice == 0xffffffff || pci_db->subdevice == subdevice) &&
204 !((pci_db->pciclass ^ pciclass) & pci_db->classmask)
205 ) {
206 for(di2 = drv_info; di2; di2 = di2->next) {
207 if(
208 di2->any.type == di_module &&
209 di2->any.hddb0 &&
210 di2->any.hddb0->str &&
211 !strcmp(di2->any.hddb0->str, pci_db->module)
212 ) break;
213 }
214
215 if(di2) continue;
216
217 prio = 0;
218 if(pci_db->vendor == vendor) prio = 1;
219 if(pci_db->device == device) prio = 2;
220 if(pci_db->subvendor == subvendor) prio = 3;
221 if(pci_db->subdevice == subdevice) prio = 4;
222
223 mod_prio[mod_list_len] = prio;
224 mod_list[mod_list_len++] = pci_db->module;
225
226 if(mod_list_len >= sizeof mod_list / sizeof *mod_list) break;
227 }
228 }
229
230 for(prio = 4; prio >= 0; prio--) {
231 for(i = 0; i < mod_list_len; i++) {
232 if(mod_prio[i] == prio) {
233 *di = new_mem(sizeof **di);
234 (*di)->any.type = di_module;
235 (*di)->module.modprobe = 1;
236 add_str_list(&(*di)->any.hddb0, mod_list[i]);
237 di = &(*di)->next;
238 }
239 }
240 }
241
242 return drv_info;
243}
244
245
246/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
247void hddb_init(hd_data_t *hd_data)
248{
249 hddb_init_pci(hd_data);
250 hddb_init_external(hd_data);
251
252#ifndef HDDB_EXTERNAL_ONLY
253 hd_data->hddb2[1] = &hddb_internal;
254#endif
255
256#ifdef HDDB_TEST
257 test_db(hd_data);
258#endif
259}
260
261
262void hddb_init_external(hd_data_t *hd_data)
263{
264 str_list_t *sl, *sl0;
265 line_t *l;
266 unsigned l_start, l_end /* end points _past_ last element */;
267 unsigned u, ent, l_nr = 1;
268 tmp_entry_t tmp_entry[he_nomask /* _must_ be he_nomask! */];
269 hddb_entry_mask_t entry_mask = 0;
270 int state;
271 hddb_list_t dbl = {};
272 hddb2_data_t *hddb2;
273
274 if(hd_data->hddb2[0]) return;
275
276 hddb2 = hd_data->hddb2[0] = new_mem(sizeof *hd_data->hddb2[0]);
277
278 sl0 = read_file(ID_LIST, 0, 0);
279
280 l_start = l_end = 0;
281 state = 0;
282
283 for(sl = sl0; sl; sl = sl->next, l_nr++) {
284 l = parse_line(sl->str);
285 if(!l) {
286 ADD2LOG("hd.ids line %d: invalid line\n", l_nr);
287 state = 4;
288 break;
289 };
290 if(l->prefix == pref_empty) continue;
291 switch(l->prefix) {
292 case pref_new:
293 if((state == 2 && !entry_mask) || state == 1) {
294 ADD2LOG("hd.ids line %d: new item not allowed\n", l_nr);
295 state = 4;
296 break;
297 }
298 if(state == 2 && entry_mask) {
299 ent = store_entry(hddb2, tmp_entry);
300 if(ent == -1u) {
301 ADD2LOG("hd.ids line %d: internal hddb oops 1\n", l_nr);
302 state = 4;
303 break;
304 }
305 if(l_end && l_end > l_start) {
306 for(u = l_start; u < l_end; u++) {
307 hddb2->list[u].value_mask = entry_mask;
308 hddb2->list[u].value = ent;
309 }
310 }
311 }
312 entry_mask = 0;
313 clear_entry(tmp_entry);
314 state = 1;
315 l_start = store_list(hddb2, &dbl);
316 l_end = l_start + 1;
317 break;
318
319 case pref_and:
320 if(state != 1) {
321 ADD2LOG("hd.ids line %d: must start item first\n", l_nr);
322 state = 4;
323 break;
324 }
325 break;
326
327 case pref_or:
328 if(state != 1 || !entry_mask || l_end <= l_start || l_end < 1) {
329 ADD2LOG("hd.ids line %d: must start item first\n", l_nr);
330 state = 4;
331 break;
332 }
333 ent = store_entry(hddb2, tmp_entry);
334 if(ent == -1u) {
335 ADD2LOG("hd.ids line %d: internal hddb oops 2\n", l_nr);
336 state = 4;
337 break;
338 }
339 hddb2->list[l_end - 1].key_mask = entry_mask;
340 hddb2->list[l_end - 1].key = ent;
341 entry_mask = 0;
342 clear_entry(tmp_entry);
343 u = store_list(hddb2, &dbl);
344 if(u != l_end) {
345 ADD2LOG("hd.ids line %d: internal hddb oops 2\n", l_nr);
346 state = 4;
347 break;
348 }
349 l_end++;
350 break;
351
352 case pref_add:
353 if(state == 1 && !entry_mask) {
354 ADD2LOG("hd.ids line %d: driver info not allowed\n", l_nr);
355 state = 4;
356 break;
357 }
358 if(state == 1 && l_end > l_start) {
359 ent = store_entry(hddb2, tmp_entry);
360 if(ent == -1u) {
361 ADD2LOG("hd.ids line %d: internal hddb oops 3\n", l_nr);
362 state = 4;
363 break;
364 }
365 hddb2->list[l_end - 1].key_mask = entry_mask;
366 hddb2->list[l_end - 1].key = ent;
367 entry_mask = 0;
368 clear_entry(tmp_entry);
369 state = 2;
370 }
371 if(state != 2 || l_end == 0) {
372 ADD2LOG("hd.ids line %d: driver info not allowed\n", l_nr);
373 state = 4;
374 break;
375 }
376 break;
377
378 default:
379 state = 4;
380 }
381
382 if(state != 4) {
383 u = add_entry(hddb2, tmp_entry, l->key, l->value);
384 if(u) {
385 entry_mask |= u;
386 }
387 else {
388 ADD2LOG("hd.ids line %d: invalid info\n", l_nr);
389 state = 4;
390 }
391 }
392
393 if(state == 4) break; /* error */
394 }
395
396 /* finalize last item */
397 if(state == 2 && entry_mask) {
398 ent = store_entry(hddb2, tmp_entry);
399 if(ent == -1u) {
400 ADD2LOG("hd.ids line %d: internal hddb oops 4\n", l_nr);
401 state = 4;
402 }
403 else if(l_end && l_end > l_start) {
404 for(u = l_start; u < l_end; u++) {
405 hddb2->list[u].value_mask = entry_mask;
406 hddb2->list[u].value = ent;
407 }
408 }
409 }
410
411 sl0 = free_str_list(sl0);
412
413 if(state == 4) {
414 /* there was an error */
415
416 free_mem(hddb2->list);
417 free_mem(hddb2->ids);
418 free_mem(hddb2->strings);
419 hd_data->hddb2[0] = free_mem(hd_data->hddb2[0]);
420 }
421}
422
423
424line_t *parse_line(char *str)
425{
426 static line_t l;
427 char *s;
428 int i;
429
430 /* drop leading spaces */
431 while(isspace(*str)) str++;
432
433 /* skip emtpy lines and comments */
434 if(!*str || *str == ';' || *str == '#') {
435 l.prefix = pref_empty;
436 return &l;
437 }
438
439 l.prefix = pref_new;
440
441 switch(*str) {
442 case '&':
443 l.prefix = pref_and;
444 str++;
445 break;
446
447 case '|':
448 l.prefix = pref_or;
449 str++;
450 break;
451
452 case '+':
453 l.prefix = pref_add;
454 str++;
455 break;
456 }
457
458 /* skip spaces */
459 while(isspace(*str)) str++;
460
461 s = str;
462 while(*str && !isspace(*str)) str++;
463 if(*str) *str++ = 0;
464 while(isspace(*str)) str++;
465
466 for(i = 0; (unsigned) i < sizeof hddb_entry_strings / sizeof *hddb_entry_strings; i++) {
467 if(!strcmp(s, hddb_entry_strings[i])) {
468 l.key = i;
469 break;
470 }
471 }
472
473 if((unsigned) i >= sizeof hddb_entry_strings / sizeof *hddb_entry_strings) return NULL;
474
475 l.value = str;
476
477 /* drop trailing white space */
478 i = strlen(str);
479 while(i > 0) {
480 if(isspace(str[i - 1]))
481 str[--i] = 0;
482 else
483 break;
484 }
485
486 /* special case: drop leading and final double quotes, if any */
487 i = strlen(l.value);
488 if(i >= 2 && l.value[0] == '"' && l.value[i - 1] == '"') {
489 l.value[i - 1] = 0;
490 l.value++;
491 }
492
493 // fprintf(stderr, "pre = %d, key = %d, val = \"%s\"\n", l.prefix, l.key, l.value);
494
495 return &l;
496}
497
498
499unsigned store_string(hddb2_data_t *x, char *str)
500{
501 unsigned l = strlen(str), u;
502
503 if(x->strings_len + l >= x->strings_max) {
504 x->strings_max += l + 0x1000; /* >4k steps */
505 x->strings = resize_mem(x->strings, x->strings_max * sizeof *x->strings);
506 }
507
508 /* make sure the 1st byte is 0 */
509 if(x->strings_len == 0) {
510 *x->strings = 0; /* resize_mem does _not_ clear memory */
511 x->strings_len = 1;
512 }
513
514 if(l == 0) return 0; /* 1st byte is always 0 */
515
516 strcpy(x->strings + (u = x->strings_len), str);
517 x->strings_len += l + 1;
518
519 return u;
520}
521
522
523unsigned store_list(hddb2_data_t *x, hddb_list_t *list)
524{
525 if(x->list_len == x->list_max) {
526 x->list_max += 0x100; /* 4k steps */
527 x->list = resize_mem(x->list, x->list_max * sizeof *x->list);
528 }
529
530 x->list[x->list_len++] = *list;
531
532 return x->list_len - 1;
533}
534
535
536unsigned store_value(hddb2_data_t *x, unsigned val)
537{
538 if(x->ids_len == x->ids_max) {
539 x->ids_max += 0x400; /* 4k steps */
540 x->ids = resize_mem(x->ids, x->ids_max * sizeof *x->ids);
541 }
542
543 x->ids[x->ids_len++] = val;
544
545 return x->ids_len - 1;
546}
547
548
549/* returns index in hddb2->ids */
550unsigned store_entry(hddb2_data_t *x, tmp_entry_t *te)
551{
552 int i, j;
553 unsigned ent = -1, u, v;
554
555 for(i = 0; i < he_nomask; i++) {
556 if(te[i].len) {
557 for(j = 0; j < te[i].len; j++) {
558 v = te[i].val[j] | (1 << 31);
559 if(j == te[i].len - 1) v &= ~(1 << 31);
560 u = store_value(x, v);
561 if(ent == -1u) ent = u;
562 }
563 }
564 }
565
566 return ent;
567}
568
569void clear_entry(tmp_entry_t *te)
570{
571 memset(te, 0, he_nomask * sizeof *te);
572}
573
574void add_value(tmp_entry_t *te, hddb_entry_t idx, unsigned val)
575{
576 if(idx >= he_nomask) return;
577 te += idx;
578
579 if((unsigned) te->len >= sizeof te->val / sizeof *te->val) return;
580
581 te->val[te->len++] = val;
582}
583
584int parse_id(char *str, unsigned *id, unsigned *range, unsigned *mask)
585{
586 static unsigned id0, val;
587 unsigned tag = 0;
588 char c = 0, *s, *t = NULL;
589
590 *id = *range = *mask = 0;
591
592 if(!str || !*str) return 0;
593
594 for(s = str; *str && !isspace(*str); str++);
595 if(*str) {
596 c = *(t = str); /* remember for later */
597 *str++ = 0;
598 }
599 while(isspace(*str)) str++;
600
601 if(*s) {
602 if(!strcmp(s, "pci")) tag = TAG_PCI;
603 else if(!strcmp(s, "usb")) tag = TAG_USB;
604 else if(!strcmp(s, "special")) tag = TAG_SPECIAL;
605 else if(!strcmp(s, "eisa")) tag = TAG_EISA;
606 else if(!strcmp(s, "isapnp")) tag = TAG_EISA;
607 else if(!strcmp(s, "pcmcia")) tag = TAG_PCMCIA;
608 else {
609 str = s;
610 if(t) *t = c; /* restore */
611 }
612 }
613
614 id0 = strtoul(str, &s, 0);
615
616 if(s == str) {
617 id0 = name2eisa_id(str);
618 if(!id0) return 0;
619 s = str + 3;
620 id0 = ID_VALUE(id0);
621 if(!tag) tag = TAG_EISA;
622 }
623
624 while(isspace(*s)) s++;
625 if(*s && *s != '&' && *s != '+') return 0;
626
627 *id = MAKE_ID(tag, id0);
628
629 if(!*s) return 1;
630
631 c = *s++;
632
633 while(isspace(*s)) s++;
634
635 val = strtoul(s, &str, 0);
636
637 if(s == str) return 0;
638
639 while(isspace(*str)) str++;
640
641 if(*str) return 0;
642
643 if(c == '+') *range = val; else *mask = val;
644
645 return c == '+' ? 2 : 3;
646}
647
648
649hddb_entry_mask_t add_entry(hddb2_data_t *hddb2, tmp_entry_t *te, hddb_entry_t idx, char *str)
650{
651 hddb_entry_mask_t mask = 0;
652 int i;
653 unsigned u, u0, u1, u2;
654 char *s, c;
655
656 for(i = 0; (unsigned) i < sizeof hddb_is_numeric / sizeof *hddb_is_numeric; i++) {
657 if(idx == hddb_is_numeric[i]) break;
658 }
659
660 if((unsigned) i < sizeof hddb_is_numeric / sizeof *hddb_is_numeric) {
661 /* numeric id */
662 mask |= 1 << idx;
663
664 i = parse_id(str, &u0, &u1, &u2);
665
666 switch(i) {
667 case 1:
668 add_value(te, idx, MAKE_DATA(FLAG_ID, u0));
669 break;
670
671 case 2:
672 add_value(te, idx, MAKE_DATA(FLAG_RANGE, u1));
673 add_value(te, idx, MAKE_DATA(FLAG_ID, u0));
674 break;
675
676 case 3:
677 add_value(te, idx, MAKE_DATA(FLAG_MASK, u2));
678 add_value(te, idx, MAKE_DATA(FLAG_ID, u0));
679 break;
680
681 default:
682 return 0;
683 }
684 }
685 else {
686 if(idx < he_nomask) {
687 /* strings */
688
689 mask |= 1 << idx;
690 u = store_string(hddb2, str);
691 // fprintf(stderr, ">>> %s\n", str);
692 add_value(te, idx, MAKE_DATA(FLAG_STRING, u));
693 }
694 else {
695 /* special */
696
697 if(idx == he_class_id) {
698 i = parse_id(str, &u0, &u1, &u2);
699 if(i != 1) return 0;
700 u = ID_VALUE(u0) >> 8;
701 add_value(te, he_baseclass_id, MAKE_DATA(FLAG_ID, u));
702 u = u0 & 0xff;
703 add_value(te, he_subclass_id, MAKE_DATA(FLAG_ID, u));
704 /* add_value(te, he_progif_id, MAKE_DATA(FLAG_ID, 0)); */
705 mask |= (1 << he_baseclass_id) + (1 << he_subclass_id) /* + (1 << he_progif_id) */;
706 }
707 else {
708 switch(idx) {
709 case he_driver_module_insmod:
710 c = 'i';
711 break;
712
713 case he_driver_module_modprobe:
714 c = 'm';
715 break;
716
717 case he_driver_module_config:
718 c = 'M';
719 break;
720
721 case he_driver_xfree:
722 c = 'x';
723 break;
724
725 case he_driver_xfree_config:
726 c = 'X';
727 break;
728
729 case he_driver_mouse:
730 c = 'p';
731 break;
732
733 case he_driver_display:
734 c = 'd';
735 break;
736
737 case he_driver_any:
738 c = 'a';
739 break;
740
741 default:
742 c = 0;
743 break;
744 }
745 if(c) {
746 s = new_mem(strlen(str) + 3);
747 s[0] = c;
748 s[1] = '\t';
749 strcpy(s + 2, str);
750 mask |= add_entry(hddb2, te, he_driver, s);
751 s = free_mem(s);
752 }
753 }
754 }
755 }
756
757 return mask;
758}
759
760
761/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
762void hddb_dump_raw(hddb2_data_t *hddb, FILE *f)
763{
764 int i;
765 unsigned u, fl, v, t, id;
766 char *s;
767
768 if(!hddb) return;
769
770 fprintf(f, "=== strings 0x%05x/0x%05x ===\n", hddb->strings_len, hddb->strings_max);
771
772 for(s = hddb->strings, i = 0, u = 0; u < hddb->strings_len; u++) {
773 if(!hddb->strings[u]) {
774 fprintf(f, "%4d (0x%05x): \"%s\"\n", i, (unsigned) (s - hddb->strings), s);
775 i++;
776 s = hddb->strings + u + 1;
777 }
778 }
779
780 fprintf(f, "\n=== ids 0x%05x/0x%05x ===\n", hddb->ids_len, hddb->ids_max);
781
782 for(u = 0; u < hddb->ids_len; u++) {
783 fprintf(f, "0x%05x: 0x%08x ", u, hddb->ids[u]);
784 if(hddb->ids[u] & (1 << 31)) fprintf(f, " ");
785 fl = DATA_FLAG(hddb->ids[u]) & 0x7;
786 v = DATA_VALUE(hddb->ids[u]);
787 if(fl == FLAG_STRING && v < hddb->strings_len) {
788 fprintf(f, "\"%s\"", hddb->strings + v);
789 }
790 else if(fl == FLAG_MASK) {
791 fprintf(f, "&0x%04x", v);
792 }
793 else if(fl == FLAG_RANGE) {
794 fprintf(f, "+0x%04x", v);
795 }
796 else if(fl == FLAG_ID) {
797 t = ID_TAG(v);
798 id = ID_VALUE(v);
799 fprintf(f, "%s0x%04x", hid_tag_name(t), id);
800 if(t == TAG_EISA) {
801 fprintf(f, " (%s)", eisa_vendor_str(id));
802 }
803 }
804 fprintf(f, "\n");
805 }
806
807 fprintf(f, "\n=== search list 0x%05x/0x%05x ===\n", hddb->list_len, hddb->list_max);
808
809 for(u = 0; u < hddb->list_len; u++) {
810 fprintf(f,
811 "%4d: 0x%08x 0x%08x 0x%05x 0x%05x\n",
812 u, hddb->list[u].key_mask, hddb->list[u].value_mask,
813 hddb->list[u].key, hddb->list[u].value
814 );
815 }
816}
817
818
819/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
820void hddb_dump_ent_name(hddb2_data_t *hddb, FILE *f, char pre, hddb_entry_t ent)
821{
822 int len, tab_ind = 24;
823
824 if(ent >= sizeof hddb_entry_strings / sizeof *hddb_entry_strings) return;
825
826 fprintf(f, "%c%s\t", pre, hddb_entry_strings[ent]);
827
828 len = strlen(hddb_entry_strings[ent]) + 1;
829
830 for(len = (len & ~7) + 8; len < tab_ind; len += 8) {
831 fputc('\t', f);
832 }
833}
834
835
836void hddb_dump_skey(hddb2_data_t *hddb, FILE *f, prefix_t pre, hddb_entry_mask_t key_mask, unsigned key)
837{
838 static char pref_char[5] = { ' ', ' ', '&', '|', '+' };
839 hddb_entry_t ent;
840 unsigned rm_val = 0, r_or_m = 0;
841 unsigned fl, val, *ids, id, tag, u;
842 char *str_val;
843 int i;
844
845 if(pre >= sizeof pref_char) return;
846
847 if(key >= hddb->ids_len) return;
848
849 ids = hddb->ids + key;
850
851 for(ent = 0; ent < he_nomask && key_mask; ent++, key_mask >>= 1) {
852 if(!(key_mask & 1)) continue;
853
854 fl = DATA_FLAG(*ids);
855 val = DATA_VALUE(*ids);
856
857 r_or_m = 0;
858
859 while((fl & FLAG_CONT)) {
860 if(fl == (FLAG_CONT | FLAG_RANGE)) {
861 rm_val = val;
862 r_or_m = 1;
863 }
864 else if(fl == (FLAG_CONT | FLAG_MASK)) {
865 rm_val = val;
866 r_or_m = 2;
867 }
868 else {
869 break;
870 }
871
872 ids++;
873
874 fl = DATA_FLAG(*ids);
875 val = DATA_VALUE(*ids);
876 }
877
878 fl &= ~FLAG_CONT;
879
880 if(ent != he_driver) {
881 hddb_dump_ent_name(hddb, f, pref_char[pre], ent);
882
883 if(fl == FLAG_ID) {
884 tag = ID_TAG(val);
885 id = ID_VALUE(val);
886 if(tag == TAG_EISA && (ent == he_vendor_id || ent == he_subvendor_id)) {
887 fprintf(f, "%s", eisa_vendor_str(id));
888 }
889 else {
890 u = 4;
891 if(ent == he_bus_id || ent == he_subclass_id || ent == he_progif_id) {
892 u = 2;
893 }
894 else if(ent == he_baseclass_id) {
895 u = 3;
896 }
897 fprintf(f, "%s0x%0*x", hid_tag_name(tag), u, id);
898 }
899 if(r_or_m) {
900 fprintf(f, "%c0x%04x", r_or_m == 1 ? '+' : '&', rm_val);
901 }
902 }
903 else if(fl == FLAG_STRING) {
904 if(val < hddb->strings_len) {
905 str_val = hddb->strings + val;
906 fprintf(f, "%s", str_val);
907 }
908 }
909 fputc('\n', f);
910 }
911 else {
912 ids--;
913 do {
914 ids++;
915 fl = DATA_FLAG(*ids) & ~FLAG_CONT;
916 val = DATA_VALUE(*ids);
917 if(fl != FLAG_STRING) break;
918 str_val = NULL;
919 if(val < hddb->strings_len) str_val = hddb->strings + val;
920 if(!str_val) break;
921 if(!*str_val && !str_val[1] == '\t') break;
922
923 switch(*str_val) {
924 case 'x':
925 i = he_driver_xfree;
926 break;
927
928 case 'X':
929 i = he_driver_xfree_config;
930 break;
931
932 case 'i':
933 i = he_driver_module_insmod;
934 break;
935
936 case 'm':
937 i = he_driver_module_modprobe;
938 break;
939
940 case 'M':
941 i = he_driver_module_config;
942 break;
943
944 case 'p':
945 i = he_driver_mouse;
946 break;
947
948 case 'd':
949 i = he_driver_display;
950 break;
951
952 case 'a':
953 i = he_driver_any;
954 break;
955
956 default:
957 i = -1;
958 break;
959 }
960 if(i == -1) break;
961
962 hddb_dump_ent_name(hddb, f, pref_char[pre], i);
963 fprintf(f, "%s\n", str_val + 2);
964 }
965 while((*ids & (1 << 31)));
966 }
967
968 /* at this point 'ids' must be the _current_ entry (_not_ the next) */
969
970 /* skip potential garbage/unhandled entries */
971 while((*ids & (1 << 31))) ids++;
972
973 ids++;
974
975 if(pre != pref_add) pre = pref_and;
976 }
977}
978
979
980void hddb_dump(hddb2_data_t *hddb, FILE *f)
981{
982 unsigned u;
983
984 if(!hddb) return;
985
986 for(u = 0; u < hddb->list_len; u++) {
987 hddb_dump_skey(hddb, f, pref_new, hddb->list[u].key_mask, hddb->list[u].key);
988 hddb_dump_skey(hddb, f, pref_add, hddb->list[u].value_mask, hddb->list[u].value);
989 fputc('\n', f);
990 }
991}
992
993
994/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
995int compare_ids(hddb2_data_t *hddb, hddb_search_t *hs, hddb_entry_mask_t mask, unsigned key)
996{
997 hddb_entry_t ent;
998 unsigned rm_val = 0, r_or_m = 0, res = 0;
999 unsigned fl, val, ok, *ids, id;
1000 char *str, *str_val;
1001
1002 if(key >= hddb->ids_len) return 1;
1003
1004 ids = hddb->ids + key;
1005
1006 for(ent = 0; ent < he_nomask && mask && !res; ent++, mask >>= 1) {
1007 if(!(mask & 1)) continue;
1008
1009 fl = DATA_FLAG(*ids);
1010 val = DATA_VALUE(*ids);
1011
1012 r_or_m = 0;
1013
1014 while((fl & FLAG_CONT)) {
1015 if(fl == (FLAG_CONT | FLAG_RANGE)) {
1016 rm_val = val;
1017 r_or_m = 1;
1018 }
1019 else if(fl == (FLAG_CONT | FLAG_MASK)) {
1020 rm_val = val;
1021 r_or_m = 2;
1022 }
1023 else {
1024 break;
1025 }
1026
1027 ids++;
1028
1029 fl = DATA_FLAG(*ids);
1030 val = DATA_VALUE(*ids);
1031 }
1032
1033 fl &= ~FLAG_CONT;
1034
1035 id = 0;
1036 str = str_val = NULL;
1037 ok = 0;
1038 if(fl == FLAG_ID) {
1039 ok = 1;
1040 switch(ent) {
1041 case he_bus_id:
1042 id = hs->bus.id;
1043 break;
1044
1045 case he_baseclass_id:
1046 id = hs->base_class.id;
1047 break;
1048
1049 case he_subclass_id:
1050 id = hs->sub_class.id;
1051 break;
1052
1053 case he_progif_id:
1054 id = hs->prog_if.id;
1055 break;
1056
1057 case he_vendor_id:
1058 id = hs->vendor.id;
1059 break;
1060
1061 case he_device_id:
1062 id = hs->device.id;
1063 break;
1064
1065 case he_subvendor_id:
1066 id = hs->sub_vendor.id;
1067 break;
1068
1069 case he_subdevice_id:
1070 id = hs->sub_device.id;
1071 break;
1072
1073 case he_rev_id:
1074 id = hs->revision.id;
1075 break;
1076 case he_detail_ccw_data_cu_model:
1077 id = hs->cu_model.id;
1078 break;
1079
1080 default:
1081 ok = 0;
1082 break;
1083 }
1084 }
1085 else if(fl == FLAG_STRING) {
1086 if(val < hddb->strings_len) str_val = hddb->strings + val;
1087 ok = 2;
1088 switch(ent) {
1089 case he_bus_name:
1090 str = hs->bus.name;
1091 break;
1092
1093 case he_baseclass_name:
1094 str = hs->base_class.name;
1095 break;
1096
1097 case he_subclass_name:
1098 str = hs->sub_class.name;
1099 break;
1100
1101 case he_progif_name:
1102 str = hs->prog_if.name;
1103 break;
1104
1105 case he_vendor_name:
1106 str = hs->vendor.name;
1107 break;
1108
1109 case he_device_name:
1110 str = hs->device.name;
1111 break;
1112
1113 case he_subvendor_name:
1114 str = hs->sub_vendor.name;
1115 break;
1116
1117 case he_subdevice_name:
1118 str = hs->sub_device.name;
1119 break;
1120
1121 case he_rev_name:
1122 str = hs->revision.name;
1123 break;
1124
1125 case he_serial:
1126 str = hs->serial;
1127 break;
1128
1129 case he_requires:
1130 str = hs->requires;
1131 break;
1132
1133 default:
1134 ok = 0;
1135 }
1136 }
1137
1138 switch(ok) {
1139 case 1:
1140 switch(r_or_m) {
1141 case 1:
1142 if(id < val || id >= val + rm_val) res = 1;
1143 break;
1144
1145 case 2:
1146 if((id & ~rm_val) != val) res = 1;
1147 break;
1148
1149 default:
1150 if(id != val) res = 1;
1151 }
1152 break;
1153
1154 case 2:
1155 if(str && str_val) {
1156 if(strcmp(str, str_val)) res = 1;
1157 }
1158 else {
1159 res = 1;
1160 }
1161 break;
1162
1163 default:
1164 res = 1;
1165 }
1166
1167#ifdef HDDB_TRACE
1168 switch(ok) {
1169 case 1:
1170 if(r_or_m) {
1171 printf(
1172 "cmp: 0x%05x: (ent = %2d, id = 0x%x, val = 0x%x%c0x%x) = %d\n",
1173 key, ent, id, val, r_or_m == 1 ? '+' : '&', rm_val, res
1174 );
1175 }
1176 else {
1177 printf(
1178 "cmp: 0x%05x: (ent = %2d, id = 0x%x, val = 0x%x) = %d\n",
1179 key, ent, id, val, res
1180 );
1181 }
1182 break;
1183
1184 case 2:
1185 printf(
1186 "cmp: 0x%05x: (ent = %2d, id = \"%s\", val = \"%s\") = %d\n",
1187 key, ent, str, str_val, res
1188 );
1189
1190 break;
1191
1192 default:
1193 printf("cmp: 0x%05x: (ent = %2d, *** unhandled key ***) = %d\n", key, ent, res);
1194 }
1195#endif
1196
1197 /* at this point 'ids' must be the _current_ entry (_not_ the next) */
1198
1199 /* skip potential garbage/unhandled entries */
1200 while((*ids & (1 << 31))) ids++;
1201
1202 ids++;
1203 }
1204
1205 return res;
1206}
1207
1208void complete_ids(
1209 hddb2_data_t *hddb, hddb_search_t *hs,
1210 hddb_entry_mask_t key_mask, hddb_entry_mask_t mask, unsigned val_idx
1211)
1212{
1213 hddb_entry_t ent;
1214 unsigned *ids, *id;
1215 unsigned fl, val, ok;
1216 char **str, *str_val;
1217
1218 if(val_idx >= hddb->ids_len) return;
1219
1220 ids = hddb->ids + val_idx;
1221
1222 for(ent = 0; ent < he_nomask && mask; ent++, mask >>= 1) {
1223 if(!(mask & 1)) continue;
1224
1225 fl = DATA_FLAG(*ids);
1226 val = DATA_VALUE(*ids);
1227
1228 fl &= ~FLAG_CONT;
1229
1230 id = NULL;
1231 str = NULL;
1232 str_val = NULL;
1233 ok = 0;
1234 if(fl == FLAG_ID) {
1235 ok = 1;
1236 switch(ent) {
1237 case he_bus_id:
1238 id = &hs->bus.id;
1239 break;
1240
1241 case he_baseclass_id:
1242 id = &hs->base_class.id;
1243 break;
1244
1245 case he_subclass_id:
1246 id = &hs->sub_class.id;
1247 break;
1248
1249 case he_progif_id:
1250 id = &hs->prog_if.id;
1251 break;
1252
1253 case he_vendor_id:
1254 id = &hs->vendor.id;
1255 break;
1256
1257 case he_device_id:
1258 id = &hs->device.id;
1259 break;
1260
1261 case he_subvendor_id:
1262 id = &hs->sub_vendor.id;
1263 break;
1264
1265 case he_subdevice_id:
1266 id = &hs->sub_device.id;
1267 break;
1268
1269 case he_rev_id:
1270 id = &hs->revision.id;
1271 break;
1272
1273 case he_detail_ccw_data_cu_model:
1274 id = &hs->cu_model.id;
1275 break;
1276
1277 default:
1278 ok = 0;
1279 break;
1280 }
1281 }
1282 else if(fl == FLAG_STRING) {
1283 if(val < hddb->strings_len) str_val = hddb->strings + val;
1284 ok = 2;
1285 switch(ent) {
1286 case he_bus_name:
1287 str = &hs->bus.name;
1288 break;
1289
1290 case he_baseclass_name:
1291 str = &hs->base_class.name;
1292 break;
1293
1294 case he_subclass_name:
1295 str = &hs->sub_class.name;
1296 break;
1297
1298 case he_progif_name:
1299 str = &hs->prog_if.name;
1300 break;
1301
1302 case he_vendor_name:
1303 str = &hs->vendor.name;
1304 break;
1305
1306 case he_device_name:
1307 str = &hs->device.name;
1308 break;
1309
1310 case he_subvendor_name:
1311 str = &hs->sub_vendor.name;
1312 break;
1313
1314 case he_subdevice_name:
1315 str = &hs->sub_device.name;
1316 break;
1317
1318 case he_rev_name:
1319 str = &hs->revision.name;
1320 break;
1321
1322 case he_serial:
1323 str = &hs->serial;
1324 break;
1325
1326 case he_driver:
1327 ok = 3;
1328 break;
1329
1330 case he_requires:
1331 str = &hs->requires;
1332 break;
1333
1334 default:
1335 ok = 0;
1336 }
1337 }
1338
1339 if(ok) {
1340 if(
1341 (hs->value_mask[ent] & key_mask) == hs->value_mask[ent] &&
1342 key_mask != hs->value_mask[ent]
1343 ) {
1344 hs->value_mask[ent] = key_mask;
1345 hs->value |= 1 << ent;
1346 }
1347 else {
1348 /* don't change if already set */
1349 ok = 4;
1350 }
1351
1352#if 0
1353 if((hs->value & (1 << ent))) {
1354 /* don't change if already set */
1355 ok = 4;
1356 }
1357 else if(ent != he_driver) {
1358 hs->value |= 1 << ent;
1359 }
1360#endif
1361 }
1362
1363 switch(ok) {
1364 case 1:
1365 *id = val;
1366#ifdef HDDB_TRACE
1367 printf("add: 0x%05x: (ent = %2d, val = 0x%08x)\n", val_idx, ent, val);
1368#endif
1369 break;
1370
1371 case 2:
1372 *str = str_val;
1373#ifdef HDDB_TRACE
1374 printf("add: 0x%05x: (ent = %2d, val = \"%s\")\n", val_idx, ent, str_val);
1375#endif
1376 break;
1377
1378 case 3:
1379 ids--;
1380 hs->driver = free_str_list(hs->driver);
1381 do {
1382 ids++;
1383 fl = DATA_FLAG(*ids) & ~FLAG_CONT;
1384 val = DATA_VALUE(*ids);
1385 if(fl != FLAG_STRING) break;
1386 str_val = NULL;
1387 if(val < hddb->strings_len) str_val = hddb->strings + val;
1388 if(!str_val) break;
1389#ifdef HDDB_TRACE
1390 printf("add: 0x%05x: (ent = %2d, val = \"%s\")\n", val_idx, ent, str_val);
1391#endif
1392 add_str_list(&hs->driver, str_val);
1393 }
1394 while((*ids & (1 << 31)));
1395 break;
1396
1397 case 4:
1398 break;
1399
1400#ifdef HDDB_TRACE
1401 default:
1402 printf("add: 0x%05x: (ent = %2d, *** unhandled value ***)\n", val_idx, ent);
1403#endif
1404 }
1405
1406 /* at this point 'ids' must be the _current_ entry (_not_ the next) */
1407
1408 /* skip potential garbage/unhandled entries */
1409 while((*ids & (1 << 31))) ids++;
1410
1411 ids++;
1412 }
1413}
1414
1415int hddb_search(hd_data_t *hd_data, hddb_search_t *hs, int max_recursions)
1416{
1417 unsigned u;
1418 int i;
1419 hddb2_data_t *hddb;
1420 int db_idx;
1421 hddb_entry_mask_t all_values = 0;
1422
1423 if(!hs) return 0;
1424
1425 if(!max_recursions) max_recursions = 2;
1426
1427 while(max_recursions--) {
1428 for(db_idx = 0; (unsigned) db_idx < sizeof hd_data->hddb2 / sizeof *hd_data->hddb2; db_idx++) {
1429 if(!(hddb = hd_data->hddb2[db_idx])) continue;
1430
1431 for(u = 0; u < hddb->list_len; u++) {
1432 if(
1433 (hs->key & hddb->list[u].key_mask) == hddb->list[u].key_mask
1434 /* && (hs->value & hddb->list[u].value_mask) != hddb->list[u].value_mask */
1435 ) {
1436 i = compare_ids(hddb, hs, hddb->list[u].key_mask, hddb->list[u].key);
1437 if(!i) {
1438 complete_ids(hddb, hs,
1439 hddb->list[u].key_mask,
1440 hddb->list[u].value_mask, hddb->list[u].value
1441 );
1442 }
1443 }
1444 }
1445 }
1446
1447 all_values |= hs->value;
1448
1449 if(!max_recursions) break;
1450
1451 hs->key |= hs->value;
1452 hs->value = 0;
1453 memset(hs->value_mask, 0, sizeof hs->value_mask);
1454 }
1455
1456 hs->value = all_values;
1457
1458 return 1;
1459}
1460
1461/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1462#ifdef HDDB_TEST
1463void test_db(hd_data_t *hd_data)
1464{
1465 hddb_search_t hs = {};
1466 int i;
1467
1468 hs.bus.id = 4;
1469 hs.key |= (1 << he_bus_id) + (1 << he_serial);
1470
1471 hs.serial = "ser 0123";
1472
1473 i = hddb_search(hd_data, &hs, 0);
1474
1475 printf("%d, >%s<\n", i, hs.bus.name);
1476}
1477#endif
1478
1479
1480str_list_t *get_hddb_packages(hd_data_t *hd_data)
1481{
1482 return NULL;
1483}
1484
1485
1486unsigned device_class(hd_data_t *hd_data, unsigned vendor, unsigned device)
1487{
1488 hddb_search_t hs = {};
1489
1490 hs.vendor.id = vendor;
1491 hs.device.id = device;
1492 hs.key |= (1 << he_vendor_id) + (1 << he_device_id);
1493
1494 hddb_search(hd_data, &hs, 1);
1495
1496 if(
1497 (hs.value & ((1 << he_baseclass_id) + (1 << he_subclass_id))) ==
1498 ((1 << he_baseclass_id) + (1 << he_subclass_id))
1499 ) {
1500 return (hs.base_class.id << 8) + (hs.sub_class.id & 0xff);
1501 }
1502
1503 return 0;
1504}
1505
1506
1507unsigned sub_device_class(hd_data_t *hd_data, unsigned vendor, unsigned device, unsigned sub_vendor, unsigned sub_device)
1508{
1509 hddb_search_t hs = {};
1510
1511 hs.vendor.id = vendor;
1512 hs.device.id = device;
1513 hs.sub_vendor.id = sub_vendor;
1514 hs.sub_device.id = sub_device;
1515 hs.key |= (1 << he_vendor_id) + (1 << he_device_id) + (1 << he_subvendor_id) + (1 << he_subdevice_id);
1516
1517 hddb_search(hd_data, &hs, 1);
1518
1519 if(
1520 (hs.value & ((1 << he_baseclass_id) + (1 << he_subclass_id))) ==
1521 ((1 << he_baseclass_id) + (1 << he_subclass_id))
1522 ) {
1523 return (hs.base_class.id << 8) + (hs.sub_class.id & 0xff);
1524 }
1525
1526 return 0;
1527}
1528
1529
1530/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1531void hddb_add_info(hd_data_t *hd_data, hd_t *hd)
1532{
1533 hddb_search_t hs = {};
1534 driver_info_t *new_driver_info = NULL;
1535#if WITH_ISDN
1536 cdb_isdn_card *cic;
1537#endif
1538
1539 if(hd->tag.fixed) return;
1540
1541 hs.bus.id = hd->bus.id;
1542 hs.key |= 1 << he_bus_id;
1543
1544 hs.base_class.id = hd->base_class.id;
1545 hs.key |= 1 << he_baseclass_id;
1546
1547 hs.sub_class.id = hd->sub_class.id;
1548 hs.key |= 1 << he_subclass_id;
1549
1550 hs.prog_if.id = hd->prog_if.id;
1551 hs.key |= 1 << he_progif_id;
1552
1553 if(hd->vendor.id) {
1554 hs.vendor.id = hd->vendor.id;
1555 hs.key |= 1 << he_vendor_id;
1556 }
1557
1558 if(hd->vendor.name) {
1559 hs.vendor.name = hd->vendor.name;
1560 hs.key |= 1 << he_vendor_name;
1561 }
1562
1563 if(hd->device.id) {
1564 hs.device.id = hd->device.id;
1565 hs.key |= 1 << he_device_id;
1566 }
1567
1568 if(hd->device.name) {
1569 hs.device.name = hd->device.name;
1570 hs.key |= 1 << he_device_name;
1571 }
1572
1573 if(hd->sub_vendor.id) {
1574 hs.sub_vendor.id = hd->sub_vendor.id;
1575 hs.key |= 1 << he_subvendor_id;
1576 }
1577
1578 if(hd->sub_device.id) {
1579 hs.sub_device.id = hd->sub_device.id;
1580 hs.key |= 1 << he_subdevice_id;
1581 }
1582
1583 hs.revision.id = hd->revision.id;
1584 hs.key |= 1 << he_rev_id;
1585
1586 if(hd->revision.name) {
1587 hs.revision.name = hd->revision.name;
1588 hs.key |= 1 << he_rev_name;
1589 }
1590
1591 if(hd->serial) {
1592 hs.serial = hd->serial;
1593 hs.key |= 1 << he_serial;
1594 }
1595
1596 if(hd->detail && hd->detail->ccw.data) {
1597 hs.cu_model.id=hd->detail->ccw.data->cu_model;
1598 hs.key |= 1 << he_detail_ccw_data_cu_model;
1599 }
1600
1601 hddb_search(hd_data, &hs, 0);
1602
1603 if((hs.value & (1 << he_bus_id))) {
1604 hd->bus.id = hs.bus.id;
1605 }
1606
1607 if((hs.value & (1 << he_bus_name))) {
1608 if(!hd->ref) free_mem(hd->bus.name);
1609 hd->bus.name = new_str(hs.bus.name);
1610 }
1611
1612 if((hs.value & (1 << he_baseclass_id))) {
1613 hd->base_class.id = hs.base_class.id;
1614 }
1615
1616 if((hs.value & (1 << he_baseclass_name))) {
1617 if(!hd->ref) free_mem(hd->base_class.name);
1618 hd->base_class.name = new_str(hs.base_class.name);
1619 }
1620
1621 if((hs.value & (1 << he_subclass_id))) {
1622 hd->sub_class.id = hs.sub_class.id;
1623 }
1624
1625 if((hs.value & (1 << he_subclass_name))) {
1626 if(!hd->ref) free_mem(hd->sub_class.name);
1627 hd->sub_class.name = new_str(hs.sub_class.name);
1628 }
1629
1630 if((hs.value & (1 << he_progif_id))) {
1631 hd->prog_if.id = hs.prog_if.id;
1632 }
1633
1634 if((hs.value & (1 << he_progif_name))) {
1635 if(!hd->ref) free_mem(hd->prog_if.name);
1636 hd->prog_if.name = new_str(hs.prog_if.name);
1637 }
1638
1639 if((hs.value & (1 << he_requires))) {
1640 if(!hd->ref) hd->requires = free_str_list(hd->requires);
1641 hd->requires = hd_split('|', hs.requires);
1642 }
1643
1644 if((hs.value & (1 << he_vendor_id))) {
1645 hd->vendor.id = hs.vendor.id;
1646 }
1647
1648 if((hs.value & (1 << he_vendor_name))) {
1649 if(!hd->ref) free_mem(hd->vendor.name);
1650 hd->vendor.name = new_str(hs.vendor.name);
1651 }
1652
1653 if((hs.value & (1 << he_device_id))) {
1654 hd->device.id = hs.device.id;
1655 }
1656
1657 if((hs.value & (1 << he_device_name))) {
1658 if(!hd->ref) free_mem(hd->device.name);
1659 hd->device.name = new_str(hs.device.name);
1660 }
1661
1662 if((hs.value & (1 << he_subvendor_id))) {
1663 hd->sub_vendor.id = hs.sub_vendor.id;
1664 }
1665
1666 if((hs.value & (1 << he_subvendor_name))) {
1667 if(!hd->ref) free_mem(hd->sub_vendor.name);
1668 hd->sub_vendor.name = new_str(hs.sub_vendor.name);
1669 }
1670
1671 if((hs.value & (1 << he_subdevice_id))) {
1672 hd->sub_device.id = hs.sub_device.id;
1673 }
1674
1675 if((hs.value & (1 << he_subdevice_name))) {
1676 if(!hd->ref) free_mem(hd->sub_device.name);
1677 hd->sub_device.name = new_str(hs.sub_device.name);
1678 }
1679
1680 if((hs.value & (1 << he_detail_ccw_data_cu_model))) {
1681 if(hd->detail && hd->detail->ccw.data)
1682 hd->detail->ccw.data->cu_model=hs.cu_model.id;
1683 }
1684
1685 /* look for sub vendor again */
1686
1687 if(!hd->sub_vendor.name && hd->sub_vendor.id) {
1688 hddb_search_t hs2 = {};
1689
1690 hs2.vendor.id = hd->sub_vendor.id;
1691 hs2.key |= 1 << he_vendor_id;
1692
1693 hddb_search(hd_data, &hs2, 1);
1694
1695 if((hs2.value & (1 << he_vendor_name))) {
1696 hd->sub_vendor.name = new_str(hs2.vendor.name);
1697 }
1698 }
1699
1700 /* look for compat device name */
1701 if(
1702 hd->compat_vendor.id &&
1703 hd->compat_device.id &&
1704 !hd->compat_vendor.name &&
1705 !hd->compat_device.name
1706 ) {
1707 hddb_search_t hs2 = {};
1708
1709 hs2.vendor.id = hd->compat_vendor.id;
1710 hs2.key |= 1 << he_vendor_id;
1711
1712 hs2.device.id = hd->compat_device.id;
1713 hs2.key |= 1 << he_device_id;
1714
1715 hddb_search(hd_data, &hs2, 1);
1716
1717 if((hs2.value & (1 << he_vendor_name))) {
1718 hd->compat_vendor.name = new_str(hs2.vendor.name);
1719 }
1720
1721 if((hs2.value & (1 << he_device_name))) {
1722 hd->compat_device.name = new_str(hs2.device.name);
1723 }
1724 }
1725
1726 /* get package info for compat device id */
1727
1728 if(!hd->requires) {
1729 hddb_search_t hs2 = {};
1730
1731 hs2.vendor.id = hd->compat_vendor.id;
1732 hs2.key |= 1 << he_vendor_id;
1733
1734 hs2.device.id = hd->compat_device.id;
1735 hs2.key |= 1 << he_device_id;
1736
1737 hddb_search(hd_data, &hs2, 1);
1738
1739 if((hs2.value & (1 << he_requires))) {
1740 hd->requires = hd_split('|', hs2.requires);
1741 }
1742 }
1743
1744 /* get driver info */
1745
1746#if WITH_ISDN
1747 if((cic = get_isdn_info(hd))) {
1748 new_driver_info = isdn_driver(hd_data, hd, cic);
1749 if(!hd->model && cic->lname && *cic->lname) {
1750 hd->model = new_str(cic->lname);
1751 }
1752 free_mem(cic);
1753 }
1754 if (!new_driver_info && ((cic = get_dsl_info(hd)))) {
1755 new_driver_info = dsl_driver(hd_data, hd, cic);
1756 if(!hd->model && cic->lname && *cic->lname) {
1757 hd->model = new_str(cic->lname);
1758 }
1759 free_mem(cic);
1760 }
1761#endif
1762
1763 if(!new_driver_info) {
1764 new_driver_info = hd_pcidb(hd_data, hd_data->hddb_pci_hm, hd, new_driver_info);
1765 }
1766
1767 if(!new_driver_info && (hs.value & (1 << he_driver))) {
1768 new_driver_info = hddb_to_device_driver(hd_data, &hs);
1769 }
1770
1771 if(!new_driver_info && (hd->compat_vendor.id || hd->compat_device.id)) {
1772 memset(&hs, 0, sizeof hs);
1773
1774 if(hd->compat_vendor.id) {
1775 hs.vendor.id = hd->compat_vendor.id;
1776 hs.key |= 1 << he_vendor_id;
1777 }
1778 if(hd->compat_device.id) {
1779 hs.device.id = hd->compat_device.id;
1780 hs.key |= 1 << he_device_id;
1781 }
1782
1783 hddb_search(hd_data, &hs, 1);
1784
1785 if((hs.value & (1 << he_driver))) {
1786 new_driver_info = hddb_to_device_driver(hd_data, &hs);
1787 }
1788 }
1789
1790 if(!new_driver_info && hd->base_class.id == bc_keyboard) {
1791 new_driver_info = kbd_driver(hd_data, hd);
1792 }
1793
1794 if(!new_driver_info && hd->base_class.id == bc_monitor) {
1795 new_driver_info = monitor_driver(hd_data, hd);
1796 }
1797
1798 new_driver_info = hd_pcidb(hd_data, hd_data->hddb_pci, hd, new_driver_info);
1799
1800 if(new_driver_info) {
1801 if(!hd->ref) {
1802 hd->driver_info = free_driver_info(hd->driver_info);
1803 }
1804 hd->driver_info = new_driver_info;
1805 expand_driver_info(hd_data, hd);
1806 }
1807
1808 free_str_list(hs.driver);
1809}
1810
1811
1812/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1813driver_info_t *hddb_to_device_driver(hd_data_t *hd_data, hddb_search_t *hs)
1814{
1815 char *s, *t, *t0;
1816 driver_info_t *di = NULL, *di0 = NULL;
1817 str_list_t *sl;
1818
1819 for(sl = hs->driver; sl; sl = sl->next) {
1820 if(!sl->str || !*sl->str || sl->str[1] != '\t') return NULL;
1821
1822 if(di && (*sl->str == 'M' || *sl->str == 'X')) {
1823 add_str_list(&di->any.hddb1, sl->str + 2);
1824 continue;
1825 }
1826
1827 if(di)
1828 di = di->next = new_mem(sizeof *di);
1829 else
1830 di = di0 = new_mem(sizeof *di);
1831
1832 switch(*sl->str) {
1833 case 'd':
1834 di->any.type = di_display;
1835 break;
1836
1837 case 'm':
1838 di->module.modprobe = 1;
1839 case 'i':
1840 di->any.type = di_module;
1841 break;
1842
1843 case 'p':
1844 di->any.type = di_mouse;
1845 break;
1846
1847 case 'x':
1848 di->any.type = di_x11;
1849 break;
1850
1851 default:
1852 di->any.type = di_any;
1853 }
1854
1855 s = new_str(sl->str + 2);
1856 for(t0 = s; (t = strsep(&t0, "|")); ) {
1857 add_str_list(&di->any.hddb0, t);
1858 }
1859 free_mem(s);
1860 }
1861
1862 return di0;
1863}
1864
1865
1866driver_info_t *kbd_driver(hd_data_t *hd_data, hd_t *hd)
1867{
1868 driver_info_t *di;
1869 driver_info_kbd_t *ki;
1870 int arch = hd_cpu_arch(hd_data);
1871 unsigned u;
1872 char *s1, *s2;
1873 hd_t *hd_tmp;
1874 usb_t *usb;
1875
1876 /* country codes
1877 1 Arabic
1878 2 Belgian
1879 3 Canadian-Bilingual
1880 4 Canadian-French
1881 5 Czech Republic
1882 6 Danish
1883 7 Finnish
1884 8 French
1885 9 German
1886 10 Greek
1887 11 Hebrew
1888 12 Hungary
1889 13 International (ISO)
1890 14 Italian
1891 15 Japan (Katakana)
1892 16 Korean
1893 17 Latin American
1894 18 Netherlands/Dutch
1895 19 Norwegian
1896 20 Persian (Farsi)
1897 21 Poland
1898 22 Portuguese
1899 23 Russia
1900 24 Slovakia
1901 25 Spanish
1902 26 Swedish
1903 27 Swiss/French
1904 28 Swiss/German
1905 29 Switzerland
1906 30 Taiwan
1907 31 Turkish
1908 32 UK
1909 33 US
1910 34 Yugoslavia
1911 */
1912 static struct {
1913 unsigned country;
1914 char *layout;
1915 char *keymap;
1916 } country_code[] = {
1917 { 5, "cs", "cz-us-qwertz" },
1918 { 8, "fr", "fr-latin1" },
1919 { 9, "de", "de-latin1-nodeadkeys" },
1920 { 10, "gr", "gr" },
1921 { 14, "it", "it" },
1922 { 18, "nl", "us" },
1923 { 23, "ru", "ru1" },
1924 { 25, "es", "es" },
1925 { 32, "uk", "uk" },
1926 { 33, "us", "us" }
1927 };
1928
1929 if(hd->sub_class.id == sc_keyboard_console) return NULL;
1930
1931 di = new_mem(sizeof *di);
1932 di->kbd.type = di_kbd;
1933 ki = &(di->kbd);
1934
1935 switch(arch) {
1936 case arch_intel:
1937 case arch_x86_64:
1938 case arch_alpha:
1939 ki->XkbRules = new_str("xfree86");
1940 ki->XkbModel = new_str("pc104");
1941 break;
1942
1943 case arch_ppc:
1944 case arch_ppc64:
1945 ki->XkbRules = new_str("xfree86");
1946 ki->XkbModel = new_str("macintosh");
1947 for(hd_tmp = hd_data->hd; hd_tmp; hd_tmp = hd_tmp->next) {
1948 if(
1949 hd_tmp->base_class.id == bc_internal &&
1950 hd_tmp->sub_class.id == sc_int_cpu &&
1951 hd_tmp->detail &&
1952 hd_tmp->detail->type == hd_detail_cpu &&
1953 hd_tmp->detail->cpu.data
1954 ) {
1955 s1 = hd_tmp->detail->cpu.data->vend_name;
1956 if(s1 && (strstr(s1, "CHRP ") == s1 || strstr(s1, "PReP ") == s1)) {
1957 free_mem(ki->XkbModel);
1958 ki->XkbModel = new_str("pc104");
1959 }
1960 }
1961 }
1962 break;
1963
1964 case arch_sparc:
1965 case arch_sparc64:
1966 if(hd->vendor.id == MAKE_ID(TAG_SPECIAL, 0x0202)) {
1967 ki->XkbRules = new_str("sun");
1968 u = ID_VALUE(hd->device.id);
1969 if(u == 4) ki->XkbModel = new_str("type4");
1970 if(u == 5) {
1971 ki->XkbModel = new_str(ID_VALUE(hd->sub_device.id) == 2 ? "type5_euro" : "type5");
1972 }
1973 s1 = s2 = NULL;
1974
1975 switch(hd->prog_if.id) {
1976 case 0: case 1: case 33: case 34: case 80: case 81:
1977 default:
1978 s1 = "us"; s2 = "sunkeymap";
1979 break;
1980
1981 case 2:
1982 s1 = "fr"; s2 = "sunt5-fr-latin1"; // fr_BE?
1983 break;
1984
1985 case 3:
1986 s1 = "ca";
1987 break;
1988
1989 case 4: case 36: case 83:
1990 s1 = "dk";
1991 break;
1992
1993 case 5: case 37: case 84:
1994 s1 = "de"; s2 = "sunt5-de-latin1";
1995 break;
1996
1997 case 6: case 38: case 85:
1998 s1 = "it";
1999 break;
2000
2001 case 7: case 39: case 86:
2002 s1 = "nl";
2003 break;
2004
2005 case 8: case 40: case 87:
2006 s1 = "no";
2007 if(u == 4) s2 = "sunt4-no-latin1";
2008 break;
2009
2010 case 9: case 41: case 88:
2011 s1 = "pt";
2012 break;
2013
2014 case 10: case 42: case 89:
2015 s1 = "es";
2016 s2 = u == 4 ? "sunt4-es" : "sunt5-es";
2017 break;
2018
2019 case 11: case 43: case 90:
2020 s1 = "se"; s2 = "sunt5-fi-latin1"; // se is swedish, not fi
2021 break;
2022
2023 case 12: case 44: case 91:
2024 s1 = "fr"; s2 = "sunt5-fr-latin1"; // fr_CH
2025 break;
2026
2027 case 13: case 45: case 92:
2028 s1 = "de"; s2 = "sunt5-de-latin1"; // de_CH
2029 break;
2030
2031 case 14: case 46: case 93:
2032 s1 = "gb"; s2 = "sunt5-uk";
2033 break;
2034
2035 case 16: case 47: case 94:
2036 s1 = "ko";
2037 break;
2038
2039 case 17: case 48: case 95:
2040 s1 = "tw";
2041 break;
2042
2043 case 32: case 49: case 96:
2044 s1 = "jp";
2045 break;
2046
2047 case 50: case 97:
2048 s1 = "fr"; s2 = "sunt5-fr-latin1"; // fr_CA
2049 break;
2050
2051 case 51:
2052 s1 = "hu";
2053 break;
2054
2055 case 52:
2056 s1 = "pl"; s2 = "sun-pl";
2057 break;
2058
2059 case 53:
2060 s1 = "cs";
2061 break;
2062
2063 case 54:
2064 s1 = "ru"; s2 = "sunt5-ru";
2065 break;
2066 }
2067 ki->XkbLayout = new_str(s1);
2068 ki->keymap = new_str(s2);
2069 }
2070 else {
2071 ki->XkbRules = new_str("xfree86");
2072 ki->XkbModel = new_str("pc104");
2073 }
2074 break;
2075
2076 default:
2077 ki->XkbRules = new_str("xfree86");
2078 }
2079
2080 if(
2081 hd->bus.id == bus_usb &&
2082 hd->detail &&
2083 hd->detail->type == hd_detail_usb &&
2084 (usb = hd->detail->usb.data) &&
2085 usb->country
2086 ) {
2087 for(u = 0; u < sizeof country_code / sizeof *country_code; u++) {
2088 if(country_code[u].country == usb->country) {
2089 if(!ki->XkbLayout) ki->XkbLayout = new_str(country_code[u].layout);
2090 if(!ki->keymap) ki->keymap = new_str(country_code[u].keymap);
2091 break;
2092 }
2093 }
2094 }
2095
2096 return di;
2097}
2098
2099
2100driver_info_t *monitor_driver(hd_data_t *hd_data, hd_t *hd)
2101{
2102 driver_info_t *di = NULL;
2103 driver_info_display_t *ddi;
2104 monitor_info_t *mi;
2105 hd_res_t *res;
2106 unsigned width = 640, height = 480;
2107
2108 if(
2109 hd->detail &&
2110 hd->detail->type == hd_detail_monitor &&
2111 (mi = hd->detail->monitor.data) &&
2112 mi->min_hsync
2113 ) {
2114 di = new_mem(sizeof *di);
2115 di->display.type = di_display;
2116 ddi = &(di->display);
2117
2118 ddi->min_vsync = mi->min_vsync;
2119 ddi->max_vsync = mi->max_vsync;
2120 ddi->min_hsync = mi->min_hsync;
2121 ddi->max_hsync = mi->max_hsync;
2122
2123 for(res = hd->res; res; res = res->next) {
2124 if(res->any.type == res_monitor) {
2125 if(res->monitor.width * res->monitor.height > width * height ) {
2126 width = res->monitor.width;
2127 height = res->monitor.height;
2128 }
2129 }
2130 }
2131
2132 ddi->width = width;
2133 ddi->height = height;
2134 }
2135
2136 return di;
2137}
2138
2139
2140#if WITH_ISDN
2141
2142#if 0
2143int chk_free_biosmem(hd_data_t *hd_data, unsigned addr, unsigned len)
2144{
2145 unsigned u;
2146 unsigned char c;
2147
2148 addr -= hd_data->bios_rom.start;
2149 if(
2150 !hd_data->bios_rom.data ||
2151 addr >= hd_data->bios_rom.size ||
2152 addr + len > hd_data->bios_rom.size
2153 ) return 0;
2154
2155 for(c = 0xff, u = addr; u < addr + len; u++) {
2156 c &= hd_data->bios_rom.data[u];
2157 }
2158
2159 return c == 0xff ? 1 : 0;
2160}
2161
2162isdn_parm_t *new_isdn_parm(isdn_parm_t **ip)
2163{
2164 while(*ip) ip = &(*ip)->next;
2165
2166 return *ip = new_mem(sizeof **ip);
2167}
2168#endif
2169
2170driver_info_t *isdn_driver(hd_data_t *hd_data, hd_t *hd, cdb_isdn_card *cic)
2171{
2172 driver_info_t *di0, *di;
2173 cdb_isdn_vario *civ;
2174/* hd_res_t *res;
2175 uint64_t i, irqs, irqs2;
2176 int irq_val, pnr;
2177*/
2178 int drv;
2179 str_list_t *sl, *sl0;
2180
2181 if(!cic) return NULL;
2182
2183 di0 = new_mem(sizeof *di0);
2184
2185 drv = cic->vario;
2186 di = NULL;
2187
2188 while((civ = hd_cdbisdn_get_vario(drv))) {
2189 drv = civ->next_vario;
2190 if (di) {
2191 di->next = new_mem(sizeof *di);
2192 di = di->next;
2193 } else {
2194 di = di0;
2195 }
2196 di->isdn.type = di_isdn;
2197 di->isdn.i4l_type = civ->typ;
2198 di->isdn.i4l_subtype = civ->subtyp;
2199 di->isdn.i4l_name = new_str(cic->lname);
2200
2201 if(civ->need_pkg && *civ->need_pkg) {
2202 sl0 = hd_split(',', (char *) civ->need_pkg);
2203 for(sl = sl0; sl; sl = sl->next) {
2204 if(!search_str_list(hd->requires, sl->str)) {
2205 add_str_list(&hd->requires, sl->str);
2206 }
2207 }
2208 free_str_list(sl0);
2209 }
2210
2211 if(hd->bus.id == bus_pci) continue;
2212#if 0
2213 pnr = 1;
2214 civ = hd_cdbisdn_get_vario(cic->vario);
2215 if (!civ) continue;
2216 if (civ->irq && civ->irq[0]) {
2217 ip = new_isdn_parm(&di->isdn.params);
2218 ip->name = new_str("IRQ");
2219 ip->type = CDBISDN_P_IRQ;
2220 }
2221 if (civ->io && civ->io[0]) {
2222 ip = new_isdn_parm(&di->isdn.params);
2223 ip->name = new_str("IO");
2224 ip->type = CDBISDN_P_IO;
2225 }
2226 if (civ->membase && civ->membase[0]) {
2227 ip = new_isdn_parm(&di->isdn.params);
2228 ip->name = new_str("MEMBASE");
2229 ip->type = CDBISDN_P_MEM;
2230 }
2231 while((ipi = hd_ihw_get_parameter(ici->handle, pnr++))) {
2232 ip = new_isdn_parm(&di->isdn.params);
2233 ip->name = new_str(ipi->name);
2234 ip->type = ipi->type & P_TYPE_MASK;
2235 ip->flags = ipi->flags & P_PROPERTY_MASK;
2236 ip->def_value = ipi->def_value;
2237 if(ipi->list) ip->alt_values = *ipi->list;
2238 ip->alt_value = new_mem(ip->alt_values * sizeof *ip->alt_value);
2239 for(i = 0; i < ip->alt_values; i++) {
2240 ip->alt_value[i] = ipi->list[i + 1];
2241 }
2242 ip->valid = 1;
2243
2244 if((ip->flags & P_SOFTSET)) {
2245 switch(ip->type) {
2246 case P_IRQ:
2247 update_irq_usage(hd_data);
2248 irqs = 0;
2249 for(i = 0; i < ip->alt_values; i++) {
2250 irqs |= 1ull << ip->alt_value[i];
2251 }
2252 irqs &= ~(hd_data->used_irqs | hd_data->assigned_irqs);
2253#ifdef __i386__
2254 irqs &= 0xffffull; /* max. 16 on intel */
2255 /*
2256 * The point is, that this is relevant for isa boards only
2257 * and those have irq values < 16 anyway. So it really
2258 * doesn't matter if we mask with 0xffff or not.
2259 */
2260#endif
2261 if(!irqs) {
2262 ip->conflict = 1;
2263 ip->valid = 0;
2264 }
2265 else {
2266 irqs2 = irqs & ~0xc018ull;
2267 /* see if we can avoid irqs 3,4,14,15 */
2268 if(irqs2) irqs = irqs2;
2269 irq_val = -1;
2270 /* try default value first */
2271 if(ip->def_value && (irqs & (1ull << ip->def_value))) {
2272 irq_val = ip->def_value;
2273 }
2274 else {
2275 for(i = 0; i < 64 && irqs; i++, irqs >>= 1) {
2276 if((irqs & 1)) irq_val = i;
2277 }
2278 }
2279 if(irq_val >= 0) {
2280 ip->value = irq_val;
2281 hd_data->assigned_irqs |= 1ull << irq_val;
2282 }
2283 else {
2284 ip->valid = 0;
2285 }
2286 }
2287 break;
2288 case P_MEM:
2289 if(!hd_data->bios_rom.data) {
2290 if(ip->def_value) {
2291 ip->value = ip->def_value;
2292 }
2293 }
2294 else {
2295 /* ###### 0x2000 is just guessing -> should be provided by libihw */
2296 if(ip->def_value && chk_free_biosmem(hd_data, ip->def_value, 0x2000)) {
2297 ip->value = ip->def_value;
2298 }
2299 else {
2300 for(i = ip->alt_values - 1; i >= 0; i--) {
2301 if(chk_free_biosmem(hd_data, ip->alt_value[i], 0x2000)) {
2302 ip->value = ip->alt_value[i];
2303 break;
2304 }
2305 }
2306 }
2307 }
2308 if(!ip->value) ip->conflict = 1;
2309 break;
2310 default:
2311 ip->valid = 0;
2312 }
2313 }
2314 else if((ip->flags & P_DEFINE)) {
2315 res = NULL;
2316 switch(ip->type) {
2317 case P_IRQ:
2318 res = get_res(hd, res_irq, 0);
2319 if(res) ip->value = res->irq.base;
2320 break;
2321 case P_MEM:
2322 res = get_res(hd, res_mem, 0);
2323 if(res) ip->value = res->mem.base;
2324 break;
2325 case P_IO:
2326 res = get_res(hd, res_io, 0);
2327 if(res) ip->value = res->io.base;
2328 break;
2329 case P_IO0:
2330 case P_IO1:
2331 case P_IO2:
2332 res = get_res(hd, res_io, ip->type - P_IO0);
2333 if(res) ip->value = res->io.base;
2334 break;
2335 // ##### might break for 64bit pci entries?
2336 case P_BASE0:
2337 case P_BASE1:
2338 case P_BASE2:
2339 case P_BASE3:
2340 case P_BASE4:
2341 case P_BASE5:
2342 res = get_res(hd, res_mem, ip->type - P_BASE0);
2343 if(res) ip->value = res->mem.base;
2344 break;
2345 default:
2346 ip->valid = 0;
2347 }
2348 if(!res) ip->valid = 0;
2349 }
2350 }
2351#endif
2352 }
2353 if(!di) di0 = free_mem(di0);
2354
2355 return di0;
2356}
2357
2358driver_info_t *dsl_driver(hd_data_t *hd_data, hd_t *hd, cdb_isdn_card *cic)
2359{
2360 driver_info_t *di0, *di;
2361 cdb_isdn_vario *civ;
2362 int drv;
2363 str_list_t *sl, *sl0;
2364
2365 if(!cic) return NULL;
2366
2367 di0 = new_mem(sizeof *di0);
2368
2369 drv = cic->vario;
2370 di = NULL;
2371
2372 while((civ = hd_cdbisdn_get_vario(drv))) {
2373 drv = civ->next_vario;
2374 if (di) {
2375 di->next = new_mem(sizeof *di);
2376 di = di->next;
2377 } else {
2378 di = di0;
2379 }
2380 di->dsl.type = di_dsl;
2381 if(civ->interface && *civ->interface) {
2382 if (!strcmp(civ->interface, "CAPI20")) {
2383 di->dsl.mode = new_str("capiadsl");
2384 if(civ->mod_name && *civ->mod_name)
2385 di->dsl.name = new_str(civ->mod_name);
2386 else
2387 di->dsl.name = new_str("unknown");
2388 } else if (!strcmp(civ->interface, "pppoe")) {
2389 di->dsl.mode = new_str("pppoe");
2390 if(civ->mod_name && *civ->mod_name)
2391 di->dsl.name = new_str(civ->mod_name);
2392 else
2393 di->dsl.name = new_str("none");
2394 } else {
2395 di->dsl.mode = new_str("unknown");
2396 di->dsl.name = new_str("unknown");
2397 }
2398 } else {
2399 di->dsl.mode = new_str("unknown");
2400 di->dsl.name = new_str("unknown");
2401 }
2402
2403 if(civ->need_pkg && *civ->need_pkg) {
2404 sl0 = hd_split(',', (char *) civ->need_pkg);
2405 for(sl = sl0; sl; sl = sl->next) {
2406 if(!search_str_list(hd->requires, sl->str)) {
2407 add_str_list(&hd->requires, sl->str);
2408 }
2409 }
2410 free_str_list(sl0);
2411 }
2412
2413 if(hd->bus.id == bus_pci) continue;
2414 }
2415 if(!di) di0 = free_mem(di0);
2416
2417 return di0;
2418}
2419
2420#endif /* WITH_ISDN */
2421
2422
2423hd_res_t *get_res(hd_t *hd, enum resource_types t, unsigned index)
2424{
2425 hd_res_t *res;
2426
2427 for(res = hd->res; res; res = res->next) {
2428 if(res->any.type == t) {
2429 if(!index) return res;
2430 index--;
2431 }
2432 }
2433
2434 return NULL;
2435}
2436
2437
2438driver_info_t *reorder_x11(driver_info_t *di0, char *info)
2439{
2440 driver_info_t *di, *di_new, **di_list;
2441 int i, dis, found;
2442
2443 for(dis = 0, di = di0; di; di = di->next) dis++;
2444
2445 di_list = new_mem(dis * sizeof *di_list);
2446
2447 for(i = 0, di = di0; di; di = di->next) {
2448 di_list[i++] = di;
2449 }
2450
2451 di = di_new = NULL;
2452 for(i = found = 0; i < dis; i++) {
2453 if(
2454 !strcmp(di_list[i]->x11.xf86_ver, info) ||
2455 !strcmp(di_list[i]->x11.server, info)
2456 ) {
2457 found = 1;
2458 if(di) {
2459 di = di->next = di_list[i];
2460 }
2461 else {
2462 di = di_new = di_list[i];
2463 }
2464 di->next = NULL;
2465 di_list[i] = NULL;
2466 }
2467 }
2468
2469 for(i = 0; i < dis; i++) {
2470 if(di_list[i]) {
2471 if(di) {
2472 di = di->next = di_list[i];
2473 }
2474 else {
2475 di = di_new = di_list[i];
2476 }
2477 di->next = NULL;
2478 di_list[i] = NULL;
2479 }
2480 }
2481
2482 free_mem(di_list);
2483
2484 if(!found && strlen(info) > 1) {
2485 free_driver_info(di_new);
2486 di_new = new_mem(sizeof *di_new);
2487 di_new->any.type = di_x11;
2488 di_new->x11.server = new_str(info);
2489 di_new->x11.xf86_ver = new_str(*info >= 'A' && *info <= 'Z' ? "3" : "4");
2490 }
2491
2492 return di_new;
2493}
2494
2495
2496void expand_driver_info(hd_data_t *hd_data, hd_t *hd)
2497{
2498 int i;
2499 unsigned u1, u2;
2500 char *s, *t, *t0;
2501 driver_info_t *di;
2502 str_list_t *sl, *sl1, *sl2, *cmd;
2503
2504 if(!hd || !hd->driver_info) return;
2505
2506 for(di = hd->driver_info; di; di = di->next) {
2507 switch(di->any.type) {
2508 case di_display:
2509 for(i = 0, sl = di->display.hddb0; sl; sl = sl->next, i++) {
2510 if(i == 0 && sscanf(sl->str, "%ux%u", &u1, &u2) == 2) {
2511 di->display.width = u1;
2512 di->display.height = u2;
2513 }
2514 else if(i == 1 && sscanf(sl->str, "%u-%u", &u1, &u2) == 2) {
2515 di->display.min_vsync = u1;
2516 di->display.max_vsync = u2;
2517 }
2518 else if(i == 2 && sscanf(sl->str, "%u-%u", &u1, &u2) == 2) {
2519 di->display.min_hsync = u1;
2520 di->display.max_hsync = u2;
2521 }
2522 else if(i == 3 && sscanf(sl->str, "%u", &u1) == 1) {
2523 di->display.bandwidth = u1;
2524 }
2525 }
2526 break;
2527
2528 case di_module:
2529 for(di->module.active = 1, sl = di->module.hddb0; sl; sl = sl->next) {
2530 t0 = s = new_str(sl->str);
2531
2532 t = strsep(&t0, " ");
2533
2534 add_str_list(&di->module.names, t);
2535 di->module.active &= (
2536 hd_module_is_active(hd_data, t) |
2537 (search_str_list(hd->drivers, t) ? 1 : 0)
2538 );
2539
2540 if(t0) {
2541 add_str_list(&di->module.mod_args, module_cmd(hd, t0));
2542 }
2543 else {
2544 add_str_list(&di->module.mod_args, NULL);
2545 }
2546
2547 free_mem(s);
2548 }
2549 for(sl = di->module.hddb1; sl; sl = sl->next) {
2550 s = module_cmd(hd, sl->str);
2551 if(s) str_printf(&di->module.conf, -1, "%s\n", s);
2552 }
2553 break;
2554
2555 case di_mouse:
2556 di->mouse.buttons = di->mouse.wheels = -1;
2557 u1 = 0;
2558 if(
2559 hd->compat_vendor.id == MAKE_ID(TAG_SPECIAL, 0x0210) &&
2560 ID_TAG(hd->compat_device.id) == TAG_SPECIAL
2561 ) {
2562 u1 = hd->compat_device.id;
2563 }
2564 if(
2565 hd->vendor.id == MAKE_ID(TAG_SPECIAL, 0x0210) &&
2566 ID_TAG(hd->device.id) == TAG_SPECIAL
2567 ) {
2568 u1 = hd->device.id;
2569 }
2570 if(u1) {
2571 di->mouse.wheels = ID_VALUE(u1) >> 4;
2572 di->mouse.buttons = ID_VALUE(u1) & 15;
2573 }
2574 for(i = 0, sl = di->mouse.hddb0; sl; sl = sl->next, i++) {
2575 if(i == 0) {
2576 di->mouse.xf86 = new_str(sl->str);
2577 }
2578 else if(i == 1) {
2579 di->mouse.gpm = new_str(sl->str);
2580 }
2581 else if(i == 2 && *sl->str) {
2582 di->mouse.buttons = strtol(sl->str, NULL, 10);
2583 }
2584 else if(i == 3 && *sl->str) {
2585 di->mouse.wheels = strtol(sl->str, NULL, 10);
2586 }
2587 }
2588 break;
2589
2590 case di_x11:
2591 for(i = 0, sl = di->x11.hddb0; sl; sl = sl->next, i++) {
2592 if(i == 0) {
2593 di->x11.xf86_ver = new_str(sl->str);
2594 }
2595 else if(i == 1) {
2596 di->x11.server = new_str(sl->str);
2597 }
2598 else if(i == 2) {
2599 if(!strcmp(sl->str, "3d")) di->x11.x3d = 1;
2600 }
2601#if 0
2602 else if(i == 3) {
2603 s = new_str(sl->str);
2604 for(t0 = s; (t = strsep(&t0, ",")); ) {
2605 add_str_list(&di->x11.packages, t);
2606 }
2607 free_mem(s);
2608 }
2609#endif
2610 else if(i == 4) {
2611 s = new_str(sl->str);
2612 for(t0 = s; (t = strsep(&t0, ",")); ) {
2613 add_str_list(&di->x11.extensions, t);
2614 }
2615 free_mem(s);
2616 }
2617 else if(i == 5) {
2618 s = new_str(sl->str);
2619 for(t0 = s; (t = strsep(&t0, ",")); ) {
2620 add_str_list(&di->x11.options, t);
2621 }
2622 free_mem(s);
2623 }
2624 else if(i == 6) {
2625 for(sl2 = sl1 = hd_split(',', sl->str); sl2; sl2 = sl2->next) {
2626 u1 = strtoul(sl2->str, NULL, 0);
2627 switch(u1) {
2628 case 8:
2629 di->x11.colors.c8 = 1;
2630 di->x11.colors.all |= (1 << 0);
2631 break;
2632
2633 case 15:
2634 di->x11.colors.c15 = 1;
2635 di->x11.colors.all |= (1 << 1);
2636 break;
2637
2638 case 16:
2639 di->x11.colors.c16 = 1;
2640 di->x11.colors.all |= (1 << 2);
2641 break;
2642
2643 case 24:
2644 di->x11.colors.c24 = 1;
2645 di->x11.colors.all |= (1 << 3);
2646 break;
2647
2648 case 32:
2649 di->x11.colors.c32 = 1;
2650 di->x11.colors.all |= (1 << 4);
2651 break;
2652 }
2653 }
2654 free_str_list(sl1);
2655 }
2656 else if(i == 7) {
2657 di->x11.dacspeed = strtol(sl->str, NULL, 10);
2658 }
2659 else if(i == 8) {
2660 di->x11.script = new_str(sl->str);
2661 }
2662 }
2663 for(i = 0, sl = di->x11.hddb1; sl; sl = sl->next, i++) {
2664 add_str_list(&di->x11.raw, sl->str);
2665 }
2666#if 0
2667 // ######## for compatibility
2668 for(sl = hd->requires; sl; sl = sl->next) {
2669 add_str_list(&di->x11.packages, sl->str);
2670 }
2671#endif
2672 break;
2673
2674 default:
2675 break;
2676 }
2677 }
2678
2679 di = hd->driver_info;
2680 if(di && di->any.type == di_x11 && !hd_probe_feature(hd_data, pr_ignx11)) {
2681 cmd = get_cmdline(hd_data, "x11");
2682 if(cmd && *cmd->str) {
2683 hd->driver_info = reorder_x11(di, cmd->str);
2684 }
2685 free_str_list(cmd);
2686 }
2687}
2688
2689
2690char *module_cmd(hd_t *hd, char *cmd)
2691{
2692 static char buf[256];
2693 char *s = buf;
2694 int idx, ofs;
2695 hd_res_t *res;
2696
2697 // skip inactive PnP cards
2698 // ##### Really necessary here?
2699 if(
2700 hd->is.isapnp &&
2701 hd->detail &&
2702 hd->detail->isapnp.data &&
2703 !(hd->detail->isapnp.data->flags & (1 << isapnp_flag_act))
2704 ) return NULL;
2705
2706 *buf = 0;
2707 while(*cmd) {
2708 if(sscanf(cmd, "<io%u>%n", &idx, &ofs) >= 1) {
2709 if((res = get_res(hd, res_io, idx))) {
2710 s += sprintf(s, "0x%02"PRIx64, res->io.base);
2711 cmd += ofs;
2712 }
2713 else {
2714 return NULL;
2715 }
2716 }
2717 else if(sscanf(cmd, "<irq%u>%n", &idx, &ofs) >= 1) {
2718 if((res = get_res(hd, res_irq, idx))) {
2719 s += sprintf(s, "%u", res->irq.base);
2720 cmd += ofs;
2721 }
2722 else {
2723 return NULL;
2724 }
2725 }
2726 else {
2727 *s++ = *cmd++;
2728 }
2729
2730 if(s - buf > (int) sizeof buf - 20) return NULL;
2731 }
2732
2733 *s = 0;
2734 return buf;
2735}
2736
2737
2738/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2739char *hid_tag_name(int tag)
2740{
2741 return (unsigned) tag < sizeof hid_tag_names / sizeof *hid_tag_names ? hid_tag_names[tag] : "";
2742}
2743
2744char *hid_tag_name2(int tag)
2745{
2746 return (unsigned) tag < sizeof hid_tag_names2 / sizeof *hid_tag_names2 ? hid_tag_names2[tag] : "";
2747}
2748