[freenos] r322 committed - Separated traversal of /dev/pci and execution of /etc/pci/$VENDOR:$DEV...

  • From: codesite-noreply@xxxxxxxxxx
  • To: freenos@xxxxxxxxxxxxx
  • Date: Tue, 18 Aug 2009 21:04:57 +0000

Revision: 322
Author: nieklinnenbank
Date: Tue Aug 18 13:59:35 2009
Log: Separated traversal of /dev/pci and execution of /etc/pci/$VENDOR:$DEVICE in PCIDetect.
This makes the PCIServer much more simple: it is now only responsible for
exporting PCI configuration space as files. Another utility PCIDetect traverses the directories in /dev/pci, corresponding to PCI busses, slots and functions, and
tries to execute /etc/pci/$VENDOR:$DEVICE for each detected device.

http://code.google.com/p/freenos/source/detail?r=322

Added:
 /trunk/srv/pci/PCIDetect.cpp
Modified:
 /trunk/srv/pci/PCIServer.cpp
 /trunk/srv/pci/PCIServer.h
 /trunk/srv/pci/SConscript

=======================================
--- /dev/null
+++ /trunk/srv/pci/PCIDetect.cpp        Tue Aug 18 13:59:35 2009
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2009 Niek Linnenbank
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+int readint(struct dirent *bus, struct dirent *slot,
+           struct dirent *func, const char *file)
+{
+    char path[256];
+    int fd, value = 0;
+
+    /* Construct target path. */
+    snprintf(path, sizeof(path), "/dev/pci/%s/%s/%s/%s",
+            bus->d_name, slot->d_name, func->d_name, file);
+
+    /* Open the target file. */
+    if ((fd = open(path, O_RDONLY)) < 0)
+    {
+       syslog(LOG_ERR, "failed to open() `%s': %s",
+              path, strerror(errno));
+       exit(EXIT_FAILURE);
+    }
+    /* Read out the integer. */
+    if (read(fd, &value, sizeof(value)) <= 0)
+    {
+       syslog(LOG_ERR, "failed to read() `%s': %s",
+              path, strerror(errno));
+       exit(EXIT_FAILURE);
+    }
+    /* Done. */
+    close(fd);
+    return value;
+}
+
+int main(int argc, char **argv)
+{
+    DIR *busDir, *slotDir, *funcDir;
+    struct dirent *bus, *slot, *func;
+    struct stat st;
+    char path[256];
+    const char *args[5];
+    int vendor, device, revision, status, pid;
+
+    /* Open logs. */
+    openlog("PCI", LOG_PID, LOG_USER);
+
+    /* Open the PCI filesystem. */
+    if (!(busDir = opendir("/dev/pci")))
+    {
+       syslog(LOG_ERR, "failed to opendir() `%s': %s",
+                       "/dev/pci", strerror(errno));
+       return EXIT_FAILURE;
+    }
+    /*
+     * Loop PCI bus(ses).
+     */
+    while ((bus = readdir(busDir)))
+    {
+       if (bus->d_name[0] == '.')
+       {
+           continue;
+       }
+       snprintf(path, sizeof(path), "/dev/pci/%s",
+                bus->d_name);
+
+       /* Open PCI slot directory. */
+        if (!(slotDir = opendir(path)))
+       {
+           syslog(LOG_ERR, "failed to opendir() `%s': %s",
+                            path, strerror(errno));
+           return EXIT_FAILURE;
+       }
+
+       /*
+        * Loop PCI slot(s).
+        */
+        while ((slot = readdir(slotDir)))
+        {
+           if (slot->d_name[0] == '.')
+           {
+               continue;
+           }
+           snprintf(path, sizeof(path), "/dev/pci/%s/%s",
+                    bus->d_name, slot->d_name);
+
+           /* Open PCI function directory. */
+           if (!(funcDir = opendir(path)))
+           {
+               syslog(LOG_ERR, "failed to opendir() `%s': %s\r\n",
+                                path, strerror(errno));
+               return EXIT_FAILURE;
+           }
+
+           /*
+            * Loop PCI function(s).
+            */
+           while ((func = readdir(funcDir)))
+           {
+               if (func->d_name[0] == '.')
+               {
+                   continue;
+               }
+               /* Read out properties. */
+               vendor   = readint(bus, slot, func, "vendor");
+               device   = readint(bus, slot, func, "device");
+               revision = readint(bus, slot, func, "revision");
+
+               /* Log the device. */
+                syslog(LOG_INFO, "[%s:%s:%s] %x:%x (rev %d)",
+                       bus->d_name, slot->d_name, func->d_name,
+                      vendor, device, revision);
+
+               /* Construct path to a device driver server. */
+               snprintf(path, sizeof(path), "/etc/pci/%x:%x",
+                        vendor, device);
+
+               /* Find device server, if any. */
+               if (stat(path, &st) == 0)
+               {
+                   /* Setup argument list. */
+                   args[0] = path;
+                   args[1] = bus->d_name;
+                   args[2] = slot->d_name;
+                   args[3] = func->d_name;
+                   args[4] = ZERO;
+
+                   /* Execute it! */
+                   pid = forkexec(path, args);
+                   waitpid(pid, &status, 0);
+               }
+
+           }
+           closedir(funcDir);
+        }
+        closedir(slotDir);
+    }
+    closedir(busDir);
+}
=======================================
--- /trunk/srv/pci/PCIServer.cpp        Sun Aug 16 14:22:16 2009
+++ /trunk/srv/pci/PCIServer.cpp        Tue Aug 18 13:59:35 2009
@@ -28,14 +28,16 @@

 int main(int argc, char **argv)
 {
-    /* (Re)create target directory. */
-    mkdir("/dev/pci", S_IWUSR | S_IRUSR);
-
     /* Create instance. */
     PCIServer server("/dev/pci");

-    /* Start serving requests. */
-    if (!fork())
+    /* (Re)create target directory. */
+    mkdir("/dev/pci", S_IWUSR | S_IRUSR);
+
+    /*
+     * Mount the filesystem.
+     */
+    if (server.mount())
     {
        /*
         * TODO: Please see issue 76:
@@ -70,12 +72,12 @@
     if (PCI_READ_WORD(0, 0, 0, PCI_VID) == 0xffff ||
         PCI_READ_WORD(0, 0, 0, PCI_DID) == 0xffff)
     {
-       syslog(LOG_INFO, "No Host Controller found");
+       syslog(LOG_INFO, "No Host Controller");
        exit(EXIT_FAILURE);
     }
     else
     {
-       syslog(LOG_INFO, "Host Controller found");
+       syslog(LOG_INFO, "Intel Host Controller");
        scan();
     }
 }
@@ -124,13 +126,6 @@
                /* Then make & fill the function directory. */
                detect(bus, slot, func);
                slotDir->insert(DirectoryFile, "%x", func);
-
-               /* Log the device. */
-               syslog(LOG_INFO, "[%x:%x:%x] %x:%x (rev %d)",
-                      bus, slot, func, vendorID, deviceID, revisionID);
-
-               /* Execute a device server. */
-               runDeviceServer(bus, slot, func, vendorID, deviceID);
            }
            slotDir = ZERO;
        }
@@ -192,51 +187,3 @@
     insertFileCache(new PCIFile(bus, slot, func, PCI_BAR5, 4),
                    "%x/%x/%x/bar5", bus, slot, func);
 }
-
-void PCIServer::runDeviceServer(u16 bus, u16 slot, u16 func,
-                               u16 vendorID, u16 deviceID)
-{
-    ProcessID pid;
-    struct stat st;
-    char path[PATHLEN];
-    const char *args[5];
-    int status;
-
-    /*
-     * Attempt to execute an external driver program
-     * to handle I/O for the PCI device. First we construct
-     * the full path to the handler, if any.
-     */
-    snprintf(path, sizeof(path), "/etc/pci/%x:%x",
-            vendorID, deviceID);
-
-    /* If there is no device server, forget it. */
-    if (stat(path, &st) == -1)
-    {
-       return;
-    }
-
-    /*
-     * Construct an argument list.
-     */
-    for (int i = 0; i < 4; i++)
-    {
-       args[i] = new char[PATHLEN];
-    }
-    args[4] = ZERO;
-    snprintf((char*)args[0], PATHLEN, "%s", path);
-    snprintf((char*)args[1], PATHLEN, "%x", bus);
-    snprintf((char*)args[2], PATHLEN, "%x", slot);
-    snprintf((char*)args[3], PATHLEN, "%x", func);
-
-    /*
-     * Try to fork off a child for the device server.
-     */
-    if ((pid = forkexec(path, args)) == (pid_t) -1)
-    {
-       syslog(LOG_ERR, "failed to forkexec() `%s': %s\r\n",
-                        path, strerror(errno));
-    }
-    else
-       waitpid(pid, &status, 0);
-}
=======================================
--- /trunk/srv/pci/PCIServer.h  Sun Aug 16 14:22:16 2009
+++ /trunk/srv/pci/PCIServer.h  Tue Aug 18 13:59:35 2009
@@ -188,17 +188,6 @@
         * @param func Device function number in the slot.
         */
        void detect(u16 bus, u16 slot, u16 func);
-
-       /**
-        * @brief Runs a PCI device server.
-        * @param bus PCI Bus number on which the device was detected.
-        * @param slot Slot number in the PCI bus.
-        * @param func Device function number in the slot.
-        * @param vendorID Numeric vendor ID read from PCI configuration space.
-        * @param deviceID Numeric device ID read from PCI configuration space.
-        */
-       void runDeviceServer(u16 bus, u16 slot, u16 func,
-                            u16 vendorID, u16 deviceID);

        /** @brief Root directory pointer. */
        Directory *rootDir;
=======================================
--- /trunk/srv/pci/SConscript   Sun Aug 16 14:22:16 2009
+++ /trunk/srv/pci/SConscript   Tue Aug 18 13:59:35 2009
@@ -22,3 +22,6 @@

 env.Program('server', [ 'PCIServer.cpp', 'PCIFile.cpp' ],
                         LIBS = env['LIBS'], LIBPATH = env['LIBPATH'])
+
+env.Program('detect', [ 'PCIDetect.cpp' ],
+                        LIBS = env['LIBS'], LIBPATH = env['LIBPATH'])

Other related posts:

  • » [freenos] r322 committed - Separated traversal of /dev/pci and execution of /etc/pci/$VENDOR:$DEV... - codesite-noreply