1 |
#!/usr/bin/perl |
2 |
|
3 |
use MDK::Common; |
4 |
|
5 |
|
6 |
my @ignored_modules = ( |
7 |
qw(alsa ignore), |
8 |
); |
9 |
|
10 |
my ($force, @force_modules, $all, $keep_subids, $wildcards, $use_description); |
11 |
|
12 |
# UPDATE ME WHEN UPDATING ../lst/Cards+: |
13 |
my $ati_driver = 'Card:ATI Radeon HD 2000 and later (radeon/fglrx)'; |
14 |
my $ati_driver_rhd = 'Card:ATI Radeon HD 2000 and later (radeonhd/fglrx)'; |
15 |
my $ati_driver_vesa= 'Card:ATI Radeon HD 2000 and later (vesa/fglrx)'; |
16 |
my $ati_free_only = 'Card:ATI Radeon X1950 and earlier'; |
17 |
my $ati_rhd_only = 'Card:ATI Radeon RV710 9592'; |
18 |
# also, be careful when merging as Cards+ and pcitable may contain card-specific |
19 |
# cases due to bugs in the various drivers |
20 |
|
21 |
if ($0 =~ /merge2pcitable/) |
22 |
{ |
23 |
if ($ARGV[0] =~ /^-f=?(.*)$/) { |
24 |
shift; |
25 |
@force_modules = split(/,/, $1); |
26 |
$force = !@force_modules; |
27 |
} |
28 |
$ARGV[0] eq '-a' and $all = shift; |
29 |
$ARGV[0] eq '--keep-subids' and $keep_subids = shift; |
30 |
$ARGV[0] eq '--handle-wildcards' and $wildcards = shift; |
31 |
$ARGV[0] eq '--old' and $use_description = shift; |
32 |
|
33 |
my $formats = join '|', grep { $_ } map { /^read_(.*)/ ? $1 : '' } keys %main::; |
34 |
|
35 |
@ARGV == 3 or die "usage: $0 [-f[=module1,...]] [-a] [--old] $formats <in_file> <mdk_pcitable>\n"; |
36 |
|
37 |
my ($format, $in, $pcitable) = @ARGV; |
38 |
|
39 |
my $read = $main::{"read_$format"} or die "unknown format $format (must be one of $formats)\n"; |
40 |
my $d_pci = read_pcitable($pcitable, 'strict'); |
41 |
my ($d_in, $classes) = $read->($in); |
42 |
|
43 |
if ($format eq 'kernel_aliasmap' || $format eq 'fglrxko_pci_ids_h') { |
44 |
foreach (keys %$d_pci) { |
45 |
if (member($d_pci->{$_}[0], ($ati_driver, $ati_driver_rhd, $ati_driver_vesa)) && !$d_in->{$_}) { |
46 |
# support dropped, handle: |
47 |
if ($d_pci->{$_}[0] eq $ati_driver) { |
48 |
$d_pci->{$_}[0] = $ati_free_only; |
49 |
} elsif ($d_pci->{$_}[0] eq $ati_driver_vesa) { |
50 |
delete $d_pci->{$_}; |
51 |
} elsif ($d_pci->{$_}[0] eq $ati_driver_rhd) { |
52 |
$d_pci->{$_}[0] = $ati_rhd_only |
53 |
} else { |
54 |
die 'not handled ' . $_; |
55 |
} |
56 |
} elsif (member($d_pci->{$_}[0], ($ati_free_only, $ati_rhd_only)) && $d_in->{$_}) { |
57 |
# support added for pre-existing entry, handle: |
58 |
if ($d_pci->{$_}[0] eq $ati_free_only) { |
59 |
$d_pci->{$_}[0] = $ati_driver; |
60 |
} elsif ($d_pci->{$_}[0] eq $ati_rhd_only) { |
61 |
$d_pci->{$_}[0] = $ati_driver_rhd; |
62 |
} else { |
63 |
die 'not handled ' . $_; |
64 |
} |
65 |
} |
66 |
} |
67 |
} |
68 |
# Here we hack around so that drivers get used in order radeon, radeonhd, vesa: |
69 |
if ($format eq 'ati_pciids_csv') { |
70 |
foreach (keys %$d_pci) { |
71 |
if (member($d_pci->{$_}[0], ($ati_driver, $ati_free_only)) && !$d_in->{$_}) { |
72 |
# support dropped, handle: |
73 |
if ($d_pci->{$_}[0] eq $ati_driver) { |
74 |
$d_pci->{$_}[0] = $ati_driver_vesa; |
75 |
} elsif ($d_pci->{$_}[0] eq $ati_free_only) { |
76 |
delete $d_pci->{$_}; |
77 |
} else { |
78 |
die 'not handled ' . $_; |
79 |
} |
80 |
} elsif (member($d_pci->{$_}[0], ($ati_driver_rhd, $ati_driver_vesa, $ati_rhd_only)) && $d_in->{$_}) { |
81 |
# support added for pre-existing entry, handle: |
82 |
next if $_ eq "10029610ffffffff"; # see Cards+ and #49824 |
83 |
if (member($d_pci->{$_}[0], ($ati_driver_rhd, $ati_driver_vesa))) { |
84 |
$d_pci->{$_}[0] = $ati_driver; |
85 |
} elsif ($d_pci->{$_}[0] eq $ati_rhd_only) { |
86 |
$d_pci->{$_}[0] = $ati_free_only; |
87 |
} else { |
88 |
die 'not handled ' . $_; |
89 |
} |
90 |
} |
91 |
} |
92 |
} |
93 |
if ($format eq 'rhd_id_c') { |
94 |
foreach (keys %$d_pci) { |
95 |
if (member($d_pci->{$_}[0], ($ati_driver_rhd, $ati_rhd_only)) && !$d_in->{$_}) { |
96 |
# support dropped, handle: |
97 |
if ($d_pci->{$_}[0] eq $ati_driver_rhd) { |
98 |
$d_pci->{$_}[0] = $ati_driver_vesa; |
99 |
} elsif ($d_pci->{$_}[0] eq $ati_rhd_only) { |
100 |
delete $d_pci->{$_}; |
101 |
} else { |
102 |
die 'not handled ' . $_; |
103 |
} |
104 |
} elsif ($d_pci->{$_}[0] eq $ati_driver_vesa && $d_in->{$_}) { |
105 |
# support added for pre-existing entry, handle: |
106 |
$d_pci->{$_}[0] = $ati_driver_rhd; |
107 |
} |
108 |
} |
109 |
} |
110 |
|
111 |
merge($d_pci, $d_in, $classes); |
112 |
exit 1 if our $error; |
113 |
cleanup_subids($d_pci) if !$keep_subids; |
114 |
write_pcitable($d_pci); |
115 |
} else { 1 } |
116 |
|
117 |
sub dummy_module { |
118 |
my ($m) = @_; |
119 |
$m =~ s/"(.*)"/$1/; |
120 |
member($m, @ignored_modules); |
121 |
} |
122 |
|
123 |
sub to_string { |
124 |
my ($id, $driver) = @_; |
125 |
@$driver >= 1 or error("error: to_string $id"); |
126 |
my ($module, $text) = map { defined($_) && qq("$_") } @$driver; |
127 |
my ($id1, $id2, $subid1, $subid2) = map { "0x$_" } ($id =~ /(....)/g); |
128 |
join "\t", $id1, $id2, if_("$subid1 $subid2" ne "0xffff 0xffff", $subid1, $subid2), $module, if_($use_description && $text, $text); |
129 |
} |
130 |
|
131 |
sub read_rhpcitable { |
132 |
my ($f, $strict) = @_; |
133 |
read_pcitable($f, $strict, 1); |
134 |
} |
135 |
|
136 |
# works for RedHat's pcitable old and new format, + mdk format (alike RedHat's old one) |
137 |
# (the new format has ending .o's and double quotes are removed) |
138 |
sub read_pcitable { |
139 |
my ($f, $strict, $newer_rh_format) = @_; |
140 |
my %drivers; |
141 |
my %class; |
142 |
my $line = 0; |
143 |
my $rm_quote_silent = sub { local ($_) = @_; s/^"//; s/"$//; $_ }; |
144 |
my $rm_quote = sub { |
145 |
local ($_) = @_; |
146 |
s/^"// or error("$f:$line: missing left quote"); |
147 |
s/"$// or error("$f:$line: missing right quote"); |
148 |
/"/ && $strict and error("$f:$line: bad double quote"); |
149 |
$_; |
150 |
}; |
151 |
foreach (eval { catMaybeCompressed($f) }) { |
152 |
chomp; $line++; |
153 |
next if /^#/ || /^\s*$/; |
154 |
|
155 |
if (!$strict) { |
156 |
#- help poor written pcitable's like redhat's :) |
157 |
s/(\S+)\s+(\S+)\s+(.*)/$1\t$2\t$3/; |
158 |
} |
159 |
|
160 |
if (my ($id1, $id2, @l) = split /\t+/) { |
161 |
push @l, '""' if $newer_rh_format; |
162 |
my ($subid1, $subid2) = ('ffff', 'ffff'); |
163 |
($subid1, $subid2, @l) = @l if @l > 2; |
164 |
@l == 1 || @l == 2 or die "$f:$line: bad number of fields " . (int @l) . " (in $_)\n"; |
165 |
my ($module, $text) = @l; |
166 |
|
167 |
my $class = $text =~ /(.*?)|/; |
168 |
my $id1_ = $rm_quote_silent->($id1); |
169 |
if (defined $text && $class{$id1_}) { |
170 |
print STDERR "$f:$line: class $id1_ named both $class and $class{$id1_}, taking $class{$id1_}\n"; |
171 |
$class{$id1_} ||= $1; |
172 |
$text =~ s/(.*?)|/$class{$id1_}|/; |
173 |
} |
174 |
|
175 |
$module =~ s/\.o$//; |
176 |
$module = '"unknown"' if dummy_module($module); |
177 |
$module = '"unknown"' if $id1 eq '0x1011' && $id2 eq '0x0004'; |
178 |
# known errors in redhat's pcitable |
179 |
# these are pci to pci bridge |
180 |
$module = '"yenta_socket"' if $module =~ /i82365/; |
181 |
my $id = join '', map { |
182 |
s/^0x//; |
183 |
length == 4 or error("$f:$line: bad number $_"); |
184 |
lc($_); |
185 |
} $id1, $id2, $subid1, $subid2; |
186 |
$drivers{$id} && $strict and error("$f:$line: multiple entry for $id (skipping $module $text)"); |
187 |
$drivers{$id} ||= [ $rm_quote->($module), defined($text) ? $rm_quote->($text) : undef, $line ]; |
188 |
} else { |
189 |
die "$f:$line: bad line\n"; |
190 |
} |
191 |
} |
192 |
\%drivers; |
193 |
} |
194 |
|
195 |
sub read_kernel_aliasmap { |
196 |
my ($f) = @_; |
197 |
my %drivers; |
198 |
if (!$f || $f eq '/dev/null') { |
199 |
$f = find { -e $_ } map { "$_/dkms-modules-info/dkms-modules.alias" } qw(. ..); |
200 |
} |
201 |
foreach (cat_($f)) { |
202 |
# too bad nvidia driver doesn't list its ids... |
203 |
next if !/alias pci.* fglrx/; |
204 |
if (/alias pci:v0000(....)d0000(....)sv/) { |
205 |
my ($id1, $id2) = (lc($1), lc($2)); |
206 |
$drivers{ join '', map { /(....)$/ } $id1, $id2, '0xffff', '0xffff' } = [ $ati_driver ]; |
207 |
} |
208 |
} |
209 |
\%drivers; |
210 |
} |
211 |
|
212 |
|
213 |
sub read_kernel_pcimap { |
214 |
my ($f) = @_; |
215 |
my (%drivers, %driver_with_classes); |
216 |
foreach (cat_($f)) { |
217 |
chomp; |
218 |
next if /^#/ || /^\s*$/; |
219 |
my ($module, $id1, $id2, $subid1, $subid2) = split; |
220 |
next if $module eq 'pci'; |
221 |
($subid1, $subid2) = ("ffff", "ffff") if hex($subid1) == 0 && hex($subid2) == 0; |
222 |
if ($id2 =~ /ffff$/ && $id1 !~ /ffff$/) { |
223 |
# $driver_with_classes{$id1} = [ $module, '' ]; |
224 |
$driver_with_classes{join '', map { /(....)$/ } $id1, $id2, $subid1, $subid2} = [ $module, '' ]; |
225 |
} else { |
226 |
$drivers{join '', map { /(....)$/ } $id1, $id2, $subid1, $subid2} = [ $module, '' ]; |
227 |
} |
228 |
} |
229 |
\%drivers, \%driver_with_classes; |
230 |
} |
231 |
|
232 |
sub read_kernel_usbmap { |
233 |
my ($f) = @_; |
234 |
my %drivers; |
235 |
foreach (cat_($f)) { |
236 |
chomp; |
237 |
next if /^#/ || /^\s*$/; |
238 |
my ($module, $flag, $id1, $id2) = split; |
239 |
hex($flag) == 3 or next; |
240 |
$drivers{join '', map { /(....)$/ } $id1, $id2, "ffff", "ffff"} = [ $module, '' ]; |
241 |
} |
242 |
\%drivers; |
243 |
} |
244 |
|
245 |
sub read_pciids { |
246 |
my ($f) = @_; |
247 |
my %drivers; |
248 |
my ($id1, $id2, $class, $line, %class); |
249 |
foreach (cat_($f)) { |
250 |
chomp; $line++; |
251 |
next if /^#/ || /^;/ || /^\s*$/; |
252 |
if (/^C\s/) { |
253 |
last; |
254 |
} elsif (my ($subid1, $subid2, $text) = /^\t\t(\S+)\s+(\S+)\s+(.+)/) { |
255 |
$text =~ s/\t/ /g; |
256 |
$id1 && $id2 or die "$f:$line: unexpected device\n"; |
257 |
$drivers{sprintf qq(%04x%04x%04x%04x), hex($id1), hex($id2), hex($subid1), hex($subid2)} = [ "unknown", "$class|$text" ]; |
258 |
} elsif (/^\t(\S+)\s+(.+)/) { |
259 |
($id2, $text) = ($1, $2); |
260 |
$text =~ s/\t/ /g; |
261 |
$id1 && $id2 or die "$f:$line: unexpected device\n"; |
262 |
$drivers{sprintf qq(%04x%04xffffffff), hex($id1), hex($id2)} = [ "unknown", "$class|$text" ]; |
263 |
} elsif (/^(\S+)\s+(.+)/) { |
264 |
$id1 = $1; |
265 |
$class = $class{$2} || $2; |
266 |
$class =~ s/(Advanced Micro Devices) \[AMD\]/$1/; |
267 |
} else { |
268 |
warn "bad line: $_\n"; |
269 |
} |
270 |
} |
271 |
\%drivers; |
272 |
} |
273 |
|
274 |
sub read_pcilst { |
275 |
my ($f) = @_; |
276 |
my %drivers; |
277 |
my ($class, $line, %class); |
278 |
foreach (cat_($f)) { |
279 |
chomp; $line++; |
280 |
next if /^#/ || /^;/ || /^\s*$/; |
281 |
if (/^\t\S/) { |
282 |
my ($id, undef, $module, $text) = split ' ', $_, 4 or die "bad line: $_\n"; |
283 |
$text =~ s/\t/ /g; |
284 |
$module = "unknown" if dummy_module($module); |
285 |
$drivers{"${id}ffffffff"} = [ $module, "$class|$text" ]; |
286 |
} elsif (/^(\S+)\s+(.*)/) { |
287 |
$class = $class{$2} || $2; |
288 |
} else { |
289 |
die "bad line: $_\n"; |
290 |
} |
291 |
} |
292 |
\%drivers; |
293 |
} |
294 |
|
295 |
sub read_pcitablepm { |
296 |
my ($f) = @_; |
297 |
eval cat_($f); |
298 |
my %drivers; |
299 |
|
300 |
%pci_probing::pcitable::ids or die; |
301 |
while (my ($k, $v) = each %pci_probing::pcitable::ids) { |
302 |
$drivers{sprintf qq(%08xffffffff), $k >> 32} = [ $v->[1], $v->[0] ]; |
303 |
} |
304 |
\%drivers; |
305 |
} |
306 |
|
307 |
sub read_hwd { |
308 |
my ($f) = @_; |
309 |
my %drivers; |
310 |
foreach (cat_($f)) { |
311 |
next if /^\s*#/; |
312 |
chomp; |
313 |
my ($id1, $id2, $_class, $module, $_undef, $descr) = /(....):(....)\s+(\S+)\s+(\S+)(\s+(.*))/ or next; |
314 |
$drivers{"$id1${id2}ffffffff"} = [ $module, $descr ]; |
315 |
} |
316 |
\%drivers; |
317 |
} |
318 |
|
319 |
sub read_hwinfo_x11 { |
320 |
my ($f) = @_; |
321 |
|
322 |
my (%drivers, %e, %vendors, $line); |
323 |
foreach (cat_($f)) { |
324 |
$line++; |
325 |
s/\s*$//; |
326 |
if (my ($add, $name, $val) = /^([ &])(\w+)\.id\s+(.*)/) { |
327 |
if (!$add) { |
328 |
warn "read_hwinfo_x11:$line: unused %e\n" if %e; |
329 |
%e = (); |
330 |
} |
331 |
if ($val =~ /^pci\s+0x([0-9a-f]{4})/i) { |
332 |
$val = hex $1; |
333 |
} else { |
334 |
warn "read_hwinfo_x11:$line: weird value $val\n"; |
335 |
} |
336 |
$e{$name} = $val; |
337 |
} elsif (/^\+vendor\.name\s+(.*)/) { |
338 |
$vendors{$e{vendor}} = $1; |
339 |
} elsif (/^\+(?:sub)?device\.name\s+(.*)/) { |
340 |
$e{name} = $1; |
341 |
} elsif (my ($driver) = /^\+driver\.xfree\s+(.*)/) { |
342 |
if (exists $e{vendor} && exists $e{device}) { |
343 |
my $vendor = $vendors{$e{vendor}}; |
344 |
my $module = $driver =~ /^4\|(\w+)/ ? "Driver:$1" : "Card:$driver"; |
345 |
$drivers{sprintf qq(%04x%04x%04x%04x), $e{vendor}, $e{device}, |
346 |
$e{subvendor} || 0xffff, $e{subdevice} || 0xffff} = [ $module, "$vendor|$e{name}" ]; |
347 |
} else { |
348 |
warn "read_hwinfo_x11:$line: $driver but no vendor or no device\n"; |
349 |
} |
350 |
} elsif (/^$/) { |
351 |
%e = (); |
352 |
} elsif (/^\+driver\.xfree\.config/) { |
353 |
# drop |
354 |
} else { |
355 |
warn "read_hwinfo_x11:$line: unknown line $_\n"; |
356 |
} |
357 |
} |
358 |
\%drivers; |
359 |
} |
360 |
|
361 |
sub read_begent_pcids_htm { |
362 |
my ($f) = @_; |
363 |
my %drivers; |
364 |
my $F; |
365 |
open $F, $f or die "can't open $f\n"; |
366 |
|
367 |
# drop until TBODY |
368 |
local $_; |
369 |
while (<$F>) { last if m|<TBODY>| } |
370 |
|
371 |
my $get_one = sub { map { scalar <$F> } 1 .. 6 }; |
372 |
my $from_h = sub { |
373 |
local $_ = lc $_[0]; |
374 |
/([0-9a-g]{4})h/ or die "$.: bad number $_\n"; |
375 |
$1; |
376 |
}; |
377 |
|
378 |
# drop first line |
379 |
$get_one->(); |
380 |
|
381 |
my ($cur_vendor, $cur_vendor_descr, $cur_id); |
382 |
|
383 |
while (1) { |
384 |
my ($tr, $vendor, $device, $sub, $text, $tr2) = map { m|<td>(.*)</td>| ? $1 : $_ } $get_one->(); |
385 |
last if $tr =~ m|</TBODY>|; |
386 |
$tr =~ m|<tr>| or die "$f:$.: bad <tr> line $tr\n"; |
387 |
$tr2 =~ m|</tr>| or die "$f:$.: bad </tr> line $tr2\n"; |
388 |
|
389 |
if ($vendor) { |
390 |
$device eq '-' && $sub eq '-' or die "$f:$.: bad vendor line\n"; |
391 |
$cur_vendor = $vendor; |
392 |
($cur_vendor_descr) = $text =~ m|<b>(.*)</b>| or die "$f:$.: vendor descr not bold\n"; |
393 |
} else { |
394 |
$cur_id = $device || $cur_id; |
395 |
my $sub_t = |
396 |
$sub ? do { |
397 |
$sub =~ /^rev / and next; # ignoring "rev " thingy |
398 |
if ($sub =~ /^(.....)$/) { |
399 |
'ffff' . $from_h->($sub); |
400 |
} else { |
401 |
my ($s1, $s2) = $sub =~ /^(....)(.....)$/ or die "$f:$.: bad subid $sub\n"; |
402 |
$from_h->($s2) . $from_h->($s1 . 'h'); |
403 |
} |
404 |
} : 'ffffffff'; |
405 |
|
406 |
$drivers{$from_h->($cur_vendor) . $from_h->($cur_id) . $sub_t} = [ 'unknown', "$cur_vendor_descr|$text" ]; |
407 |
} |
408 |
} |
409 |
\%drivers; |
410 |
} |
411 |
|
412 |
sub read_nvidia_readme { |
413 |
my ($f) = @_; |
414 |
my %drivers; |
415 |
my $section; |
416 |
my $card = $ENV{NVIDIA_CARD} ? $ENV{NVIDIA_CARD} : "NVIDIA_UNKNOWN"; |
417 |
foreach (cat_($f)) { |
418 |
chomp; |
419 |
last if $section > 3; |
420 |
if (!($section % 2)) { |
421 |
next unless /^\s+NVIDIA GPU product\s+Device PCI ID/; |
422 |
$section++; |
423 |
next; |
424 |
} |
425 |
if (/^\s*$/) { |
426 |
$section++; |
427 |
next; |
428 |
} |
429 |
next if /^\s+-+[\s-]+$/; |
430 |
my ($description, $id, $subid) = /^\s+(.+?)\s+0x(....)(?: 0x(....))?/; |
431 |
$id = "10de" . lc($id); |
432 |
$subid = $subid ? "10de" . lc($subid) : "ffffffff"; |
433 |
$drivers{$id . $subid} = [ "Card:$card", $description ]; |
434 |
} |
435 |
\%drivers; |
436 |
} |
437 |
|
438 |
sub read_fglrxko_pci_ids_h { |
439 |
my ($f) = @_; |
440 |
my %drivers; |
441 |
foreach (cat_($f)) { |
442 |
chomp; |
443 |
my ($id) = /^\s+FGL_ASIC_ID\(0x(....)\)/ or next; |
444 |
$drivers{"1002" . lc($id) . "ffffffff"} = [ $ati_driver_vesa, 'unknown' ]; |
445 |
} |
446 |
\%drivers; |
447 |
} |
448 |
|
449 |
sub read_rhd_id_c { |
450 |
my ($f) = @_; |
451 |
my %drivers; |
452 |
foreach (cat_($f)) { |
453 |
chomp; |
454 |
my ($id, $description) = /^\s+RHD_DEVICE_MATCH\(\s*0x(....).*\/\* (.*)\*\// or next; |
455 |
$drivers{"1002" . lc($id) . "ffffffff"} = [ $ati_rhd_only, $description ]; |
456 |
} |
457 |
\%drivers; |
458 |
} |
459 |
|
460 |
sub read_ati_pciids_csv { |
461 |
my ($f) = @_; |
462 |
my %drivers; |
463 |
foreach (cat_($f)) { |
464 |
chomp; |
465 |
my ($id, $description) = /^"0x(....)",.*,(?:"([^,]*)")?$/ or next; |
466 |
$drivers{"1002" . lc($id) . "ffffffff"} = [ $ati_driver, $description ]; |
467 |
} |
468 |
\%drivers; |
469 |
} |
470 |
|
471 |
# write in RedHat's pcitable old format (mdk one) |
472 |
sub write_pcitable { |
473 |
my ($drivers) = @_; |
474 |
foreach (sort keys %$drivers) { |
475 |
print to_string($_, $drivers->{$_}), "\n"; |
476 |
} |
477 |
} |
478 |
|
479 |
|
480 |
sub merge_entries_with_wildcards { |
481 |
my ($drivers, $classes) = @_; |
482 |
foreach (keys %$classes) { |
483 |
my ($vendor, $id, $subvendor, $subid); |
484 |
next unless ($vendor, $id, $subvendor, $subid) = /^([0-9a-f]{4,4})([0-9a-f]{4,4})/; |
485 |
|
486 |
# handle PCI_ANY_ID as PCI device ID: |
487 |
if ($vendor !~ /ffff$/ && $id =~ /ffff$/) { |
488 |
foreach my $old (keys %$drivers) { |
489 |
next if $old !~ /^$vendor/ || $drivers->{$old}[0] ne 'unknown'; |
490 |
# blacklist AGP for now; |
491 |
next if $classes->{$_}[0] =~ /agp/; |
492 |
# the following test would be better but still generates some wrong entries (the only real check is to check |
493 |
# PCI_CAP_ID_AGP at probing time): |
494 |
# next if $classes->{$_}[0] =~ /-agp/ && $drivers->{$old}[1] !~ /Bridge|Controller|Host/i; |
495 |
$drivers->{$old}[0] = $classes->{$_}[0]; # if $drivers->{$old}[0] eq "unknown"; |
496 |
} |
497 |
} |
498 |
} |
499 |
} |
500 |
|
501 |
sub merge { |
502 |
my ($drivers, $new, $classes) = @_; |
503 |
merge_entries_with_wildcards($drivers, $classes) if $wildcards; |
504 |
|
505 |
foreach (keys %$new) { |
506 |
next if $new->{$_}[0] =~ /parport_pc|i810_ng/; |
507 |
if ($drivers->{$_}) { |
508 |
if ($new->{$_}[0] ne "unknown") { |
509 |
if ($drivers->{$_}[0] eq "unknown" || $force || member($new->{$_}[0], @force_modules)) { |
510 |
$drivers->{$_}[0] = $new->{$_}[0]; |
511 |
} elsif ($drivers->{$_}[0] ne $new->{$_}[0]) { |
512 |
my $different = 1; |
513 |
$different = 0 if $new->{$_}[0] =~ /fb/; |
514 |
$different = 0 if $drivers->{$_}[0] =~ /^(Card|Server):/; |
515 |
$different = 0 if $drivers->{$_}[0] =~ /^ISDN:([^,]+)/ && $new->{$_}[0] eq $1; |
516 |
print STDERR "different($drivers->{$_}[0] $new->{$_}[0]): ", to_string($_, $drivers->{$_}), "\n" if $different; |
517 |
} |
518 |
} |
519 |
next if !$new->{$_}[1]; |
520 |
$drivers->{$_}[1] = $new->{$_}[1] if !$drivers->{$_}[1] || $drivers->{$_}[1] =~ /\|$/; |
521 |
} else { |
522 |
if (!/ffffffff$/ && $new->{$_}[0] eq "unknown") { |
523 |
# keep sub-entry with major-entry module |
524 |
# will be dropped if every subids have the same module |
525 |
# ie. if no subids already present have a different module than the main one |
526 |
if (/(........)/) { |
527 |
$new->{$_}[0] = $drivers->{$1 . 'ffffffff'}[0] || "unknown" |
528 |
if exists $drivers->{$1 . 'ffffffff'}; |
529 |
} |
530 |
} |
531 |
|
532 |
$drivers->{$_} = $new->{$_} |
533 |
# don't keep sub-entries with unknown drivers |
534 |
if $all || /ffffffff$/ || $new->{$_}[0] ne "unknown"; |
535 |
} |
536 |
} |
537 |
} |
538 |
|
539 |
sub cleanup_subids { |
540 |
my ($drivers) = @_; |
541 |
my (%l, %m); |
542 |
foreach (sort keys %$drivers) { |
543 |
my ($id, $subid) = /(........)(........)/; |
544 |
if ($l{$id}) { |
545 |
push @{$m{$id}}, $l{$id}, $subid; |
546 |
} else { |
547 |
$l{$id} = $subid; |
548 |
} |
549 |
} |
550 |
foreach my $id (keys %m) { |
551 |
my %modules; |
552 |
my $text; |
553 |
foreach my $subid (@{$m{$id}}) { |
554 |
my $e = $drivers->{"$id$subid"}; |
555 |
$modules{$e->[0]} = 1; |
556 |
$text = $e->[1] if length($e->[1]) > length($text) || $subid eq 'ffffffff'; # favour previous text |
557 |
} |
558 |
if (keys(%modules) == 1) { |
559 |
my ($module, undef) = each %modules; |
560 |
|
561 |
# remove others |
562 |
foreach my $subid (@{$m{$id}}) { |
563 |
delete $drivers->{"$id$subid"}; |
564 |
} |
565 |
# add a main one |
566 |
$drivers->{$id . 'ffffffff'} = [ $module, $text ]; |
567 |
} else { |
568 |
# print STDERR "keeping subids for $id ($text) because of ", join(", ", keys %modules), "\n"; |
569 |
} |
570 |
} |
571 |
} |
572 |
|
573 |
sub error { |
574 |
our $error = 1; |
575 |
print STDERR "$_[0]\n"; |
576 |
} |