Rewrite pl_hwinit in Python.
authorDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Wed, 21 Nov 2007 02:32:06 +0000 (02:32 +0000)
committerDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Wed, 21 Nov 2007 02:32:06 +0000 (02:32 +0000)
conf_files/pl_hwinit

index 256fe6c..8654708 100755 (executable)
-#!/bin/sh
-
-pci_table=/etc/pl_pcitable
-
-loaded_module_list=/tmp/loadedmodules
-
-echo "pl_hwinit: loading applicable modules"
-
-echo > $loaded_module_list
-
-# this will contain lines of device_id:vendor_id (no 0x)
-system_devices=$(lspci -n | cut -d " " -f4)
-
-for device in $system_devices; do
-
-    # now vendor_id and device_id are broken apart
-    vendor_id=$(echo $device | cut -d ":" -f1)
-    device_id=$(echo $device | cut -d ":" -f2)
-
-    # either exactly match vendor:device, or a vendor:ffff (let the module
-    # figure out if it can be used for this device), or ffff:device
-    # (not sure if this is legal, but shows up in the pci map)
-    mods=$(grep -i "\($vendor_id:ffff\|$vendor_id:$device_id\|ffff:$device_id\)" \
-       $pci_table | cut -d " " -f1)
-
-    for module in $mods; do
-       if [ -n "$module" ]; then
-           echo "pl_hwinit: found and loading module $module"
-           /sbin/modprobe $module
-           echo $module >> $loaded_module_list
-       fi
-    done
-done
-
-# just in case, look for any modules that are ffff:ffff and load them
-mods=$(grep -i "ffff:ffff" $pci_table | cut -d " " -f1)
-for module in $mods; do
-    if [ -n "$module" ]; then
-       echo "pl_hwinit: found and loading wild module $module"
-       /sbin/modprobe $module
-    fi
-done
-
-# sd_mod won't get loaded automatically
-echo "pl_hwinit: loading sd_mod"
-/sbin/modprobe sd_mod
-
-# load usb_storage to support node conf files on flash disks
-echo "pl_hwinit: loading usb_storage"
-/sbin/modprobe usb_storage
-
-echo "pl_hwinit: loading floppy device driver"
-/sbin/modprobe floppy
-
-# always wait a bit between loading the usb drivers, and checking /sys/
-# for usb devices (this isn't necessarily for waiting for mass storage files,
-# that is done below)
-echo "pl_hwinit: waiting for usb system to initialize."
-/bin/sleep 10s
-
-# sometimes, flash devices take a while to initialize. in fact, the kernel
-# intentionally waits 5 seconds for a device to 'settle'. some take even longer
-# to show up. if there are any mass storage devices on the system, try to
-# delay until they come online, up to a max delay of 30s.
-
-# the way this will be done is to look for files in /sys/devices that are named
-# 'bInterfaceClass', these will be a list of the usb devices on the system, and
-# their primary usb device interface class ids. The base directory these files 
-# exist in will be the full path to the /sys/device entry for that device.
-# for each mass storage devices (they have an interface class value of 08),
-# we wait for a new symbolic link named 'driver' to exist in that directory,
-# indicating the kernel loaded a driver for that device.
-
-# usb interface class id for mass storage
-INTERFACE_CLASS_MASS_STORAGE="08"
-
-# how long to wait in seconds before continuing on if devices
-# aren't available
-MAX_USB_WAIT_TIME=30
-
-# low long in seconds to wait between checks
-PER_CHECK_USB_WAIT_TIME=5
-
-
-# find out if the device identified by the /sys dir has a module
-# loaded for it. check for a symlink in the dir named driver.
-function does_device_dir_have_driver()
-{
-    if [[ -h "$1/driver" ]]; then
-       return 1
-    else
-       return 0
-    fi
-}
-
-wait_dev_list=""
-for interface_class_file in `find /sys/devices -name 'bInterfaceClass'`; do
-    interface_class=`cat $interface_class_file`
-    if [[ "$interface_class" == $INTERFACE_CLASS_MASS_STORAGE ]]; then
-       wait_dev_list="$wait_dev_list "`dirname $interface_class_file`
-    fi
-done
-
-if [[ -n "$wait_dev_list" ]]; then
-    echo "pl_hwinit: found USB mass storage device(s). Attempting to wait"
-    echo "pl_hwinit: up to $MAX_USB_WAIT_TIME seconds for them to come online."
-
-    total_wait_time=0
-    success=0
-    while [[ $total_wait_time < $MAX_USB_WAIT_TIME ]]; do
-       
-       total_wait_time=$(($total_wait_time+$PER_CHECK_USB_WAIT_TIME))
-
-       echo "pl_hwinit: waiting $PER_CHECK_USB_WAIT_TIME seconds."
-       /bin/sleep $PER_CHECK_USB_WAIT_TIME
-
-       all_devices_online=1
-       for device_dir in $wait_dev_list; do
-           does_device_dir_have_driver $device_dir
-           if [[ "$?" -eq 0 ]]; then
-               all_devices_online=0
-           fi
-       done
-
-       if [[ $all_devices_online -eq 1 ]]; then
-           success=1
-           echo "pl_hwinit: looks like the devices are now online."
-           break;
-       else
-           echo "pl_hwinit: not all devices online yet, waiting..."
-       fi
-    done
-
-    if [[ $success -eq 1 ]]; then
-       echo "pl_hwinit: Succesfully waited for USB mass storage devices"
-       echo "pl_hwinit: to come online."
-    else
-       echo "pl_hwinit: One or more USB mass storage devices did not"
-       echo "pl_hwinit: initialize in time. Continuing anyway."
-    fi
-fi
-
+#!/usr/bin/python
+
+import sys
+import pypciscan
+import pypcimap
+import os
+import time
+
+def modprobe(module):
+    ret = os.system("/sbin/modprobe %s" % module)
+    return os.WEXITSTATUS(ret) == 0
+
+def main(argv):
+    if len(argv) == 0:
+        kernel = os.uname()[2]
+    else:
+        kernel = argv[0]
+
+    if os.path.exists(kernel):
+        path = kernel
+    else:
+        path = "/lib/modules/%s/modules.pcimap" % kernel
+
+    pcimap = pypcimap.PCIMap(path)
+    print "pl_hwinit: loading applicable modules"
+    devices = pypciscan.get_devices()
+    missing = []
+    for (slot, dev) in devices.iteritems():
+        modules = pcimap.get(dev)
+        if len(modules) == 0:
+            base = (dev[4] & 0xff00) >> 8
+            if base == 0x01 or base == 0x02:
+                # storage or network device, in that order
+                missing.append((slot, dev))
+        else:
+            # FIXME: This needs improved logic in the case of multiple matching modules
+            for module in modules:
+                modprobe(module)
+
+    # sd_mod won't get loaded automatically
+    print "pl_hwinit: loading sd_mod"
+    modprobe("sd_mod")
+
+    # load usb_storage to support node conf files on flash disks
+    print "pl_hwinit: loading usb_storage"
+    modprobe("usb_storage")
+
+    print "pl_hwinit: loading floppy device driver"
+    modprobe("floppy")
+
+    # always wait a bit between loading the usb drivers, and checking /sys/
+    # for usb devices (this isn't necessarily for waiting for mass storage files,
+    # that is done below)
+    print "pl_hwinit: waiting for usb system to initialize."
+    time.sleep(10)
+
+    # sometimes, flash devices take a while to initialize. in fact, the kernel
+    # intentionally waits 5 seconds for a device to 'settle'. some take even longer
+    # to show up. if there are any mass storage devices on the system, try to
+    # delay until they come online, up to a max delay of 30s.
+
+    # the way this will be done is to look for files in /sys/devices that are named
+    # 'bInterfaceClass', these will be a list of the usb devices on the system, and
+    # their primary usb device interface class ids. The base directory these files 
+    # exist in will be the full path to the /sys/device entry for that device.
+    # for each mass storage devices (they have an interface class value of 08),
+    # we wait for a new symbolic link named 'driver' to exist in that directory,
+    # indicating the kernel loaded a driver for that device.
+
+    # usb interface class id for mass storage
+    INTERFACE_CLASS_MASS_STORAGE = "08"
+
+    # how long to wait in seconds before continuing on if devices
+    # aren't available
+    MAX_USB_WAIT_TIME = 30
+
+    # low long in seconds to wait between checks
+    PER_CHECK_USB_WAIT_TIME = 5
+
+
+    # find out if the device identified by the /sys dir has a module
+    # loaded for it. check for a symlink in the dir named driver.
+    def does_device_dir_have_driver(device):
+        return os.path.exists(os.path.join(device, "driver"))
+
+    def filter_and_add(list, directory, files):
+        if ("bInterfaceClass" in files and
+            int(file(os.path.join(directory, "bInterfaceClass")).read(), 16) == INTERFACE_CLASS_MASS_STORAGE):
+            list.append(directory)
+
+    wait_dev_list = []
+    os.path.walk("/sys/devices", filter_and_add, wait_dev_list)
+
+    if len(wait_dev_list) > 0:
+        print "pl_hwinit: found USB mass storage device(s). Attempting to wait"
+        print "pl_hwinit: up to %d seconds for them to come online." % MAX_USB_WAIT_TIME
+
+        total_wait_time = 0
+        success = False
+        while total_wait_time < MAX_USB_WAIT_TIME:    
+            total_wait_time += PER_CHECK_USB_WAIT_TIME
+
+            print "pl_hwinit: waiting %d seconds." % PER_CHECK_USB_WAIT_TIME
+            time.sleep(PER_CHECK_USB_WAIT_TIME)
+
+            all_devices_online = True
+            for device in wait_dev_list:
+                if not does_device_dir_have_driver(device):
+                    all_devices_online = False
+
+            if all_devices_online:
+                success = True
+                print "pl_hwinit: looks like the devices are now online."
+                break
+            else:
+                print "pl_hwinit: not all devices online yet, waiting..."
+
+        if success:
+            print "pl_hwinit: Succesfully waited for USB mass storage devices"
+            print "pl_hwinit: to come online."
+        else:
+            print "pl_hwinit: One or more USB mass storage devices did not"
+            print "pl_hwinit: initialize in time. Continuing anyway."
+
+if __name__ == "__main__":
+    main(sys.argv[1:])