#! /bin/sh # # The block between #B and #E will be used as help. #B # Formilux 0.1.8 - http://www.ant-computing.com/ # PCIDEV - PCI device drivers scanner version 0.5 # 2008/12/09 - Willy Tarreau - willy@ant-computing.com # May be redistributed under the terms of the GPL. # # usage : # pcidev [-vnm] [-c class/mask]* [path to modules.pcimap] # examples : # pcidev /lib/modules/`uname -r`/modules.pcimap # pcidev -v -n -m -c 0x200000/0xffff00 # # This program lists all pci devices, displays their IDs and the names of the # driver attached to each device, when available, or "##none##'. If an argument # is passed, it will be interpreted as the path to a modules.pcimap file. In # this case, the list of all possible modules for each device is appended at # the end of the line. If the "-n" argument is given, only modules that seem # not to have already been loaded will be. Note that with '-n', an implicit # path to modules.pcimap is used for the current kernel. If the "-m" argument # is given, those modules will be loaded through modprobe (verbosely if "-v" # is specified). "-c" limits modules to classes matching hex using hex # . Multiple -c may be used to look for multiple classes. # Eg: -c 0x020000/0xffff00 for Ethernet devices. #E MODPROBE=0 ONLYNEW=0 VERBOSE=0 ONLYCLASS=( ) ONLYMASK=( ) MAPFILE= NBCLASS=0 PCIDEVDIR=/proc/bus/pci KVER=$(uname -r) if [ ! -d "$PCIDEVDIR" ]; then echo "No PCI support on this host. Aborting." exit 1 fi while [ $# -gt 0 ]; do case $1 in -v) VERBOSE=1 ;; -n) ONLYNEW=1 ;; -c) oc=$2 om=${oc##*/} oc=${oc%%/*} ONLYCLASS[$NBCLASS]=$oc ONLYMASK[$NBCLASS]=$om (( NBCLASS++ )) shift ;; -m) MODPROBE=1 ONLYNEW=1 ;; -*) sed -e '/^#B/,/^#E/!d' --e 's/^#.\?//' < $0 exit 1 ;; *) break ;; esac shift done if [ $ONLYNEW -gt 0 ]; then MAPFILE=/lib/modules/`uname -r`/modules.pcimap fi if [ $# -gt 0 ]; then MAPFILE=$* fi # let's collect a list of all PCI devices in the form bus/slot.func pcidev=$PCIDEVDIR/*/* if [ $ONLYNEW -eq 0 ]; then echo "# module device(entry) class vid pid svid spid irq modules" fi oldlist=; xpid=; xvid=; xsvid=; xspid=; xclass= for device in $pcidev; do x=${device%??/??.?} dev=${device#$x} set -- `od -v -tx1 -An $device` # at first it semt it was possible not to display bridges # but cardbus bridges (at least) do have a driver. #if [ "${12}" = "06" ]; then # this is a bridge => no driver !! #continue; #fi vid=$2$1; pid=$4$3; class=${12}${11}${10}; svid=${46}${45}; spid=${48}${47} # now construct in a 16 bits entry for pci/devices from $dev, with # bus in $1, slot in $2, func in $3 set -- ${dev//[.\/]/ } entry=$(printf "%s%02x" "$1" $(((0x$2<<3)+0x$3))) # look for a registered device in /proc/bus/pci/devices set -- `grep "^$entry" $PCIDEVDIR/devices` irq=$[0x$3]; driver=${18} # maybe we asked to limit the class to a specific value/mask if [ $NBCLASS -gt 0 ]; then cid=0 while [ $cid -lt $NBCLASS ]; do (( (0x$class & ${ONLYMASK[$cid]}) == ${ONLYCLASS[$cid]} )) && break (( cid++ )) done [ $cid -lt $NBCLASS ] || continue fi # if we only list new modules and the module is the same as # previous one, don't list it (common with network cards) [ $ONLYNEW -gt 0 -a "$xclass" = "0x$class" -a \ "$xpid" = "0x$pid" -a "$xvid" = "0x$vid" -a \ "$xsvid" = "0x$svid" -a "$xspid" = "0x$spid" ] && continue xpid=0x$pid; xvid=0x$vid; xsvid=0x$svid; xspid=0x$spid; xclass=0x$class # look for modules supporting these devices. We exclude the rare modules # which pretend to support any vendor/product/subsys for PCI bridges because # they tend to pop up everywhere there is a bridge. if [ ! -z "$MAPFILE" ]; then list="" while read f1 f2 f3 f4 f5 f6 f7 rest; do [ "$f1" != "#" -a -n "$f7" ] || continue (( $f3 == 0xffffffff || $f3 == $xpid )) || continue (( $f2 == 0xffffffff || $f2 == $xvid )) || continue (( $f4 == 0xffffffff || $f4 == $xsvid )) || continue (( $f5 == 0xffffffff || $f5 == $xspid )) || continue (( ($xclass & $f7) == $f6 )) || continue (( $f2 != 0xffffffff || $f3 != 0xffffffff || $f4 != 0xffffffff || $f5 != 0xffffffff || $f6 != 0x00060400 )) || continue list="$list$f1 " done < $MAPFILE fi if [ -z "$driver" ]; then if [ $ONLYNEW -gt 0 ]; then if [ "$list" -a "$list" != "$oldlist" ]; then oldlist="$list" if [ $MODPROBE -gt 0 ]; then if [ -z "${KVER##2.6*}" ]; then # modprobe in 2.6 is smart enough to try several modules if [ $VERBOSE -gt 0 ]; then echo "modprobe $list" fi modprobe $list else for module in $list; do if [ $VERBOSE -gt 0 ]; then echo "modprobe $module" fi modprobe $module done fi else echo $list fi fi else echo "##none## $dev($entry) $class $vid $pid $svid $spid $irq $list" fi else if [ $ONLYNEW -eq 0 ]; then echo "$driver $dev($entry) $class $vid $pid $svid $spid $irq $list" fi fi done