Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

linux_pci.c

00001 /***************************************************************************
00002  * CVSID: $Id: linux_pci.c,v 1.6 2004/03/03 17:56:56 david Exp $
00003  *
00004  * linux_pci.c : PCI handling on Linux 2.6
00005  *
00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
00007  *
00008  * Licensed under the Academic Free License version 2.0
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  **************************************************************************/
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #  include <config.h>
00028 #endif
00029 
00030 #include <ctype.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <getopt.h>
00035 #include <assert.h>
00036 #include <unistd.h>
00037 #include <stdarg.h>
00038 
00039 #include "../logger.h"
00040 #include "../device_store.h"
00041 #include "linux_pci.h"
00042 
00052 static char *pci_ids = NULL;
00053 
00055 static unsigned int pci_ids_len;
00056 
00058 static unsigned int pci_ids_iter_pos;
00059 
00061 static void
00062 pci_ids_line_iter_init ()
00063 {
00064     pci_ids_iter_pos = 0;
00065 }
00066 
00068 #define PCI_IDS_MAX_LINE_LEN 512
00069 
00077 static char *
00078 pci_ids_line_iter_get_line (unsigned int *line_len)
00079 {
00080     unsigned int i;
00081     static char line[PCI_IDS_MAX_LINE_LEN];
00082 
00083     for (i = 0;
00084          pci_ids_iter_pos < pci_ids_len &&
00085          i < PCI_IDS_MAX_LINE_LEN - 1 &&
00086          pci_ids[pci_ids_iter_pos] != '\n'; i++, pci_ids_iter_pos++) {
00087         line[i] = pci_ids[pci_ids_iter_pos];
00088     }
00089 
00090     line[i] = '\0';
00091     if (line_len != NULL)
00092         *line_len = i;
00093 
00094     pci_ids_iter_pos++;
00095 
00096     return line;
00097 }
00098 
00103 static dbus_bool_t
00104 pci_ids_line_iter_has_more ()
00105 {
00106     return pci_ids_iter_pos < pci_ids_len;
00107 }
00108 
00109 
00124 static void
00125 pci_ids_find (int vendor_id, int product_id,
00126           int subsys_vendor_id, int subsys_product_id,
00127           char **vendor_name, char **product_name,
00128           char **subsys_vendor_name, char **subsys_product_name)
00129 {
00130     char *line;
00131     unsigned int i;
00132     unsigned int line_len;
00133     unsigned int num_tabs;
00134     char rep_vi[8];
00135     char rep_pi[8];
00136     char rep_svi[8];
00137     char rep_spi[8];
00138     static char store_vn[PCI_IDS_MAX_LINE_LEN];
00139     static char store_pn[PCI_IDS_MAX_LINE_LEN];
00140     static char store_svn[PCI_IDS_MAX_LINE_LEN];
00141     static char store_spn[PCI_IDS_MAX_LINE_LEN];
00142     dbus_bool_t vendor_matched = FALSE;
00143     dbus_bool_t product_matched = FALSE;
00144 
00145     snprintf (rep_vi, 8, "%04x", vendor_id);
00146     snprintf (rep_pi, 8, "%04x", product_id);
00147     snprintf (rep_svi, 8, "%04x", subsys_vendor_id);
00148     snprintf (rep_spi, 8, "%04x", subsys_product_id);
00149 
00150     *vendor_name = NULL;
00151     *product_name = NULL;
00152     *subsys_vendor_name = NULL;
00153     *subsys_product_name = NULL;
00154 
00155     for (pci_ids_line_iter_init (); pci_ids_line_iter_has_more ();) {
00156         line = pci_ids_line_iter_get_line (&line_len);
00157 
00158         /* skip lines with no content */
00159         if (line_len < 4)
00160             continue;
00161 
00162         /* skip comments */
00163         if (line[0] == '#')
00164             continue;
00165 
00166         /* count number of tabs */
00167         num_tabs = 0;
00168         for (i = 0; i < line_len; i++) {
00169             if (line[i] != '\t')
00170                 break;
00171             num_tabs++;
00172         }
00173 
00174         switch (num_tabs) {
00175         case 0:
00176             /* vendor names */
00177             vendor_matched = FALSE;
00178 
00179             /* first check subsys_vendor_id, if haven't done 
00180              * already */
00181             if (*subsys_vendor_name == NULL
00182                 && subsys_vendor_id != 0) {
00183                 if ((*((dbus_uint32_t *) line)) ==
00184                     (*((dbus_uint32_t *) rep_svi))) {
00185                     /* found it */
00186                     for (i = 4; i < line_len; i++) {
00187                         if (!isspace (line[i]))
00188                             break;
00189                     }
00190                     strncpy (store_svn, line + i,
00191                          PCI_IDS_MAX_LINE_LEN);
00192                     *subsys_vendor_name = store_svn;
00193                 }
00194             }
00195 
00196             /* check vendor_id */
00197             if (vendor_id != 0) {
00198                 if (memcmp (line, rep_vi, 4) == 0) {
00199                     /* found it */
00200                     vendor_matched = TRUE;
00201 
00202                     for (i = 4; i < line_len; i++) {
00203                         if (!isspace (line[i]))
00204                             break;
00205                     }
00206                     strncpy (store_vn, line + i,
00207                          PCI_IDS_MAX_LINE_LEN);
00208                     *vendor_name = store_vn;
00209                 }
00210             }
00211 
00212             break;
00213 
00214         case 1:
00215             product_matched = FALSE;
00216 
00217             /* product names */
00218             if (!vendor_matched)
00219                 continue;
00220 
00221             /* check product_id */
00222             if (product_id != 0) {
00223                 if (memcmp (line + 1, rep_pi, 4) == 0) {
00224                     /* found it */
00225 
00226                     product_matched = TRUE;
00227 
00228                     for (i = 5; i < line_len; i++) {
00229                         if (!isspace (line[i]))
00230                             break;
00231                     }
00232                     strncpy (store_pn, line + i,
00233                          PCI_IDS_MAX_LINE_LEN);
00234                     *product_name = store_pn;
00235                 }
00236             }
00237             break;
00238 
00239         case 2:
00240             /* subsystem_vendor subsystem_product */
00241             if (!vendor_matched || !product_matched)
00242                 continue;
00243 
00244             /* check product_id */
00245             if (subsys_vendor_id != 0
00246                 && subsys_product_id != 0) {
00247                 if (memcmp (line + 2, rep_svi, 4) == 0
00248                     && memcmp (line + 7, rep_spi,
00249                            4) == 0) {
00250                     /* found it */
00251                     for (i = 11; i < line_len; i++) {
00252                         if (!isspace (line[i]))
00253                             break;
00254                     }
00255                     strncpy (store_spn, line + i,
00256                          PCI_IDS_MAX_LINE_LEN);
00257                     *subsys_product_name = store_spn;
00258                 }
00259             }
00260 
00261             break;
00262 
00263         default:
00264             break;
00265         }
00266 
00267     }
00268 }
00269 
00277 static dbus_bool_t
00278 pci_ids_load (const char *path)
00279 {
00280     FILE *fp;
00281     unsigned int num_read;
00282 
00283     fp = fopen (path, "r");
00284     if (fp == NULL) {
00285         HAL_ERROR (("couldn't open PCI database at %s,", path));
00286         return FALSE;
00287     }
00288 
00289     fseek (fp, 0, SEEK_END);
00290     pci_ids_len = ftell (fp);
00291     fseek (fp, 0, SEEK_SET);
00292 
00293     pci_ids = malloc (pci_ids_len);
00294     if (pci_ids == NULL) {
00295         DIE (("Couldn't allocate %d bytes for PCI database file\n",
00296               pci_ids_len));
00297     }
00298 
00299     num_read = fread (pci_ids, sizeof (char), pci_ids_len, fp);
00300     if (pci_ids_len != num_read) {
00301         HAL_ERROR (("Error loading PCI database file\n"));
00302         free (pci_ids);
00303         pci_ids = NULL;
00304         return FALSE;
00305     }
00306 
00307     return TRUE;
00308 }
00309 
00314 static dbus_bool_t
00315 pci_ids_free ()
00316 {
00317     if (pci_ids != NULL) {
00318         free (pci_ids);
00319         pci_ids = NULL;
00320         return TRUE;
00321     }
00322     return FALSE;
00323 }
00324 
00325 
00344 static char *
00345 pci_compute_udi (HalDevice * d, int append_num)
00346 {
00347     static char buf[256];
00348 
00349     if (append_num == -1)
00350         sprintf (buf, "/org/freedesktop/Hal/devices/pci_%x_%x",
00351              ds_property_get_int (d, "pci.vendor_id"),
00352              ds_property_get_int (d, "pci.product_id"));
00353     else
00354         sprintf (buf, "/org/freedesktop/Hal/devices/pci_%x_%x/%d",
00355              ds_property_get_int (d, "pci.vendor_id"),
00356              ds_property_get_int (d, "pci.product_id"),
00357              append_num);
00358 
00359     return buf;
00360 }
00361 
00362 
00371 static void
00372 pci_add_caps_from_class (HalDevice * d,
00373              int dev_class, int dev_sub_class, int dev_proto)
00374 {
00375     char *cat = NULL;
00376 
00377     switch (dev_class) {
00378     case 0x01:
00379         cat = "storage_controller";
00380         ds_add_capability (d, "storage_controller");
00381         switch (dev_sub_class) {
00382         case 0x00:
00383             ds_add_capability (d, "storage_controller.scsi");
00384             break;
00385         case 0x01:
00386             ds_add_capability (d, "storage_controller.ide");
00387             break;
00388         case 0x02:
00389             ds_add_capability (d, "storage_controller.floppy");
00390             break;
00391         case 0x03:
00392             ds_add_capability (d, "storage_controller.ipi");
00393             break;
00394         case 0x04:
00395             ds_add_capability (d, "storage_controller.raid");
00396             break;
00397         }
00398         break;
00399     case 0x02:
00400         cat = "net";
00401         ds_add_capability (d, "net");
00402         switch (dev_sub_class) {
00403         case 0x00:
00404             ds_add_capability (d, "net.ethernet");
00405             break;
00406         case 0x01:
00407             ds_add_capability (d, "net.tokenring");
00408             break;
00409         case 0x02:
00410             ds_add_capability (d, "net.fddi");
00411             break;
00412         case 0x03:
00413             ds_add_capability (d, "net.atm");
00414             break;
00415         case 0x04:
00416             ds_add_capability (d, "net.isdn");
00417             break;
00418         }
00419         break;
00420     case 0x03:
00421         cat = "video";
00422         ds_add_capability (d, "video");
00423         if (dev_sub_class == 0x00 && dev_proto == 0x00)
00424             ds_add_capability (d, "video.vga");
00425         if (dev_sub_class == 0x00 && dev_proto == 0x01)
00426             ds_add_capability (d, "video.8514");
00427         else if (dev_sub_class == 0x01)
00428             ds_add_capability (d, "video.xga");
00429         else if (dev_sub_class == 0x02)
00430             ds_add_capability (d, "video.3d");
00431         break;
00432     case 0x04:
00433         cat = "multimedia";
00434         ds_add_capability (d, "multimedia");
00435         switch (dev_sub_class) {
00436         case 0x00:
00437             ds_add_capability (d, "multimedia.video");
00438             cat = "multimedia.video";
00439             break;
00440         case 0x01:
00441             ds_add_capability (d, "multimedia.audio");
00442             cat = "multimedia.audio";
00443             break;
00444         case 0x02:
00445             ds_add_capability (d, "multimedia.telephony");
00446             cat = "multimedia.telephony";
00447             break;
00448         }
00449         break;
00450     case 0x06:
00451         cat = "bridge";
00452         ds_add_capability (d, "bridge");
00453         switch (dev_sub_class) {
00454         case 0x00:
00455             ds_add_capability (d, "bridge.host");
00456             break;
00457         case 0x01:
00458             ds_add_capability (d, "bridge.isa");
00459             break;
00460         case 0x02:
00461             ds_add_capability (d, "bridge.eisa");
00462             break;
00463         case 0x03:
00464             ds_add_capability (d, "bridge.micro_channel");
00465             break;
00466         case 0x04:
00467             ds_add_capability (d, "bridge.pci");
00468             break;
00469         case 0x05:
00470             ds_add_capability (d, "bridge.pcmcia");
00471             break;
00472         case 0x06:
00473             ds_add_capability (d, "bridge.nubus");
00474             break;
00475         case 0x07:
00476             cat = "bridge.cardbus";
00477             ds_add_capability (d, "bridge.cardbus");
00478             break;
00479         case 0x08:
00480             ds_add_capability (d, "bridge.raceway");
00481             break;
00482         case 0x09:
00483             ds_add_capability (d, "bridge.semi_transparent");
00484             break;
00485         case 0x0a:
00486             ds_add_capability (d, "bridge.infiniband");
00487             break;
00488         }
00489         break;
00490     case 0x07:
00491         cat = "comm";
00492         ds_add_capability (d, "comm");
00493         if (dev_sub_class == 0x00) {
00494             cat = "comm.serial";
00495             ds_add_capability (d, "comm.serial");
00496             switch (dev_proto) {
00497             case 0x00:
00498                 ds_add_capability (d, "comm.serial.8250");
00499                 break;
00500             case 0x01:
00501                 ds_add_capability (d, "comm.serial.16450");
00502                 break;
00503             case 0x02:
00504                 ds_add_capability (d, "comm.serial.16550");
00505                 break;
00506             case 0x03:
00507                 ds_add_capability (d, "comm.serial.16650");
00508                 break;
00509             case 0x04:
00510                 ds_add_capability (d, "comm.serial.16750");
00511                 break;
00512             case 0x05:
00513                 ds_add_capability (d, "comm.serial.16850");
00514                 break;
00515             case 0x06:
00516                 ds_add_capability (d, "comm.serial.16950");
00517                 break;
00518             }
00519         } else if (dev_sub_class == 0x01) {
00520             cat = "comm.parallel";
00521             ds_add_capability (d, "comm.parallel");
00522             switch (dev_proto) {
00523             case 0x00:
00524                 ds_add_capability (d, "comm.parallel.spp");
00525                 break;
00526             case 0x01:
00527                 ds_add_capability (d,
00528                            "comm.parallel.bidir");
00529                 break;
00530             case 0x02:
00531                 ds_add_capability (d, "comm.parallel.ecp");
00532                 break;
00533             case 0x03:
00534                 ds_add_capability (d,
00535                            "comm.parallel.ieee1284");
00536                 break;
00537             case 0xfe:
00538                 ds_add_capability (d,
00539                            "comm.parallel.ieee1284_target");
00540                 break;
00541             }
00542         } else if (dev_sub_class == 0x02) {
00543             cat = "comm.serial";
00544             ds_add_capability (d, "comm.serial");
00545             ds_add_capability (d, "comm.serial.multiport");
00546         } else if (dev_sub_class == 0x03) {
00547             cat = "modem";
00548             ds_add_capability (d, "modem");
00549             if (dev_proto >= 0x01 && dev_proto <= 0x04)
00550                 ds_add_capability (d, "modem.hayes");
00551         }
00552         break;
00553     case 0x0c:
00554         cat = "serial_controller";
00555         ds_add_capability (d, "serial_controller");
00556         switch (dev_sub_class) {
00557         case 0x00:
00558             cat = "serial_controller.ieee1394";
00559             ds_add_capability (d,
00560                        "serial_controller.ieee1394");
00561             if (dev_proto == 0x10)
00562                 ds_add_capability (d,
00563                            "serial_controller.ieee1394.ohci");
00564             break;
00565         case 0x01:
00566             ds_add_capability (d, "serial_controller.access");
00567             break;
00568         case 0x02:
00569             ds_add_capability (d, "serial_controller.ssa");
00570             break;
00571         case 0x03:
00572             cat = "serial_controller.usb";
00573             ds_add_capability (d, "serial_controller.usb");
00574             switch (dev_proto) {
00575             case 0x00:
00576                 ds_add_capability (d,
00577                            "serial_controller.usb.uhci");
00578                 break;
00579             case 0x01:
00580                 ds_add_capability (d,
00581                            "serial_controller.usb.ohci");
00582                 break;
00583             case 0x02:
00584                 ds_add_capability (d,
00585                            "serial_controller.usb.ehci");
00586                 break;
00587             case 0xfe:
00588                 ds_add_capability (d,
00589                            "serial_controller.usb.device");
00590                 break;
00591             }
00592             break;
00593         }
00594         break;
00595     case 0x0d:
00596         cat = "wireless";
00597         ds_add_capability (d, "wireless");
00598         switch (dev_sub_class) {
00599         case 0x00:
00600             ds_add_capability (d, "wireless.irda");
00601             break;
00602         case 0x01:
00603             ds_add_capability (d,
00604                        "wireless.consumer_controller");
00605             break;
00606         case 0x02:
00607             ds_add_capability (d, "wireless.rf_controller");
00608             break;
00609         }
00610         break;
00611     case 0x0f:
00612         cat = "satellite_controller";
00613         ds_add_capability (d, "satellite_controller");
00614         switch (dev_sub_class) {
00615         case 0x00:
00616             ds_add_capability (d, "satellite_controller.tv");
00617             break;
00618         case 0x01:
00619             ds_add_capability (d,
00620                        "satellite_controller.audio");
00621             break;
00622         case 0x02:
00623             ds_add_capability (d,
00624                        "satellite_controller.video");
00625             break;
00626         case 0x03:
00627             ds_add_capability (d, "satellite_controller.data");
00628             break;
00629         }
00630         break;
00631     }
00632 
00633     if (cat != NULL)
00634         ds_property_set_string (d, "info.category", cat);
00635 }
00636 
00637 
00638 /* fwd decl */
00639 static void visit_device_pci_got_parent (HalDevice * parent,
00640                      void *data1, void *data2);
00641 
00650 void
00651 visit_device_pci (const char *path, struct sysfs_device *device)
00652 {
00653     int i;
00654     int len;
00655     HalDevice *d;
00656     char attr_name[SYSFS_NAME_LEN];
00657     struct sysfs_attribute *cur;
00658     int vendor_id = 0;
00659     int product_id = 0;
00660     int subsys_vendor_id = 0;
00661     int subsys_product_id = 0;
00662     char *vendor_name;
00663     char *product_name;
00664     char *subsys_vendor_name;
00665     char *subsys_product_name;
00666     const char *driver;
00667     dbus_int32_t cls = 0x00ffffff;
00668     char namebuf[512];
00669     char *parent_sysfs_path;
00670 
00671     /*printf("pci: %s\n", path); */
00672 
00673     /* Must be a new PCI device */
00674     d = ds_device_new ();
00675     ds_property_set_string (d, "info.bus", "pci");
00676     ds_property_set_string (d, "linux.sysfs_path", path);
00677     ds_property_set_string (d, "linux.sysfs_path_device", path);
00684     ds_property_set_string (d, "pci.linux.sysfs_path", path);
00685     /*printf("*** created udi=%s for path=%s\n", d, path); */
00686 
00687     /* set driver */
00688     driver = drivers_lookup (path);
00689     if (driver != NULL)
00690         ds_property_set_string (d, "linux.driver", driver);
00691 
00692     dlist_for_each_data (sysfs_get_device_attributes (device), cur,
00693                  struct sysfs_attribute) {
00694 
00695         if (sysfs_get_name_from_path (cur->path,
00696                           attr_name,
00697                           SYSFS_NAME_LEN) != 0)
00698             continue;
00699 
00700         /* strip whitespace */
00701         len = strlen (cur->value);
00702         for (i = len - 1; isspace (cur->value[i]); --i)
00703             cur->value[i] = '\0';
00704 
00705         /*printf("attr_name=%s -> '%s'\n", attr_name, cur->value); */
00706 
00707         if (strcmp (attr_name, "device") == 0)
00708             product_id = parse_hex (cur->value);
00709         else if (strcmp (attr_name, "vendor") == 0)
00710             vendor_id = parse_hex (cur->value);
00711         else if (strcmp (attr_name, "subsystem_device") == 0)
00712             subsys_product_id = parse_hex (cur->value);
00713         else if (strcmp (attr_name, "subsystem_vendor") == 0)
00714             subsys_vendor_id = parse_hex (cur->value);
00715         else if (strcmp (attr_name, "class") == 0) {
00716             cls = parse_hex (cur->value);
00717         }
00718     }
00719 
00720     ds_property_set_int (d, "pci.vendor_id", vendor_id);
00721     ds_property_set_int (d, "pci.product_id", product_id);
00722     ds_property_set_int (d, "pci.subsys_vendor_id", subsys_vendor_id);
00723     ds_property_set_int (d, "pci.subsys_product_id",
00724                  subsys_product_id);
00725 
00726     /* Lookup names in pci.ids */
00727     pci_ids_find (vendor_id, product_id, subsys_vendor_id,
00728               subsys_product_id, &vendor_name, &product_name,
00729               &subsys_vendor_name, &subsys_product_name);
00730     if (vendor_name != NULL)
00731         ds_property_set_string (d, "pci.vendor", vendor_name);
00732     if (product_name != NULL)
00733         ds_property_set_string (d, "pci.product", product_name);
00734     if (subsys_vendor_name != NULL)
00735         ds_property_set_string (d, "pci.subsys_vendor",
00736                     subsys_vendor_name);
00737     if (subsys_product_name != NULL)
00738         ds_property_set_string (d, "pci.subsys_product",
00739                     subsys_product_name);
00740 
00741     /* Provide best-guess of name, goes in Product property; 
00742      * .fdi files can override this */
00743     if (product_name != NULL) {
00744         ds_property_set_string (d, "info.product", product_name);
00745     } else {
00746         snprintf (namebuf, 512, "Unknown (0x%04x)", product_id);
00747         ds_property_set_string (d, "info.product", namebuf);
00748     }
00749 
00750     /* Provide best-guess of vendor, goes in Vendor property; 
00751      * .fdi files can override this */
00752     if (vendor_name != NULL) {
00753         ds_property_set_string (d, "info.vendor", vendor_name);
00754     } else {
00755         snprintf (namebuf, 512, "Unknown (0x%04x)", vendor_id);
00756         ds_property_set_string (d, "info.vendor", namebuf);
00757     }
00758 
00759 
00760     ds_property_set_int (d, "pci.device_class", (cls >> 16) & 0xff);
00761     ds_property_set_int (d, "pci.device_subclass", (cls >> 8) & 0xff);
00762     ds_property_set_int (d, "pci.device_protocol", cls & 0xff);
00763     pci_add_caps_from_class (d, (cls >> 16) & 0xff, (cls >> 8) & 0xff,
00764                  cls & 0xff);
00765 
00766     parent_sysfs_path = get_parent_sysfs_path (path);
00767 
00768     /* Find parent; this happens asynchronously as our parent might
00769      * be added later. If we are probing this can't happen so the
00770      * timeout is set to zero in that event..
00771      */
00772     ds_device_async_find_by_key_value_string
00773         ("linux.sysfs_path_device", parent_sysfs_path, TRUE,
00774          visit_device_pci_got_parent, (void *) d, NULL,
00775          is_probing ? 0 : HAL_LINUX_HOTPLUG_TIMEOUT);
00776 
00777     free (parent_sysfs_path);
00778 }
00779 
00787 static void
00788 visit_device_pci_got_parent (HalDevice * parent, void *data1, void *data2)
00789 {
00790     char *new_udi = NULL;
00791     HalDevice *new_d = NULL;
00792     HalDevice *d = (HalDevice *) data1;
00793 
00794     if (parent != NULL) {
00795         ds_property_set_string (d, "info.parent", parent->udi);
00796     }
00797 
00798     /* Compute a proper UDI (unique device id) and try to locate a 
00799      * persistent unplugged device or simple add this new device...
00800      */
00801     new_udi = rename_and_merge (d, pci_compute_udi, "pci");
00802     if (new_udi != NULL) {
00803         new_d = ds_device_find (new_udi);
00804         if (new_d != NULL) {
00805             ds_gdl_add (new_d);
00806         }
00807     }
00808 }
00809 
00810 
00814 void
00815 linux_pci_init ()
00816 {
00817     /* get all drivers under /sys/bus/pci/drivers */
00818     drivers_collect ("pci");
00819 
00820     /* Load /usr/share/hwdata/pci.ids */
00821     pci_ids_load (HWDATA_DIR "/pci.ids");
00822 }
00823 
00828 void
00829 linux_pci_detection_done ()
00830 {
00831 }
00832 
00836 void
00837 linux_pci_shutdown ()
00838 {
00839     pci_ids_free ();
00840 }
00841 

Generated on Thu Mar 11 21:32:22 2004 for HAL by doxygen 1.3.6-20040222