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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3925 - (show 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 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 DRI_GLX_SPECIAL => $device->{Driver} eq 'nvidia' && eval { member('glx', $raw_X->get_modules) },
47 %$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 if (arch() =~ /ppc/ && member($_->{Driver}, qw(r128 radeon))) {
64 $_->{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 # prefer the boot device
97 my @cards = sort { $b->{boot_device} cmp $a->{boot_device} } map {
98 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 boot_device => chomp_(cat_($_->{sysfs_device} . "/boot_vga")) || 0,
104 };
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 if_($_->{media_type} eq 'DISPLAY_VGA', $card);
117 } @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 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 $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 $bad_card ||= member($card->{Driver}, qw(intel fbdev));
469 $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 #- 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 !$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 DRIVER_NO_FIRMWARE => sub { $card->{DRIVER_NO_FIRMWARE} = $val },
503 DRIVER2 => sub { $card->{Driver2} = $val },
504 DRIVER2_NEEDS_SSE => sub { $card->{DRIVER2_NEEDS_SSE} = 1 },
505 DRIVER2_NO_SSE => sub { $card->{DRIVER2_NO_SSE} = $val },
506 FIRMWARE => sub { $card->{FIRMWARE} = $val },
507 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