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

linux_pci.c

00001 /***************************************************************************
00002  * CVSID: $Id: linux_pci.c,v 1.5 2004/01/02 12:11:24 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 pci_ids_line_iter_init()
00062 {
00063     pci_ids_iter_pos = 0;
00064 }
00065 
00067 #define PCI_IDS_MAX_LINE_LEN 512
00068 
00076 static char* pci_ids_line_iter_get_line(unsigned int* line_len)
00077 {
00078     unsigned int i;
00079     static char line[PCI_IDS_MAX_LINE_LEN];
00080 
00081     for(i=0; 
00082         pci_ids_iter_pos<pci_ids_len && 
00083             i<PCI_IDS_MAX_LINE_LEN-1 && 
00084             pci_ids[pci_ids_iter_pos]!='\n';
00085         i++, pci_ids_iter_pos++)
00086     {
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 pci_ids_line_iter_has_more()
00104 {
00105     return pci_ids_iter_pos<pci_ids_len;
00106 }
00107 
00108 
00123 static void pci_ids_find(int vendor_id, int product_id,
00124                          int subsys_vendor_id, int subsys_product_id,
00125                          char** vendor_name, char** product_name,
00126                          char** subsys_vendor_name,char** subsys_product_name)
00127 {
00128     char* line;
00129     unsigned int i;
00130     unsigned int line_len;
00131     unsigned int num_tabs;
00132     char rep_vi[8];
00133     char rep_pi[8];
00134     char rep_svi[8];
00135     char rep_spi[8];
00136     static char store_vn[PCI_IDS_MAX_LINE_LEN];
00137     static char store_pn[PCI_IDS_MAX_LINE_LEN];
00138     static char store_svn[PCI_IDS_MAX_LINE_LEN];
00139     static char store_spn[PCI_IDS_MAX_LINE_LEN];
00140     dbus_bool_t vendor_matched=FALSE;
00141     dbus_bool_t product_matched=FALSE;
00142 
00143     snprintf(rep_vi, 8, "%04x", vendor_id);
00144     snprintf(rep_pi, 8, "%04x", product_id);
00145     snprintf(rep_svi, 8, "%04x", subsys_vendor_id);
00146     snprintf(rep_spi, 8, "%04x", subsys_product_id);
00147 
00148     *vendor_name = NULL;
00149     *product_name = NULL;
00150     *subsys_vendor_name = NULL;
00151     *subsys_product_name = NULL;
00152 
00153     for(pci_ids_line_iter_init(); pci_ids_line_iter_has_more(); )
00154     {
00155         line = pci_ids_line_iter_get_line(&line_len);
00156 
00157         /* skip lines with no content */
00158         if( line_len<4 )
00159             continue;
00160 
00161         /* skip comments */
00162         if( line[0]=='#' )
00163             continue;
00164 
00165         /* count number of tabs */
00166         num_tabs = 0;
00167         for(i=0; i<line_len; i++)
00168         {
00169             if( line[i]!='\t' )
00170                 break;
00171             num_tabs++;
00172         }
00173 
00174         switch( num_tabs )
00175         {
00176         case 0:
00177             /* vendor names */
00178             vendor_matched = FALSE;
00179 
00180             /* first check subsys_vendor_id, if haven't done already */
00181             if( *subsys_vendor_name==NULL && subsys_vendor_id!=0 )
00182             {
00183                 if( (*((dbus_uint32_t*)line))==(*((dbus_uint32_t*)rep_svi)) )
00184                 {
00185                     /* found it */
00186                     for(i=4; i<line_len; i++)
00187                     {
00188                         if( !isspace(line[i]) )
00189                             break;
00190                     }
00191                     strncpy(store_svn, line+i, PCI_IDS_MAX_LINE_LEN);
00192                     *subsys_vendor_name = store_svn;
00193                 }
00194             }
00195             
00196             /* check vendor_id */
00197             if( vendor_id!=0 )
00198             {
00199                 if( memcmp(line, rep_vi, 4)==0 )
00200                 {
00201                     /* found it */
00202                     vendor_matched = TRUE;
00203 
00204                     for(i=4; i<line_len; i++)
00205                     {
00206                         if( !isspace(line[i]) )
00207                             break;
00208                     }
00209                     strncpy(store_vn, line+i, PCI_IDS_MAX_LINE_LEN);
00210                     *vendor_name = store_vn;
00211                 }
00212             }
00213             
00214             break;
00215 
00216         case 1:
00217             product_matched = FALSE;
00218 
00219             /* product names */
00220             if( !vendor_matched )
00221                 continue;
00222 
00223             /* check product_id */
00224             if( product_id!=0 )
00225             {
00226                 if( memcmp(line+1, rep_pi, 4)==0 )
00227                 {
00228                     /* found it */
00229 
00230                     product_matched = TRUE;
00231 
00232                     for(i=5; i<line_len; i++)
00233                     {
00234                         if( !isspace(line[i]) )
00235                             break;
00236                     }
00237                     strncpy(store_pn, line+i, PCI_IDS_MAX_LINE_LEN);
00238                     *product_name = store_pn;
00239                 }
00240             }
00241             break;
00242 
00243         case 2:
00244             /* subsystem_vendor subsystem_product */
00245             if( !vendor_matched || !product_matched )
00246                 continue;
00247 
00248             /* check product_id */
00249             if( subsys_vendor_id!=0 && subsys_product_id!=0 )
00250             {
00251                 if( memcmp(line+2, rep_svi, 4)==0 &&
00252                     memcmp(line+7, rep_spi, 4)==0 )
00253                 {
00254                     /* found it */
00255                     for(i=11; i<line_len; i++)
00256                     {
00257                         if( !isspace(line[i]) )
00258                             break;
00259                     }
00260                     strncpy(store_spn, line+i, PCI_IDS_MAX_LINE_LEN);
00261                     *subsys_product_name = store_spn;
00262                 }
00263             }
00264 
00265             break;
00266 
00267         default:
00268             break;
00269         }
00270         
00271     }
00272 }
00273 
00281 static dbus_bool_t pci_ids_load(const char* path)
00282 {
00283     FILE* fp;
00284     unsigned int num_read;
00285 
00286     fp = fopen(path, "r");
00287     if( fp==NULL )
00288     {
00289         HAL_ERROR(("couldn't open PCI database at %s,", path));
00290         return FALSE;
00291     }
00292 
00293     fseek(fp, 0, SEEK_END);
00294     pci_ids_len = ftell(fp);
00295     fseek(fp, 0, SEEK_SET);
00296 
00297     pci_ids = malloc(pci_ids_len);
00298     if( pci_ids==NULL )
00299     {
00300         DIE(("Couldn't allocate %d bytes for PCI database file\n",
00301              pci_ids_len));
00302     }
00303     
00304     num_read = fread(pci_ids, sizeof(char), pci_ids_len, fp);
00305     if( pci_ids_len!=num_read )
00306     {
00307         HAL_ERROR(("Error loading PCI database file\n"));
00308         free(pci_ids);
00309         pci_ids=NULL;
00310         return FALSE;
00311     }    
00312 
00313     return TRUE;
00314 }
00315 
00320 static dbus_bool_t pci_ids_free()
00321 {
00322     if( pci_ids!=NULL )
00323     {
00324         free(pci_ids);
00325         pci_ids=NULL;
00326         return TRUE;
00327     }
00328     return FALSE;
00329 }
00330 
00331 
00350 static char* pci_compute_udi(HalDevice* d, int append_num)
00351 {
00352     static char buf[256];
00353 
00354     if( append_num==-1 )
00355         sprintf(buf, "/org/freedesktop/Hal/devices/pci_%x_%x",
00356                 ds_property_get_int(d, "pci.vendor_id"),
00357                 ds_property_get_int(d, "pci.product_id"));
00358     else
00359         sprintf(buf, "/org/freedesktop/Hal/devices/pci_%x_%x/%d", 
00360                 ds_property_get_int(d, "pci.vendor_id"),
00361                 ds_property_get_int(d, "pci.product_id"),
00362                 append_num);
00363     
00364     return buf;
00365 }
00366 
00367 
00376 static void pci_add_caps_from_class(HalDevice* d,
00377                                     int dev_class, 
00378                                     int dev_sub_class, 
00379                                     int dev_proto)
00380 {
00381     char* cat = NULL;
00382 
00383     switch( dev_class )
00384     {
00385     case 0x01:
00386         cat = "storage_controller";
00387         ds_add_capability(d, "storage_controller");
00388         switch( dev_sub_class)
00389         {
00390         case 0x00:
00391             ds_add_capability(d, "storage_controller.scsi");
00392             break;
00393         case 0x01:
00394             ds_add_capability(d, "storage_controller.ide");
00395             break;
00396         case 0x02:
00397             ds_add_capability(d, "storage_controller.floppy");
00398             break;
00399         case 0x03:
00400             ds_add_capability(d, "storage_controller.ipi");
00401             break;
00402         case 0x04:
00403             ds_add_capability(d, "storage_controller.raid");
00404             break;
00405         }
00406         break;
00407     case 0x02:
00408         cat = "net";
00409         ds_add_capability(d, "net");
00410         switch( dev_sub_class)
00411         {
00412         case 0x00:
00413             ds_add_capability(d, "net.ethernet");
00414             break;
00415         case 0x01:
00416             ds_add_capability(d, "net.tokenring");
00417             break;
00418         case 0x02:
00419             ds_add_capability(d, "net.fddi");
00420             break;
00421         case 0x03:
00422             ds_add_capability(d, "net.atm");
00423             break;
00424         case 0x04:
00425             ds_add_capability(d, "net.isdn");
00426             break;
00427         }
00428         break;
00429     case 0x03:
00430         cat = "video";
00431         ds_add_capability(d, "video");
00432         if( dev_sub_class==0x00 && dev_proto==0x00 )
00433             ds_add_capability(d, "video.vga");
00434         if( dev_sub_class==0x00 && dev_proto==0x01 )
00435             ds_add_capability(d, "video.8514");
00436         else if( dev_sub_class==0x01 )
00437             ds_add_capability(d, "video.xga");
00438         else if( dev_sub_class==0x02 )
00439             ds_add_capability(d, "video.3d");
00440         break;
00441     case 0x04:
00442         cat = "multimedia";
00443         ds_add_capability(d, "multimedia");
00444         switch( dev_sub_class)
00445         {
00446         case 0x00:
00447             ds_add_capability(d, "multimedia.video");
00448             cat = "multimedia.video";
00449             break;
00450         case 0x01:
00451             ds_add_capability(d, "multimedia.audio");
00452             cat = "multimedia.audio";
00453             break;
00454         case 0x02:
00455             ds_add_capability(d, "multimedia.telephony");
00456             cat = "multimedia.telephony";
00457             break;
00458         }
00459         break;
00460     case 0x06:
00461         cat = "bridge";
00462         ds_add_capability(d, "bridge");
00463         switch( dev_sub_class)
00464         {
00465         case 0x00:
00466             ds_add_capability(d, "bridge.host");
00467             break;
00468         case 0x01:
00469             ds_add_capability(d, "bridge.isa");
00470             break;
00471         case 0x02:
00472             ds_add_capability(d, "bridge.eisa");
00473             break;
00474         case 0x03:
00475             ds_add_capability(d, "bridge.micro_channel");
00476             break;
00477         case 0x04:
00478             ds_add_capability(d, "bridge.pci");
00479             break;
00480         case 0x05:
00481             ds_add_capability(d, "bridge.pcmcia");
00482             break;
00483         case 0x06:
00484             ds_add_capability(d, "bridge.nubus");
00485             break;
00486         case 0x07:
00487             cat = "bridge.cardbus";
00488             ds_add_capability(d, "bridge.cardbus");
00489             break;
00490         case 0x08:
00491             ds_add_capability(d, "bridge.raceway");
00492             break;
00493         case 0x09:
00494             ds_add_capability(d, "bridge.semi_transparent");
00495             break;
00496         case 0x0a:
00497             ds_add_capability(d, "bridge.infiniband");
00498             break;
00499         }
00500         break;
00501     case 0x07:
00502         cat = "comm";
00503         ds_add_capability(d, "comm");
00504         if( dev_sub_class==0x00 )
00505         {
00506             cat = "comm.serial";
00507             ds_add_capability(d, "comm.serial");
00508             switch( dev_proto)
00509             {
00510             case 0x00:
00511                 ds_add_capability(d, "comm.serial.8250");
00512                 break;
00513             case 0x01:
00514                 ds_add_capability(d, "comm.serial.16450");
00515                 break;
00516             case 0x02:
00517                 ds_add_capability(d, "comm.serial.16550");
00518                 break;
00519             case 0x03:
00520                 ds_add_capability(d, "comm.serial.16650");
00521                 break;
00522             case 0x04:
00523                 ds_add_capability(d, "comm.serial.16750");
00524                 break;
00525             case 0x05:
00526                 ds_add_capability(d, "comm.serial.16850");
00527                 break;
00528             case 0x06:
00529                 ds_add_capability(d, "comm.serial.16950");
00530                 break;
00531             }
00532         }
00533         else if( dev_sub_class==0x01 )
00534         {
00535             cat = "comm.parallel";
00536             ds_add_capability(d, "comm.parallel");
00537             switch( dev_proto)
00538             {
00539             case 0x00:
00540                 ds_add_capability(d, "comm.parallel.spp");
00541                 break;
00542             case 0x01:
00543                 ds_add_capability(d, "comm.parallel.bidir");
00544                 break;
00545             case 0x02:
00546                 ds_add_capability(d, "comm.parallel.ecp");
00547                 break;
00548             case 0x03:
00549                 ds_add_capability(d, "comm.parallel.ieee1284");
00550                 break;
00551             case 0xfe:
00552                 ds_add_capability(d, "comm.parallel.ieee1284_target");
00553                 break;
00554             }
00555         }
00556         else if( dev_sub_class==0x02 )
00557         {
00558             cat = "comm.serial";
00559             ds_add_capability(d, "comm.serial");
00560             ds_add_capability(d, "comm.serial.multiport");
00561         }
00562         else if( dev_sub_class==0x03 )
00563         {
00564             cat = "modem";
00565             ds_add_capability(d, "modem");
00566             if( dev_proto>=0x01 && dev_proto<=0x04 )
00567                 ds_add_capability(d, "modem.hayes");
00568         }
00569         break;
00570     case 0x0c:
00571         cat = "serial_controller";
00572         ds_add_capability(d, "serial_controller");
00573         switch( dev_sub_class)
00574         {
00575         case 0x00:
00576             cat = "serial_controller.ieee1394";
00577             ds_add_capability(d, "serial_controller.ieee1394");
00578             if( dev_proto==0x10 )
00579                 ds_add_capability(d, "serial_controller.ieee1394.ohci");
00580             break;
00581         case 0x01:
00582             ds_add_capability(d, "serial_controller.access");
00583             break;
00584         case 0x02:
00585             ds_add_capability(d, "serial_controller.ssa");
00586             break;
00587         case 0x03:
00588             cat = "serial_controller.usb";
00589             ds_add_capability(d, "serial_controller.usb");
00590             switch( dev_proto )
00591             {
00592             case 0x00:
00593                 ds_add_capability(d, "serial_controller.usb.uhci");
00594                 break;
00595             case 0x01:
00596                 ds_add_capability(d, "serial_controller.usb.ohci");
00597                 break;
00598             case 0x02:
00599                 ds_add_capability(d, "serial_controller.usb.ehci");
00600                 break;
00601             case 0xfe:
00602                 ds_add_capability(d, "serial_controller.usb.device");
00603                 break;
00604             }
00605             break;
00606         }
00607         break;
00608     case 0x0d:
00609         cat = "wireless";
00610         ds_add_capability(d, "wireless");
00611         switch( dev_sub_class)
00612         {
00613         case 0x00:
00614             ds_add_capability(d, "wireless.irda");
00615             break;
00616         case 0x01:
00617             ds_add_capability(d, "wireless.consumer_controller");
00618             break;
00619         case 0x02:
00620             ds_add_capability(d, "wireless.rf_controller");
00621             break;
00622         }
00623         break;
00624     case 0x0f:
00625         cat = "satellite_controller";
00626         ds_add_capability(d, "satellite_controller");
00627         switch( dev_sub_class)
00628         {
00629         case 0x00:
00630             ds_add_capability(d, "satellite_controller.tv");
00631             break;
00632         case 0x01:
00633             ds_add_capability(d, "satellite_controller.audio");
00634             break;
00635         case 0x02:
00636             ds_add_capability(d, "satellite_controller.video");
00637             break;
00638         case 0x03:
00639             ds_add_capability(d, "satellite_controller.data");
00640             break;
00641         }
00642         break;
00643     }
00644 
00645     if( cat!=NULL )
00646         ds_property_set_string(d, "info.category", cat);
00647 }
00648 
00649 
00650 /* fwd decl */
00651 static void visit_device_pci_got_parent(HalDevice* parent, 
00652                                         void* data1, void* data2);
00653 
00662 void visit_device_pci(const char* path, struct sysfs_device *device)
00663 {
00664     int i;
00665     int len;
00666     HalDevice* d;
00667     char attr_name[SYSFS_NAME_LEN];
00668     struct sysfs_attribute* cur;
00669     int vendor_id=0;
00670     int product_id=0;
00671     int subsys_vendor_id=0;
00672     int subsys_product_id=0;
00673     char* vendor_name;
00674     char* product_name;
00675     char* subsys_vendor_name;
00676     char* subsys_product_name;
00677     const char* driver;
00678     dbus_int32_t cls = 0x00ffffff;
00679     char namebuf[512];
00680     char* parent_sysfs_path;
00681 
00682     /*printf("pci: %s\n", path);*/
00683 
00684     /* Must be a new PCI device */
00685     d = ds_device_new();
00686     ds_property_set_string(d, "info.bus", "pci");
00687     ds_property_set_string(d, "linux.sysfs_path", path);
00688     ds_property_set_string(d, "linux.sysfs_path_device", path);
00693     ds_property_set_string(d, "pci.linux.sysfs_path", path);
00694     /*printf("*** created udi=%s for path=%s\n", d, path);*/
00695 
00696     /* set driver */
00697     driver = drivers_lookup(path);
00698     if( driver!=NULL )
00699         ds_property_set_string(d, "linux.driver", driver);
00700 
00701     dlist_for_each_data(sysfs_get_device_attributes(device), cur,
00702                         struct sysfs_attribute)
00703     {
00704         
00705         if( sysfs_get_name_from_path(cur->path, 
00706                                      attr_name, SYSFS_NAME_LEN) != 0 )
00707             continue;
00708         
00709         /* strip whitespace */
00710         len = strlen(cur->value);
00711         for(i=len-1; isspace(cur->value[i]); --i)
00712             cur->value[i] = '\0';
00713         
00714         /*printf("attr_name=%s -> '%s'\n", attr_name, cur->value);*/
00715         
00716         if( strcmp(attr_name, "device")==0 )
00717             product_id = parse_hex(cur->value);
00718         else if( strcmp(attr_name, "vendor")==0 )
00719             vendor_id = parse_hex(cur->value);
00720         else if( strcmp(attr_name, "subsystem_device")==0 )
00721             subsys_product_id = parse_hex(cur->value);
00722         else if( strcmp(attr_name, "subsystem_vendor")==0 )
00723             subsys_vendor_id = parse_hex(cur->value);
00724         else if( strcmp(attr_name, "class")==0 )
00725         {
00726             cls = parse_hex(cur->value);
00727         }
00728     }
00729 
00730     ds_property_set_int(d, "pci.vendor_id", vendor_id);
00731     ds_property_set_int(d, "pci.product_id", product_id);
00732     ds_property_set_int(d, "pci.subsys_vendor_id", subsys_vendor_id);
00733     ds_property_set_int(d, "pci.subsys_product_id",subsys_product_id);
00734 
00735     /* Lookup names in pci.ids */
00736     pci_ids_find(vendor_id, product_id, subsys_vendor_id, subsys_product_id,
00737                  &vendor_name, &product_name, 
00738                  &subsys_vendor_name, &subsys_product_name);
00739     if( vendor_name!=NULL )
00740         ds_property_set_string(d, "pci.vendor", vendor_name);
00741     if( product_name!=NULL )
00742         ds_property_set_string(d, "pci.product", product_name);
00743     if( subsys_vendor_name!=NULL )
00744         ds_property_set_string(d, "pci.subsys_vendor", subsys_vendor_name);
00745     if( subsys_product_name!=NULL )
00746         ds_property_set_string(d, "pci.subsys_product", subsys_product_name);
00747 
00748     /* Provide best-guess of name, goes in Product property; 
00749      * .fdi files can override this */
00750     if( product_name!=NULL )
00751     {
00752         ds_property_set_string(d, "info.product", product_name);
00753     }
00754     else
00755     {
00756         snprintf(namebuf, 512, "Unknown (0x%04x)", product_id);
00757         ds_property_set_string(d, "info.product", namebuf);
00758     }
00759 
00760     /* Provide best-guess of vendor, goes in Vendor property; 
00761      * .fdi files can override this */
00762     if( vendor_name!=NULL )
00763     {
00764         ds_property_set_string(d, "info.vendor", vendor_name);
00765     }
00766     else
00767     {
00768         snprintf(namebuf, 512, "Unknown (0x%04x)", vendor_id);
00769         ds_property_set_string(d, "info.vendor", namebuf);
00770     }
00771 
00772 
00773     ds_property_set_int(d, "pci.device_class", (cls>>16)&0xff);
00774     ds_property_set_int(d, "pci.device_subclass",(cls>>8)&0xff);
00775     ds_property_set_int(d, "pci.device_protocol", cls&0xff);
00776     pci_add_caps_from_class(d, (cls>>16)&0xff, (cls>>8)&0xff, cls&0xff);
00777 
00778     parent_sysfs_path = get_parent_sysfs_path(path);
00779 
00780     /* Find parent; this happens asynchronously as our parent might
00781      * be added later. If we are probing this can't happen so the
00782      * timeout is set to zero in that event..
00783      */
00784     ds_device_async_find_by_key_value_string("linux.sysfs_path_device",
00785                                              parent_sysfs_path, 
00786                                              TRUE,
00787                                              visit_device_pci_got_parent,
00788                                              (void*) d, NULL, 
00789                                              is_probing ? 0 :
00790                                              HAL_LINUX_HOTPLUG_TIMEOUT);
00791 
00792     free(parent_sysfs_path);
00793 }
00794 
00802 static void visit_device_pci_got_parent(HalDevice* parent, 
00803                                         void* data1, void* data2)
00804 {
00805     char* new_udi = NULL;
00806     HalDevice* new_d = NULL;
00807     HalDevice* d = (HalDevice*) data1;
00808 
00809     if( parent!=NULL )
00810     {
00811         ds_property_set_string(d, "info.parent", parent->udi);
00812     }
00813 
00814     /* Compute a proper UDI (unique device id) and try to locate a persistent
00815      * unplugged device or simple add this new device...
00816      */
00817     new_udi = rename_and_merge(d, pci_compute_udi, "pci");
00818     if( new_udi!=NULL )
00819     {
00820         new_d = ds_device_find(new_udi);
00821         if( new_d!=NULL )
00822         {
00823             ds_gdl_add(new_d);
00824         }
00825     }
00826 }
00827 
00828 
00832 void linux_pci_init()
00833 {
00834     /* get all drivers under /sys/bus/pci/drivers */
00835     drivers_collect("pci");
00836 
00837     /* Load /usr/share/hwdata/pci.ids */
00838     pci_ids_load(HWDATA_DIR "/pci.ids");
00839 }
00840 
00845 void linux_pci_detection_done()
00846 {
00847 }
00848 
00852 void linux_pci_shutdown()
00853 {
00854     pci_ids_free();
00855 }
00856 

Generated on Sat Feb 7 22:11:47 2004 for HAL by doxygen 1.3.5