3 # Hardware -- find modules for a thingy in /devices.
4 # Copyright (C) 2005 Erik van Konijnenburg
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 # Method: walk up the path, and for everything you recognise,
22 # prepend the appropriate module.
23 # As an example, for a usb-stick connected via a hub to a pci card,
24 # you'l need usb-storage, a usb protocol driver, and some usb module.
41 my @components = split (/\/+/, $path);
42 my $devicesPath = Conf::get ('sysDevices');
43 for my $i (0 .. $#components) {
44 my $abspath = $devicesPath
45 . "/" . join ('/', @components[0 .. $i]);
47 if ($abspath =~ m!/pci[0-9a-f]{4}:[0-9a-f]{2}$!) {
50 elsif (-f "$abspath/subsystem_vendor") {
51 # PCI function on a slot.
52 my $dev = PciDev->new (path => $abspath);
53 $modules = PciTab::find ($dev);
54 push @{$modules}, @{addPciSiblings ($abspath)};
57 elsif (-f "$abspath/bDeviceClass"
58 || -f "$abspath/bInterfaceClass")
61 # USB. Every component in the path
62 # "usb1/1-4/1-4.4/1-4.4:1.0" has either
63 # a deviceClass or interfaceClass attribute.
65 my $dev = UsbDev->new (path => $abspath);
66 $modules = UsbTab::find ($dev);
69 elsif ($abspath =~ m!/ide\d+$!) {
72 elsif ($abspath =~ m!/ide\d+/\d+\.\d+$!) {
74 my $dev = IdeDev->new (path => $abspath);
75 $modules = IdeDev::findModuleByIdeDev ($dev);
78 elsif ($abspath =~ m!/host\d+$!) {
79 # grouping of SCSI devices; harmless.
81 elsif ($abspath =~ m!/target\d+:\d+:\d+$!) {
82 # grouping of SCSI devices within a host
83 # (2.6.10 and later); harmless.
85 elsif ($abspath =~ m!/\d+:\d+:\d+:\d+$!
86 && -f "$abspath/scsi_level")
88 my $dev = ScsiDev->new (path => $abspath);
89 $modules = ScsiDev::findModuleByScsiDev ($dev);
93 # NOTE: We may want to avoid duplicate messages
94 Base::warning ("unrecognised device: $abspath");
97 if (defined ($modules)) {
98 push @{$result}, @{$modules};
106 # addPciSiblings -- probably a bug.
108 # Here's something odd: my test machine has an USB keyboard, connected
109 # via PCI. The same 8 ports are visible both as one 8-port EHCI
110 # controller and four 2-port UHCI controllers. The difference is not
111 # in the hardware, only in the protocol used to talk to the remote device.
112 # These are different PCI functions (0..7) in the same PCI slot (1d):
113 # 0000:00:1d.0 USB Controller: Intel ... USB UHCI #1 (rev 03)
114 # 0000:00:1d.1 USB Controller: Intel ... USB UHCI #2 (rev 03)
115 # 0000:00:1d.2 USB Controller: Intel ... USB UHCI #3 (rev 03)
116 # 0000:00:1d.3 USB Controller: Intel ... USB UHCI #4 (rev 03)
117 # 0000:00:1d.7 USB Controller: Intel ... USB2 EHCI Controller (rev 03)
119 # The keyboard shows up under the EHCI controller, a printer shows up
120 # under one of the UHCI controllers.
121 # If we load only the EHCI module, the UHCI-only printer causes some
122 # complaints, and the keyboard is not detected (unless you try to
123 # debug this via a serial line ...)
124 # If you load UHCI as well, the keyboard is detected flawlessly.
126 # We could interpret this as a bug in EHCI, and claim that a non-EHCI
127 # device on one of the ports should not interfere with detecting devices
128 # on other ports, but it's more productive to see this as an example of
129 # how some PCI devices work better if there's a driver for every
130 # function in the slot.
132 # (Or you could just add a special case to always add an UHCI driver
133 # after EHCI, but then you would have to consider OHCI as well, plus
134 # think about blacklisting and competing USB driver implementations.
135 # I'd rather not go there.)
137 # The kernel function pci_setup_device() uses the following format
138 # for PCI function directories in sysfs:
139 # "%04x:%02x:%02x.%d", domain, bus, slot, function.
141 # Given an absolute path to a PCI function directory, return a list
142 # of modules needed for all USB functions *except* the one specified by
143 # the path, but only if the path refers to a USB function.
145 # Limiting this behaviour to USB functions alone is desirable, given
146 # the existence of chips such as VT8366/A/7, that combine ISA, IDE,
147 # USB and multimedia in a single PCI slot.
149 sub addPciSiblings ($) {
152 if (! isUsb ($abspath)) {
156 my $dirName = Base::dirname ($abspath);
157 my $cur = Base::basename ($abspath);
159 if ($cur !~ /^([0-9a-f]{4}):([0-9a-f]{2}):([0-9a-f]{2})\.(\d)$/) {
160 Base::fatal ("Odd PCI directory in sysfs: $abspath");
167 #print "D $dirName, B $cur, d $domain b $bus s $slot f $function\n";
169 if (! opendir ($dir, $dirName)) {
170 Base::fatal ("can't open directory $dirName");
172 while (defined(my $entry = readdir($dir))) {
173 if ($entry !~ /^([0-9a-f]{4}):([0-9a-f]{2}):([0-9a-f]{2})\.(\d+)$/) {
176 if (! ($1 eq $domain && $2 eq $bus && $3 eq $slot
182 # OK, it's in my slot, and it isn't me.
183 # Add required modules if it's USB.
184 my $sibling = "$dirName/$entry";
185 if (isUsb ($sibling)) {
186 my $dev = PciDev->new (path => $sibling);
187 push @{$modules}, @{PciTab::find ($dev)};
190 if (! closedir ($dir)) {
191 Base::fatal ("could not read directory $dirName");
197 # isUsb -- given an absolute path into sysfs, true iff it controls a usb port.
203 if (! opendir ($dir, $abspath)) {
204 Base::fatal ("can't open directory $abspath");
206 while (defined(my $entry = readdir($dir))) {
207 if ($entry =~ /^usb\d+$/) {
211 if (! closedir ($dir)) {
212 Base::fatal ("could not read directory $abspath");