summaryrefslogtreecommitdiffstats
path: root/perl-install/detect_devices.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/detect_devices.pm')
-rw-r--r--perl-install/detect_devices.pm324
1 files changed, 254 insertions, 70 deletions
diff --git a/perl-install/detect_devices.pm b/perl-install/detect_devices.pm
index 8f1fac97d..79bfedb71 100644
--- a/perl-install/detect_devices.pm
+++ b/perl-install/detect_devices.pm
@@ -1,25 +1,33 @@
-package detect_devices;
+package detect_devices; # $Id$
use diagnostics;
use strict;
+#-######################################################################################
+#- misc imports
+#-######################################################################################
use log;
-use common qw(:common :file);
+use common qw(:common :file :functional);
+use devices;
use c;
+#-#####################################################################################
+#- Globals
+#-#####################################################################################
+my @netdevices = map { my $l = $_; map { "$l$_" } (0..3) } qw(eth tr fddi plip);
+my %serialprobe = ();
+my $usb_interface = undef;
-my $scsiDeviceAvailable;
-my $CSADeviceAvailable;
-
-1;
-
+#-######################################################################################
+#- Functions
+#-######################################################################################
sub get {
- # Detect the default BIOS boot harddrive is kind of tricky. We may have IDE,
- # SCSI and RAID devices on the same machine. From what I see so far, the default
- # BIOS boot harddrive will be
- # 1. The first IDE device if IDE exists. Or
- # 2. The first SCSI device if SCSI exists. Or
- # 3. The first RAID device if RAID exists.
+ #- Detect the default BIOS boot harddrive is kind of tricky. We may have IDE,
+ #- SCSI and RAID devices on the same machine. From what I see so far, the default
+ #- BIOS boot harddrive will be
+ #- 1. The first IDE device if IDE exists. Or
+ #- 2. The first SCSI device if SCSI exists. Or
+ #- 3. The first RAID device if RAID exists.
map { &{$_->[0]}() ? &{$_->[1]}() : () }
[ \&hasIDE, \&getIDE ],
@@ -27,52 +35,88 @@ sub get {
[ \&hasDAC960, \&getDAC960 ],
[ \&hasCompaqSmartArray, \&getCompaqSmartArray ];
}
-sub hds() { grep { $_->{type} eq 'hd' } get(); }
-sub cdroms() { grep { $_->{type} eq 'cdrom' } get(); }
+sub hds() { grep { $_->{type} eq 'hd' && ($::isStandalone || !isRemovableDrive($_)) } get(); }
+sub zips() { grep { $_->{type} =~ /.d/ && isZipDrive($_) } get(); }
+sub ide_zips() { grep { $_->{type} =~ /.d/ && isZipDrive($_) } getIDE(); }
+#-sub jazzs() { grep { $_->{type} =~ /.d/ && isJazDrive($_) } get(); }
+sub ls120s() { grep { $_->{type} =~ /.d/ && isLS120Drive($_) } get(); }
+sub usbfdus() { grep { $_->{type} =~ /.d/ && isUSBFDUDrive($_) } get(); }
+sub cdroms() {
+ my @l = grep { $_->{type} eq 'cdrom' } get();
+ if (my @l2 = IDEburners()) {
+ require modules;
+ modules::add_alias('scsi_hostadapter', 'ide-scsi');
+ my $nb = 1 + max(-1, map { $_->{device} =~ /scd (\d+)/x } @l);
+ foreach my $i (@l2) {
+ log::l("IDEBurner: $i->{device}");
+ my ($e) = grep { $_->{device} eq $i->{device} } @l;
+ $e->{device} = "scd" . $nb++;
+ }
+ }
+ @l;
+}
+sub burners { grep { isBurner($_->{device}) } cdroms() }
+sub IDEburners { grep { $_->{type} eq 'cdrom' && isBurner($_->{device}) } getIDE() }
+
+sub floppies() {
+ require modules;
+ my @ide = map { $_->{device} } ls120s() and modules::load("ide-floppy");
+ my @scsi = map { $_->{device} } usbfdus();
+ (@ide, @scsi, grep { tryOpen($_) } qw(fd0 fd1));
+}
+sub floppy { first(floppies()) }
+#- example ls120, model = "LS-120 SLIM 02 UHD Floppy"
+
+sub isBurner { my $f = tryOpen($_[0]); $f && c::isBurner(fileno($f)) }
+sub isZipDrive { $_[0]->{info} =~ /ZIP\s+\d+/ } #- accept ZIP 100, untested for bigger ZIP drive.
+#-sub isJazzDrive { $_[0]->{info} =~ /JAZZ?\s+/ } #- untested.
+sub isLS120Drive { $_[0]->{info} =~ /LS-?120|144MB/ }
+sub isUSBFDUDrive { $_[0]->{info} =~ /USB-?FDU/ }
+sub isRemovableDrive { &isZipDrive || &isLS120Drive || &isUSBFDUDrive } #-or &isJazzDrive }
sub hasSCSI() {
- defined $scsiDeviceAvailable and return $scsiDeviceAvailable;
- local *F;
- open F, "/proc/scsi/scsi" or log::l("failed to open /proc/scsi/scsi: $!"), return 0;
- foreach (<F>) {
- /devices: none/ and log::l("no scsi devices are available"), return $scsiDeviceAvailable = 0;
+ local *F; open F, "/proc/scsi/scsi" or return 0;
+ local $_;
+ while (<F>) {
+ /devices: none/ and log::l("no scsi devices are available"), return 0;
}
- log::l("scsi devices are available");
- $scsiDeviceAvailable = 1;
+#- log::l("scsi devices are available");
+ 1;
}
-sub hasIDE() { 1 }
+sub hasIDE() { -e "/proc/ide" }
sub hasDAC960() { 1 }
+sub hasCompaqSmartArray() { -r "/proc/array/ida0" }
-sub hasCompaqSmartArray() {
- defined $CSADeviceAvailable and return $CSADeviceAvailable;
- -r "/proc/array/ida0" or log::l("failed to open /proc/array/ida0: $!"), return $CSADeviceAvailable = 0;
- log::l("Compaq Smart Array controllers available");
- $CSADeviceAvailable = 1;
+sub isFloppyOrHD {
+ my ($dev) = @_;
+ require partition_table_raw;
+ my $geom = partition_table_raw::get_geometry(devices::make($dev));
+ $geom->{totalsectors} < 10 << 11 ? 'floppy' : 'hd';
}
sub getSCSI() {
my @drives;
my ($driveNum, $cdromNum, $tapeNum) = qw(0 0 0);
- my $err = sub { chop; log::l("unexpected line in /proc/scsi/scsi: $_"); error() };
+ my $err = sub { chop; die "unexpected line in /proc/scsi/scsi: $_"; };
local $_;
local *F;
- open F, "/proc/scsi/scsi" or return &$err();
- $_ = <F>; /^Attached devices:/ or return &$err();
+ open F, "/proc/scsi/scsi" or die "failed to open /proc/scsi/scsi";
+ local $_ = <F>; /^Attached devices:/ or return &$err();
while ($_ = <F>) {
my ($id) = /^Host:.*?Id: (\d+)/ or return &$err();
$_ = <F>; my ($vendor, $model) = /^\s*Vendor:\s*(.*?)\s+Model:\s*(.*?)\s+Rev:/ or return &$err();
$_ = <F>; my ($type) = /^\s*Type:\s*(.*)/ or &$err();
my $device;
- if ($type =~ /Direct-Access/) {
- $type = 'hd';
+ if ($type =~ /Direct-Access/) { #- what about LS-120 floppy drive, assuming there are Direct-Access...
$device = "sd" . chr($driveNum++ + ord('a'));
+ $type = isFloppyOrHD($device);
} elsif ($type =~ /Sequential-Access/) {
- $type = 'tape';
$device = "st" . $tapeNum++;
+ $type = 'tape';
} elsif ($type =~ /CD-ROM/) {
- $type = 'cdrom';
$device = "scd" . $cdromNum++;
+ $type = 'cdrom';
}
$device and push @drives, { device => $device, type => $type, info => "$vendor $model", id => $id, bus => 0 };
}
@@ -82,10 +126,11 @@ sub getSCSI() {
sub getIDE() {
my @idi;
- -r "/proc/ide" or die "sorry, /proc/ide not available, seems like you have a pre-2.2 kernel\n => not handled yet :(";
+ #- what about a system with absolutely no IDE on it, like some sparc machine.
+ hasIDE() or return ();
- # Great. 2.2 kernel, things are much easier and less error prone.
- foreach my $d (glob_('/proc/ide/hd*')) {
+ #- Great. 2.2 kernel, things are much easier and less error prone.
+ foreach my $d (sort @{[glob_('/proc/ide/hd*')]}) {
my ($t) = chop_(cat_("$d/media"));
my $type = $ {{disk => 'hd', cdrom => 'cdrom', tape => 'tape', floppy => 'fd'}}{$t} or next;
my ($info) = chop_(cat_("$d/model")); $info ||= "(none)";
@@ -96,56 +141,195 @@ sub getIDE() {
@idi;
}
-
sub getCompaqSmartArray() {
my @idi;
my $f;
for (my $i = 0; -r ($f = "/proc/array/ida$i"); $i++) {
- local *F;
- open F, $f or die;
- local $_ = <F>;
- my ($name) = m|ida/(.*?):| or next;
- push @idi, { device => $name, info => "Compaq RAID logical disk", type => 'hd' };
+ foreach (cat_($f)) {
+ if (m|^(ida/.*?):|) {
+ push @idi, { device => $1, info => "Compaq RAID logical disk", type => 'hd' };
+ last;
+ }
+ }
}
@idi;
}
sub getDAC960() {
- my @idi;
- my $file = "/var/log/dmesg";
- -r $file or $file = "/tmp/syslog";
+ my %idi;
+
+ #- We are looking for lines of this format:DAC960#0:
+ #- /dev/rd/c0d0: RAID-7, Online, 17928192 blocks, Write Thru0123456790123456789012
+ foreach (syslog()) {
+ my ($device, $info) = m|/dev/(rd/.*?): (.*?),| or next;
+ $idi{$device} = { info => $info, type => 'hd', device => $device };
+ log::l("DAC960: $device ($info)");
+ }
+ values %idi;
+}
+
+sub getNet() {
+ grep { !($::isStandalone && /plip/) && c::hasNetDevice($_) } @netdevices;
+}
+
+# pci_probing::main::probe with $probe_type is unsafe for pci! (bug in kernel&hardware)
+# get_pcmcia_devices provides field "device", used in network.pm
+# => probeall with $probe_type is unsafe
+sub probeall {
+ my ($probe_type) = @_;
+ require pci_probing::main;
+ require sbus_probing::main;
+ require modules;
+ pci_probing::main::probe($probe_type), sbus_probing::main::probe(), modules::get_pcmcia_devices();
+}
+sub matching_desc {
+ my ($regexp) = @_;
+ grep { $_->{description} =~ /$regexp/i } probeall();
+}
+sub stringlist {
+ map { " $_->{description} ($_->{type} $_->{driver})" . ($_->{subid} ? sprintf(" SubVendor=0x%04x SubDevice=0x%04x", $_->{subvendor}, $_->{subid}) : '') } probeall(1);
+}
+sub check {
+ my ($l) = @_;
+ my $ok = $l->{driver} !~ /(unknown|ignore)/;
+ $ok or log::l("skipping $l->{description}, no module available (if you know one, please mail bugs\@linux-mandrake.com)");
+ $ok
+}
+
+
+sub tryOpen($) {
+ local *F;
+ sysopen F, devices::make($_[0]), c::O_NONBLOCK() and *F;
+}
+sub tryWrite($) {
local *F;
- open F, $file or die "Failed to open $file: $!";
-
- # We are looking for lines of this format:DAC960#0:
- # /dev/rd/c0d0: RAID-7, Online, 17928192 blocks, Write Thru0123456790123456789012
- foreach (<F>) {
- my ($devicename, $info) = m|/dev/rd/(.*?): (.*?),| or next;
- push @idi, { info => $info, type => 'hd', devicename => $devicename };
- log::l("DAC960: $devicename: $info");
+ sysopen F, devices::make($_[0]), 1 | c::O_NONBLOCK() and *F;
+}
+
+sub syslog {
+ -r "/tmp/syslog" and return map { /<\d+>(.*)/ } cat_("/tmp/syslog");
+ `dmesg`;
+}
+
+sub hasUsb {
+ my ($class, $prot) = @_;
+ foreach (cat_("/proc/bus/usb/devices")) {
+ if (/^P/ .. /^I/) {
+ my ($c, $p) = /Cls=(\d+).*Prot=(\d+)/;
+ $c == $class && ($prot < 0 || $prot == $p) and log::l("found usb $c $p"), return 1;
+ }
}
- @idi;
+ 0;
}
+sub hasUsbKeyboard { hasUsb(3, 1) }
+sub hasUsbMouse { hasUsb(3, 2) }
+sub hasUsbZip { hasUsb(8, -1) }
+sub hasSMP { c::detectSMP() }
-sub getNet() {
- # I should probably ask which device to use if multiple ones are available -- oh well :-(
- foreach (qw(eth0 tr0 plip0 plip1 plip2 fddi0)) {
- hasNetDevice($_) and log::l("$_ is available -- using it for networking"), return $_;
+sub hasUltra66 {
+ #- keep it BUT DO NOT USE IT as now included in kernel.
+ cat_("/proc/cmdline") =~ /(ide2=(\S+)(\s+ide3=(\S+))?)/ and return $1;
+
+ my @l = map { $_->{verbatim} } matching_desc('HPT|Ultra66') or return;
+
+ my $ide = sprintf "ide2=0x%x,0x%x ide3=0x%x,0x%x",
+ @l == 2 ?
+ (map_index { hex($_) + (odd($::i) ? 1 : -1) } map { (split ' ')[3..4] } @l) :
+ (map_index { hex($_) + (odd($::i) ? 1 : -1) } map { (split ' ')[3..6] } @l);
+
+ log::l("HPT|Ultra66: found $ide");
+ $ide;
+}
+
+sub whatParport() {
+ my @res =();
+ foreach (0..3) {
+ my $elem = {};
+ local *F; open F, "/proc/parport/$_/autoprobe" or next;
+ local $_;
+ while (<F>) { $elem->{$1} = $2 if /(.*):(.*);/ }
+ push @res, { port => "/dev/lp$_", val => $elem};
+ }
+ @res;
+}
+
+sub whatUsbport() {
+ my ($i, $elem, @res) = (0, {});
+ local *F; open F, "/proc/bus/usb/devices" or return;
+ local $_;
+ while (<F>) {
+ $elem->{$1} = $2 if /S:\s+(.*)=(.*\S)/;
+ if (/I:.*Driver=(printer|usblp)/ && $elem->{Manufacturer} && $elem->{Product}) {
+ my $MF = ${{ 'Hewlett-Packard' => 'HP' }}{$elem->{Manufacturer}} || $elem->{Manufacturer};
+ push @res, { port => "/dev/usb/lp$i", val => { CLASS => 'PRINTER',
+ MODEL => $elem->{Product},
+ MANUFACTURER => $elem->{Manufacturer},
+ DESCRIPTION => "$MF $elem->{Product}",
+ }};
+ $i++; $elem = {}; #- try next one, but blank what has been probed.
+ }
}
- undef;
+ @res;
}
-sub getPlip() {
- foreach (0..2) {
- hasNetDevice("plip$_") and log::l("plip$_ will be used for PLIP"), return "plip$_";
+
+#-CLASS:PRINTER;
+#-MODEL:HP LaserJet 1100;
+#-MANUFACTURER:Hewlett-Packard;
+#-DESCRIPTION:HP LaserJet 1100 Printer;
+#-COMMAND SET:MLC,PCL,PJL;
+sub whatPrinter() {
+ my @res = (whatParport(), whatUsbport());
+ grep { $_->{val}{CLASS} eq "PRINTER"} @res;
+}
+
+sub whatPrinterPort() {
+ grep { tryWrite($_)} qw(/dev/lp0 /dev/lp1 /dev/lp2 /dev/usb/lp0);
+}
+
+sub probeSerialDevices {
+ #- make sure the device are created before probing.
+ foreach (0..3) { devices::make("/dev/ttyS$_") }
+
+ #- for device already probed, we can safely (assuming device are
+ #- not moved during install :-)
+ #- include /dev/mouse device if using an X server.
+ -d "/var/lock" or mkdir "/var/lock", 0755;
+ -l "/dev/mouse" and $serialprobe{"/dev/" . readlink "/dev/mouse"} = undef;
+ foreach (keys %serialprobe) { m|^/dev/(.*)| and touch "/var/lock/LCK..$1" }
+
+ print STDERR "Please wait while probing serial ports...\n";
+ #- start probing all serial ports... really faster than before ...
+ #- ... but still take some time :-)
+ local *F; open F, "serial_probe 2>/dev/null |";
+ local $_;
+ my %current = (); while (<F>) {
+ $serialprobe{$current{DEVICE}} = { %current } and %current = () if /^\s*$/ && $current{DEVICE};
+ $current{$1} = $2 if /^([^=]+)=(.*?)\s*$/;
}
- undef;
+ close F;
+
+ foreach (values %serialprobe) {
+ $_->{DESCRIPTION} =~ /modem/i and $_->{CLASS} = 'MODEM'; #- hack to make sure a modem is detected.
+ $_->{DESCRIPTION} =~ /olitec/i and $_->{CLASS} = 'MODEM'; #- hack to make sure such modem gets detected.
+ log::l("probed $_->{DESCRIPTION} of class $_->{CLASS} on device $_->{DEVICE}");
+ }
+}
+
+sub probeSerial($) { $serialprobe{$_[0]} }
+
+sub hasModem($) {
+ $serialprobe{$_[0]} and $serialprobe{$_[0]}{CLASS} eq 'MODEM' and $serialprobe{$_[0]}{DESCRIPTION};
+}
+
+sub hasMousePS2 {
+ my $t; sysread(tryOpen($_[0]) || return, $t, 256) != 1 || $t ne "\xFE";
}
-sub hasNet() { goto &getNet }
-sub hasPlip() { goto &getPlip }
-sub hasEthernet() { hasNetDevice("eth0"); }
-sub hasTokenRing() { hasNetDevice("tr0"); }
-sub hasNetDevice($) { c::hasNetDevice($_[0]) }
+#-######################################################################################
+#- Wonderful perl :(
+#-######################################################################################
+1; #
+