pcidetect

Aus Mikiwiki
Version vom 10. Februar 2010, 02:56 Uhr von Michi (Diskussion | Beiträge)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Originalskript: http://www.linux-magazin.de/Service/Listings/2005/09/hwdetect/pcidetect

Die Variable SYSTEMMAP ist gemäss dem lokalen Host anzupassen! Ausserdem erscheint bei Skriptaufruf folgende Fehlermeldung.

/home/mik/bin/pcidetect: line 81: declare: `m=#': not a valid identifier




#!/bin/bash

#
# Pfade zu den benötigten Dateien
PCIIDS=pci.db      # PCI-ID-Liste von http://pciids.sourceforge.net/pci.db
PCIMAP=/lib/modules/`uname -r`/modules.pcimap
SYSTEMMAP=/boot/System.map

#
# Tabulator- und Newline-Zeichen als Variable, ist so leichter lesbar
Tab=$'\t'
Newline=$'\n'

#
# Wir benötigen Zugriff auf /proc/bus/pci, daher prüfen, ob es das Verzeichnis
# überhaupt gibt
if [ ! /sys/bus/pci -a ! -d /proc/bus/pci ]; then
  echo "/sys/bus/pci und /proc/bus/pci existieren nicht."
  exit 1
fi

#
# Die PCI-ID-Datenbank (http://pciids.sf.net/pci.db) einlesen
if [ -r "$PCIIDS" ]; then
  PCIIDCMD="cat $PCIIDS"
else
  PCIIDCMD="wget -q -O - http://pciids.sf.net/pci.db"
fi

# PCI-Modulliste (/lib/modules/[Kernel-Version]/modules.pcimap) und
# Kernel-Symbolliste (/boot/System.map) prüfen
if [ ! -r "$PCIMAP" -o ! -r "$SYSTEMMAP" ]; then
  echo "PCI-Modul-Liste oder System.map nicht gefunden."
  exit 1
fi

#
# PCI-ID-Liste zeilenweise einlesen
IFS="${Newline}"
for z in `eval ${PCIIDCMD}`; do
  # Die Spalten sind mit Tabs getrennt -- aufsplitten
  IFS="${Tab}"
  set -- $z

  # Das erste Zeichen unterscheidet Vendor- und Device-Einträge
  case "$1" in
    v)
      # Hersteller-Eintrag: Nur verifizierte Einträge erlauben ($4=0)
      if [ "$4" = "0" ]; then
        declare v${2}=$3
      fi
      ;;
    d)
      # Device-Eintrag
      declare d${2}=$3
      ;;
  esac
done

#
# PCI-Modul-Liste zeilenweise einlesen
IFS="${Newline}"
for z in `cat $PCIMAP`; do
  # Die Spalten sind mit (mehreren) Leerzeichen getrennt
  IFS=" "
  set -- $z

  # Spalte 2 und 3 enthalten Vendor-/Device-ID, 6 die Class-ID
  if [ "$2" = "0xffffffff" -a "$3" = "0xffffffff" ]; then
    # generischer Gerätetreiber für bestimmte Geräteklassen
    id="c${6:4:4}"
  elif [ "$3" = "0xffffffff" ]; then
    # generischer Gerätetreiber für alle Geräte des Herstellers
    id="m${2:6}"
  else
    id="m${2:6}${3:6}"
  fi
  
  if [ -z "${!id}" ]; then
    # Spalte 1 den Namen des Moduls
    declare ${id}="$1"
  else
    declare ${id}="${!id}${Tab}${1}"
  fi
done

#
# Liste der vom Kernel unterstützten Geräte zeilenweise einlesen
IFS="${Newline}"
for z in `cat $SYSTEMMAP`; do
  # Die Spalten sind mit Leerzeichen getrennt
  IFS="${Tab} "
  set -- $z

  # Symbole mit "__devicestr_" am Anfang der 3. Spalte herauslösen
  if [ "${3:0:12}" = "__devicestr_" ]; then
    # Der Device-String ist mit Unterstichen von der ID getrennt
    IFS="_"
    set -- $3
    # Der 4. Parameter ist die kombinierte Vendor- und Device-ID
    declare k${4}=1
  fi
done

IFS=",${Tab}${Newline}"
#
# /sys/bus/pci/devices/* respektive /proc/bus/pci/??/* nach Geräten scannen
if [ -e /sys/bus/pci/devices ]; then
  PCIDevices=/sys/bus/pci/devices/*
  Method="sysfs"
elif [ -e /proc/bus/pci ]; then
  PCIDevices=/proc/bus/pci/??/*
  Method="proc"
fi

# Geräte nacheinander bestimmen
for device in $PCIDevices; do
  if [ "$Method" = "sysfs" ]; then
    read Vendor < ${device}/vendor
    Vendor=${Vendor:2:4}
    read Device < ${device}/device
    Device=${Device:2:4}
    read Class < ${device}/class
    Class=${Class:2:4}
  elif [ "$Method" = "proc" ]; then
    # Vendor- und Device-ID auslesen und nach Hex wandeln
    Vendor=`hexdump -s 0 -n 2 -e '1/2 "%04x"' $device`
    Device=`hexdump -s 2 -n 2 -e '1/2 "%04x"' $device`
  
    # Class-ID: Teilt die Hardware in verschiedene Gruppen, 0x0200 sind
    # zum Beispiel Netzwerkkarten. Nachzulesen bei
    #   http://www.pcidatabase.com/pci_c_header.php
    # in der Struktur "PciClassCodeTable"
    Class=`hexdump -s 10 -n 2 -e '1/2 "%04x"' $device`
  fi
  
  # variable Variablennamen generieren
  v="v${Vendor}"             # Variablenname des Herstellernamens
  d="d${Vendor}${Device}"    # Variablenname der Gerätebeschreibung
  m="m${Vendor}${Device}"    # Variablenname des Kernel-Moduls
  g="m${Vendor}"             # Variablenname des generischen Kernel-Moduls
  k="k${Vendor}${Device}"    # Variablenname des Kernel-Symbols
  c="c${Class}"              # PCI-Geräteklasse

  echo "Hersteller:   ${!v}${Tab}[0x${Vendor}]"
  echo "Gerät:        ${!d}${Tab}[0x${Device}]"
  # echo "Klasse:       [0x${Class}]"

  if [ -n "${!m}" -o -n "${!g}" -o -n "${!c}" ]; then
    set -- ${!m} ${!g} ${!c}
    if [ "$#" -gt "1" ]; then
      echo "Kernel-Module: $*"
    else
      echo "Kernel-Modul: $1"
    fi
  elif [ -n "${!k}" ]; then
    echo "Vom Kernel unterstützt"
  else
    echo "Nicht unterstützt"
  fi
  echo
done