~ubuntu-branches/ubuntu/edgy/hwinfo/edgy

« back to all changes in this revision

Viewing changes to src/hd/hddb.c

  • Committer: Bazaar Package Importer
  • Author(s): James Vega
  • Date: 2006-09-28 20:56:06 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060928205606-bgxl69hts04xbx51
Tags: 13.4-1
* New upstream version.
* Switch from dbs to quilt
  - Revamp debian/rules
  - Add quilt and remove dbs from Build-Depends in debian/control
* Remove reference to hwscan(8) from manpage. (closes: #388245)
* Re-wrote manpage from scratch.  Drop docbook-to-man from Build-Depends.
* Remove NEWS.Debian since it is no longer applicable.

Show diffs side-by-side

added added

removed removed

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