/[soft]/drakx-kbd-mouse-x11/trunk/lib/Xconfig/card.pm
ViewVC logotype

Annotation of /drakx-kbd-mouse-x11/trunk/lib/Xconfig/card.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3925 - (hide annotations) (download)
Thu Apr 5 02:49:52 2012 UTC (12 years ago) by anssi
File size: 18084 byte(s)
Fix firmware handling (it is DRIVER which needs it, not DRIVER2)
1 dmorgan 391 package Xconfig::card; # $Id: card.pm 266355 2010-02-22 20:51:38Z pzanoni $
2    
3     use diagnostics;
4     use strict;
5    
6     use lib '/usr/lib/libDrakX';
7     use detect_devices;
8     use Xconfig::xfree;
9     use modules;
10     use common;
11     use interactive;
12     use log;
13     use run_program;
14    
15     my $lib = arch() =~ /x86_64/ ? "lib64" : "lib";
16    
17     sub modules_dir() { "/usr/$lib/xorg/modules" }
18    
19     my %VideoRams = (
20     256 => N_("256 kB"),
21     512 => N_("512 kB"),
22     1024 => N_("1 MB"),
23     2048 => N_("2 MB"),
24     4096 => N_("4 MB"),
25     8192 => N_("8 MB"),
26     16384 => N_("16 MB"),
27     32768 => N_("32 MB"),
28     65536 => N_("64 MB or more"),
29     );
30    
31     my @xfree4_Drivers = ((arch() =~ /^sparc/ ? qw(sunbw2 suncg14 suncg3 suncg6 sunffb sunleo suntcx) :
32     qw(apm ark ast chips cirrus i128 i740 intel mga
33     neomagic newport nouveau nv openchrome psb qxl
34     rendition s3 s3virge savage siliconmotion sis sisusb
35     tdfx tga trident tseng vesa vmware xgi xgixp)),
36     if_(arch() =~ /i.86/, qw(geode)),
37     qw(ati glint fbdev));
38    
39     sub from_raw_X {
40     my ($raw_X) = @_;
41    
42     my ($device, @cards) = $raw_X->get_devices or die "no card configured";
43    
44     my $card = {
45     use_DRI_GLX => eval { any { /dri/ } $raw_X->get_modules },
46 tv 2391 DRI_GLX_SPECIAL => $device->{Driver} eq 'nvidia' && eval { member('glx', $raw_X->get_modules) },
47 dmorgan 391 %$device,
48     if_($device->{Driver} eq 'nvidia',
49     DriverVersion =>
50     readlink("$::prefix/etc/alternatives/gl_conf") =~ m!nvidia(.*)/! ? $1 : '97xx'),
51     if_(@cards, cards => \@cards),
52     };
53     add_to_card__using_Cards($card, $card->{BoardName});
54     $card;
55     }
56    
57     sub to_raw_X {
58     my ($card, $raw_X) = @_;
59    
60     my @cards = ($card, @{$card->{cards} || []});
61    
62     foreach (@cards) {
63 tv 2396 if (arch() =~ /ppc/ && member($_->{Driver}, qw(r128 radeon))) {
64 dmorgan 391 $_->{UseFBDev} = 1;
65     }
66     }
67    
68     $raw_X->set_devices(@cards);
69    
70     $raw_X->get_ServerLayout->{Xinerama} = { commented => !$card->{Xinerama}, Option => 1 }
71     if defined $card->{Xinerama};
72    
73     # cleanup deprecated previous special nvidia explicit libglx
74     $raw_X->remove_load_module(modules_dir() . "$_/libglx.so") foreach '/extensions/nvidia', '/extensions/nvidia_legacy', '/extensions';
75    
76     # remove ModulePath that we added
77     $raw_X->remove_ModulePath(modules_dir() . "/extensions/$_") foreach 'nvidia97xx', 'nvidia96xx', 'nvidia71xx', 'nvidia-current';
78     $raw_X->remove_ModulePath(modules_dir());
79     #- if we have some special ModulePath, ensure the last one is the standard ModulePath
80     $raw_X->add_ModulePath(modules_dir()) if $raw_X->get_ModulePaths;
81    
82     #- un-disable modules that we previously disabled
83     $raw_X->remove_disable_module('glx');
84     $raw_X->remove_disable_module('dri');
85    
86     $raw_X->remove_Section('DRI');
87    
88     $raw_X->remove_load_module('v4l') if $card->{use_DRI_GLX} && $card->{Driver} eq 'r128';
89     }
90    
91     sub probe() {
92     #-for Pixel tests
93     #- my @c = { driver => 'Card:Matrox Millennium G400 DualHead', description => 'Matrox|Millennium G400 Dual HeadCard' };
94     my @c = detect_devices::matching_driver__regexp('^(Card|Server|Driver):');
95    
96 anssi 1001 # prefer the boot device
97     my @cards = sort { $b->{boot_device} cmp $a->{boot_device} } map {
98 dmorgan 391 my @l = $_->{description} =~ /(.*?)\|(.*)/;
99     my $card = {
100     description => $_->{description},
101     VendorName => $l[0], BoardName => $l[1],
102     BusID => "PCI:$_->{pci_bus}:$_->{pci_device}:$_->{pci_function}",
103 anssi 1001 boot_device => chomp_(cat_($_->{sysfs_device} . "/boot_vga")) || 0,
104 dmorgan 391 };
105     if (my ($card_name) = $_->{driver} =~ /Card:(.*)/) {
106     $card->{BoardName} = $card_name;
107     add_to_card__using_Cards($card, $card_name);
108     } elsif ($_->{driver} =~ /Driver:(.*)/) {
109     $card->{Driver} = $1;
110     } else {
111     internal_error();
112     }
113     #dual head ATI card have a dummy DISPLAY_OTHER pci device because it
114     #was needed by Win2000, filter those out because we don't want to
115     #behave as if there were 2 video cards in the system in such cases
116 tv 3720 if_($_->{media_type} eq 'DISPLAY_VGA', $card);
117 dmorgan 391 } @c;
118    
119     if (@cards >= 2 && $cards[0]{card_name} eq $cards[1]{card_name} && $cards[0]{card_name} eq 'Intel 830 - 965') {
120     shift @cards;
121     }
122     #- take a default on sparc if nothing has been found.
123     if (arch() =~ /^sparc/ && !@cards) {
124     log::l("Using probe with /proc/fb as nothing has been found!");
125     my $s = cat_("/proc/fb");
126     @cards = { server => $s =~ /Mach64/ ? "Mach64" : $s =~ /Permedia2/ ? "3DLabs" : "Sun24" };
127     }
128    
129     #- disabling MULTI_HEAD when not available
130     foreach (@cards) {
131     $_->{MULTI_HEAD} && $_->{card_name} =~ /G[24]00/ or next;
132     if ($ENV{MATROX_HAL}) {
133     $_->{need_MATROX_HAL} = 1;
134     } else {
135     delete $_->{MULTI_HEAD};
136     }
137     }
138    
139     #- in case of only one cards, remove all BusID reference, this will avoid
140     #- need of change of it if the card is moved.
141     #- on many PPC machines, card is on-board, BusID is important, leave?
142     if (@cards == 1 && !$cards[0]{MULTI_HEAD} && arch() !~ /ppc/) {
143     delete $cards[0]{BusID};
144     }
145    
146     @cards;
147     }
148    
149     sub card_config__not_listed {
150     my ($in, $card, $options) = @_;
151    
152     my $vendors_regexp = join '|', map { quotemeta } (
153     '3Dlabs',
154     'AOpen', 'ASUS', 'ATI', 'Ark Logic', 'Avance Logic',
155     'Cardex', 'Chaintech', 'Chips & Technologies', 'Cirrus Logic', 'Compaq', 'Creative Labs',
156     'Dell', 'Diamond', 'Digital',
157     'ET', 'Elsa',
158     'Genoa', 'Guillemot', 'Hercules', 'Intel', 'Leadtek',
159     'Matrox', 'Miro', 'NVIDIA', 'NeoMagic', 'Number Nine',
160     'Oak', 'Orchid',
161     'RIVA', 'Rendition Verite',
162     'S3', 'Silicon Motion', 'STB', 'SiS', 'Sun',
163     'Toshiba', 'Trident',
164     'VideoLogic',
165     );
166     my $cards = readCardsDB("$ENV{SHARE_PATH}/ldetect-lst/Cards+");
167    
168     my @xf4 = grep { $options->{allowFB} || $::isStandalone || $_ ne 'fbdev' }
169     uniq(@xfree4_Drivers, map { $_->{Driver} } values %$cards);
170     my @list = (
171     (map { 'Vendor|' . $_ } keys %$cards),
172     (map { 'Xorg|' . $_ } @xf4),
173     );
174    
175     my $r = exists $cards->{$card->{BoardName}} ? "Vendor|$card->{BoardName}" : 'Xorg|vesa';
176     $in->ask_from_({ title => N("X server"),
177     messages => N("Choose an X server"),
178     interactive_help_id => 'configureX_card_list',
179     },
180     [ { val => \$r, separator => '|', list => \@list, sort => 1,
181     format => sub { $_[0] =~ /^Vendor\|($vendors_regexp)\s*-?(.*)/ ? "Vendor|$1|$2" :
182     $_[0] =~ /^Vendor\|(.*)/ ? "Vendor|Other|$1" : $_[0] } } ]) or return;
183    
184     log::explanations("Xconfig::card: $r manually chosen");
185    
186     $r eq "Vendor|$card->{BoardName}" and return 1; #- it is unchanged, do not modify $card
187    
188     my ($kind, $s) = $r =~ /(.*?)\|(.*)/;
189    
190     %$card = ();
191     if ($kind eq 'Vendor') {
192     add_to_card__using_Cards($card, $s);
193     } else {
194     $card->{Driver} = $s;
195     $card->{DRI_GLX} = 0;
196     }
197     $card->{manually_chosen} = 1;
198     1;
199     }
200    
201     sub multi_head_choose {
202     my ($in, $_auto, @cards) = @_;
203    
204     my @choices = multi_head_choices('', @cards);
205    
206     my $tc = $choices[0];
207     if (@choices > 1) {
208     $tc = $in->ask_from_listf(N("Multi-head configuration"),
209     N("Your system supports multiple head configuration.
210     What do you want to do?"), sub { $_[0]{text} }, \@choices) or return;
211     }
212     $tc->{code} or die internal_error();
213     return $tc->{code}();
214     }
215    
216     sub configure_auto_install {
217     my ($raw_X, $do_pkgs, $old_X, $options) = @_;
218    
219     my $card = $old_X->{card} || {};
220    
221     if ($card->{card_name}) {
222     #- try to get info from given card_name
223     add_to_card__using_Cards($card, $card->{card_name});
224     if (!$card->{Driver}) {
225     log::l("bad card_name $card->{card_name}, using probe");
226     undef $card->{card_name};
227     }
228     }
229    
230     my ($boot_xdriver) = cat_("/proc/cmdline") =~ /.*\bxdriver=(\S+)/;
231    
232     $options->{freedriver} = 1 if $boot_xdriver eq 'free';
233    
234     if (!$card->{Driver} && $boot_xdriver && !member($boot_xdriver, 'auto', 'free')) {
235     log::explanations("using driver $boot_xdriver from kernel command line");
236     $card = {
237     Driver => $boot_xdriver,
238     description => "Set by boot parameter",
239     VendorName => "Custom",
240     BoardName => "Set by boot parameter",
241     };
242     if ($boot_xdriver =~ /^(nvidia.|fglrx)/) {
243     $card->{Driver} = "vesa";
244     $card->{Driver2} = $boot_xdriver;
245     }
246     }
247    
248     if (!$card->{Driver}) {
249     my @cards = probe();
250     my ($choice) = multi_head_choices($old_X->{Xinerama}, @cards);
251     $card = $choice ? $choice->{code}() : do {
252     log::explanations('no graphic card probed, try providing one using $o->{card}{Driver} or $o->{card}{card_name}. Defaulting...');
253     { Driver => $options->{allowFB} ? 'fbdev' : 'vesa' };
254     };
255     }
256    
257     install_server($card, $options, $do_pkgs, undef) or return;
258     $card = configure_Driver2($card, undef);
259    
260     Xconfig::various::various_auto_install($raw_X, $card, $old_X);
261     set_glx_restrictions($card);
262    
263     if ($card->{needVideoRam} && !$card->{VideoRam}) {
264     $card->{VideoRam} = $options->{VideoRam_probed} || 4096;
265     log::explanations("argh, I need to know VideoRam! Taking " . ($options->{probed_VideoRam} ? "the probed" : "a default") . " value: VideoRam = $card->{VideoRam}");
266     }
267     to_raw_X($card, $raw_X);
268     $card;
269     }
270    
271     sub configure {
272     my ($in, $raw_X, $do_pkgs, $auto, $options) = @_;
273    
274     my @cards = probe();
275     @cards or @cards = {};
276    
277     if (!$cards[0]{Driver}) {
278     if ($options->{allowFB}) {
279     $cards[0]{Driver} = 'fbdev';
280     }
281     }
282     if (!$auto || !$cards[0]{Driver}) {
283     card_config__not_listed:
284     card_config__not_listed($in, $cards[0], $options) or return;
285     }
286    
287     my $card = multi_head_choose($in, $auto, @cards) or return;
288    
289     install_server($card, $options, $do_pkgs, $in) or goto card_config__not_listed;
290    
291     $card = configure_Driver2($card, $in);
292    
293     Xconfig::various::various($in, $raw_X, $card, $options, $auto);
294     set_glx_restrictions($card);
295    
296     if ($card->{needVideoRam} && !$card->{VideoRam}) {
297     $card->{VideoRam} = (find { $_ <= $options->{VideoRam_probed} } reverse ikeys %VideoRams) || 4096;
298     $in->ask_from('', N("Select the memory size of your graphics card"),
299     [ { val => \$card->{VideoRam},
300     type => 'list',
301     list => [ ikeys %VideoRams ],
302     format => sub { translate($VideoRams{$_[0]}) },
303     not_edit => 0 } ]) or return;
304     }
305    
306     to_raw_X($card, $raw_X);
307     $card;
308     }
309    
310     sub install_server {
311     my ($card, $options, $do_pkgs, $o_in) = @_;
312    
313     my @packages;
314    
315     if ($options->{freedriver}) {
316     delete $card->{Driver2};
317     }
318    
319     if ($card->{Driver2}) {
320     require Xconfig::proprietary;
321     Xconfig::proprietary::handle_DRIVER2_NO_SSE($card);
322     my @pkgs = Xconfig::proprietary::pkgs_for_Driver2($card->{Driver2}, $do_pkgs);
323     if (@pkgs && (!$o_in || $o_in->ask_yesorno('', formatAlaTeX(N("There is a proprietary driver available for your video card which may support additional features.
324     Do you wish to use it?")), 1))) {
325     push @packages, @pkgs;
326     } else {
327     delete $card->{Driver2};
328     }
329     }
330    
331 anssi 3925 Xconfig::proprietary::handle_FIRMWARE($do_pkgs, $card);
332    
333     # handle_FIRMWARE could've changed $card->{Driver}
334     my @must_have = "x11-driver-video-$card->{Driver}";
335    
336 dmorgan 391 $do_pkgs->ensure_are_installed([ @must_have, @packages ], 1) or
337     @must_have == listlength($do_pkgs->are_installed(@must_have))
338     or return;
339    
340     if ($card->{need_MATROX_HAL}) {
341     require Xconfig::proprietary;
342     Xconfig::proprietary::install_matrox_hal($::prefix);
343     }
344     1;
345     }
346    
347     sub configure_Driver2 {
348     my ($card, $o_in) = @_;
349    
350     if ($card->{Driver2}) {
351     require Xconfig::proprietary;
352     if (my $card2 = Xconfig::proprietary::may_use_Driver2($card)) {
353     $card = $card2;
354     } else {
355     $o_in and $o_in->ask_warn('', formatAlaTeX(N("The proprietary driver was not properly installed, defaulting to free software driver.")));
356     log::l("defaulting to free software driver");
357     }
358     }
359    
360     libgl_config_and_more($card);
361     $card;
362     }
363    
364     #- configures which libGL.so.1 to use, using update-alternatives
365     #- it also configures nvidia_drv.so (using a slave alternative, cf "update-alternatives --display gl_conf")
366     sub libgl_config_and_more {
367     my ($card) = @_;
368    
369     if ($card->{Driver} eq 'nvidia') {
370     $card->{DriverVersion} or internal_error("DriverVersion should be set for driver nvidia!");
371     }
372    
373     #- ensure old deprecated conf files are not there anymore
374     unlink("/etc/ld.so.conf.d/$_.conf") foreach 'nvidia', 'nvidia_legacy', 'ati';
375    
376     my %files = (
377     fglrx => "/etc/ld.so.conf.d/GL/ati$card->{DriverVersion}.conf",
378     nvidia => "/etc/nvidia$card->{DriverVersion}/ld.so.conf",
379     psb => "/etc/ld.so.conf.d/GL/libdrm-psb.conf",
380     );
381     my $wanted = $files{$card->{Driver}} || '/etc/ld.so.conf.d/GL/standard.conf';
382     my $link = "$::prefix/etc/alternatives/gl_conf";
383     my $need_run_ldconfig = readlink($link) ne $wanted;
384     -e "$::prefix$wanted" or log::l("ERROR: $wanted does not exist, linking $link to it anyway");
385     common::symlinkf_update_alternatives('gl_conf', $wanted);
386     if ($need_run_ldconfig) {
387     log::explanations("ldconfig will be run because the GL library was switched to $wanted");
388     run_program::rooted($::prefix, 'ldconfig', '-X');
389     }
390    
391     if (member($card->{Driver}, 'fglrx', 'nvidia')) {
392     log::l("workaround buggy fglrx/nvidia driver: make dm restart xserver (#29550, #38297)");
393     eval { common::update_gnomekderc_no_create("$::prefix/etc/kde/kdm/kdmrc", 'X-:0-Core' => (
394     TerminateServer => "true",
395     )) };
396     eval { update_gnomekderc("$::prefix/etc/X11/gdm/custom.conf", daemon => (
397     AlwaysRestartServer => "true",
398     )) };
399     }
400     }
401    
402     sub multi_head_choices {
403     my ($want_Xinerama, @cards) = @_;
404     my @choices;
405    
406     my $has_multi_head = @cards > 1 || @cards && $cards[0]{MULTI_HEAD} > 1;
407     my $disable_multi_head = any {
408     $_->{Driver} or log::explanations("found card $_->{description} not supported by XF4, disabling multi-head support");
409     !$_->{Driver};
410     } @cards;
411    
412     if ($has_multi_head && !$disable_multi_head) {
413     my $configure_multi_head = sub {
414    
415     #- special case for multi head card using only one BusID.
416     @cards = map {
417     map_index { { Screen => $::i, %$_ } } ($_) x ($_->{MULTI_HEAD} || 1);
418     } @cards;
419    
420     my $card = shift @cards; #- assume good default.
421     $card->{cards} = \@cards;
422     $card->{Xinerama} = $_[0];
423     $card;
424     };
425     my $independent = { text => N("Configure all heads independently"), code => sub { $configure_multi_head->('') } };
426     my $xinerama = { text => N("Use Xinerama extension"), code => sub { $configure_multi_head->(1) } };
427     push @choices, $want_Xinerama ? ($xinerama, $independent) : ($independent, $xinerama);
428     }
429    
430     foreach my $c (@cards) {
431     push @choices, { text => N("Configure only card \"%s\"%s", $c->{description}, $c->{BusID} && " ($c->{BusID})"),
432     code => sub { $c } };
433     }
434     @choices;
435     }
436    
437     sub set_glx_restrictions {
438     my ($card) = @_;
439    
440     #- 3D acceleration configuration for XFree 4 using DRI, this is enabled by default
441     #- but for some there is a need to specify VideoRam (else it will not run).
442     if ($card->{use_DRI_GLX}) {
443     $card->{needVideoRam} = 1 if $card->{description} =~ /Matrox.* G[245][05]0/;
444     ($card->{needVideoRam}, $card->{VideoRam}) = (1, 16384)
445     if $card->{card_name} eq 'Intel 810 / 815';
446    
447     #- hack for ATI Rage 128 card using a bttv or peripheral with PCI bus mastering exchange
448     #- AND using DRI at the same time.
449     if ($card->{card_name} eq 'ATI Rage 128 TV-out') {
450     $card->{Options}{UseCCEFor2D} = bool2text(detect_devices::probe_category('multimedia/tv'));
451     }
452     }
453     }
454    
455     sub add_to_card__using_Cards {
456     my ($card, $name) = @_;
457     my $cards = readCardsDB("$ENV{SHARE_PATH}/ldetect-lst/Cards+");
458     add2hash($card, $cards->{$name});
459     $card->{BoardName} = $card->{card_name};
460    
461     $card;
462     }
463    
464     #- needed for bad cards not restoring cleanly framebuffer, according to which version of Xorg are used.
465     sub check_bad_card {
466     my ($card) = @_;
467     my $bad_card = $card->{BAD_FB_RESTORE};
468 tv 2391 $bad_card ||= member($card->{Driver}, qw(intel fbdev));
469 dmorgan 391 $bad_card ||= member($card->{Driver}, 'nvidia', 'vmware') if !$::isStandalone; #- avoid testing during install at any price.
470    
471     log::explanations("the graphics card does not like X in framebuffer") if $bad_card;
472    
473 tv 2394 #- avoid testing during install at any price:
474     if (!$bad_card && !$::isStandalone) {
475     $bad_card = member($card->{Driver}, qw(ati intel nouveau));
476     log::explanations("the graphics card does not like using KMS in framebuffer") if $bad_card;
477     }
478    
479 dmorgan 391 !$bad_card;
480     }
481    
482     sub readCardsDB {
483     my ($file) = @_;
484     my ($card, %cards);
485    
486     my $F = openFileMaybeCompressed($file);
487    
488     my $lineno = 0;
489     my ($cmd, $val);
490     my $fs = {
491     NAME => sub {
492     $cards{$card->{card_name}} = $card if $card;
493     $card = { card_name => $val };
494     },
495     SEE => sub {
496     my $c = $cards{$val} or die "Error in database, invalid reference $val at line $lineno";
497     add2hash($card, $c);
498     },
499     LINE => sub { $val =~ s/^\s*//; $card->{raw_LINES} .= "$val\n" },
500     CHIPSET => sub { $card->{Chipset} = $val },
501     DRIVER => sub { $card->{Driver} = $val },
502 anssi 3925 DRIVER_NO_FIRMWARE => sub { $card->{DRIVER_NO_FIRMWARE} = $val },
503 dmorgan 391 DRIVER2 => sub { $card->{Driver2} = $val },
504 tv 2576 DRIVER2_NEEDS_SSE => sub { $card->{DRIVER2_NEEDS_SSE} = 1 },
505 dmorgan 391 DRIVER2_NO_SSE => sub { $card->{DRIVER2_NO_SSE} = $val },
506 tv 2577 FIRMWARE => sub { $card->{FIRMWARE} = $val },
507 dmorgan 391 NEEDVIDEORAM => sub { $card->{needVideoRam} = 1 },
508     DRI_GLX => sub { $card->{DRI_GLX} = 1 if $card->{Driver} },
509     DRI_GLX_EXPERIMENTAL => sub { $card->{DRI_GLX_EXPERIMENTAL} = 1 if $card->{Driver} },
510     MULTI_HEAD => sub { $card->{MULTI_HEAD} = $val if $card->{Driver} },
511     BAD_FB_RESTORE => sub { $card->{BAD_FB_RESTORE} = 1 },
512     FB_TVOUT => sub { $card->{FB_TVOUT} = 1 },
513     UNSUPPORTED => sub { delete $card->{Driver} },
514     COMMENT => sub {},
515     };
516    
517     local $_;
518     while (<$F>) { $lineno++;
519     s/\s+$//;
520     /^#/ and next;
521     /^$/ and next;
522     /^END/ and do { $cards{$card->{card_name}} = $card if $card; last };
523    
524     ($cmd, $val) = /(\S+)\s*(.*)/ or next;
525    
526     my $f = $fs->{$cmd};
527    
528     $f ? $f->() : log::l("unknown line $lineno ($_)");
529     }
530     \%cards;
531     }
532    
533     1;
534    

  ViewVC Help
Powered by ViewVC 1.1.30