1 /* 2 * The PCI Library -- Initialization and related things 3 * 4 * Copyright (c) 1997--2008 Martin Mares <[email protected]> 5 * 6 * Can be freely distributed and used under the terms of the GNU GPL. 7 */ 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <stdarg.h> 12 #include <string.h> 13 14 #include "internal.h" 15 16 static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = { 17 NULL, 18 #ifdef PCI_HAVE_PM_LINUX_SYSFS 19 &pm_linux_sysfs, 20 #else 21 NULL, 22 #endif 23 #ifdef PCI_HAVE_PM_LINUX_PROC 24 &pm_linux_proc, 25 #else 26 NULL, 27 #endif 28 #ifdef PCI_HAVE_PM_INTEL_CONF 29 &pm_intel_conf1, 30 &pm_intel_conf2, 31 #else 32 NULL, 33 NULL, 34 #endif 35 #ifdef PCI_HAVE_PM_FBSD_DEVICE 36 &pm_fbsd_device, 37 #else 38 NULL, 39 #endif 40 #ifdef PCI_HAVE_PM_AIX_DEVICE 41 &pm_aix_device, 42 #else 43 NULL, 44 #endif 45 #ifdef PCI_HAVE_PM_NBSD_LIBPCI 46 &pm_nbsd_libpci, 47 #else 48 NULL, 49 #endif 50 #ifdef PCI_HAVE_PM_OBSD_DEVICE 51 &pm_obsd_device, 52 #else 53 NULL, 54 #endif 55 #ifdef PCI_HAVE_PM_DUMP 56 &pm_dump, 57 #else 58 NULL, 59 #endif 60 }; 61 62 void * 63 pci_malloc(struct pci_access *a, int size) 64 { 65 void *x = malloc(size); 66 67 if (!x) 68 a->error("Out of memory (allocation of %d bytes failed)", size); 69 return x; 70 } 71 72 void 73 pci_mfree(void *x) 74 { 75 if (x) 76 free(x); 77 } 78 79 char * 80 pci_strdup(struct pci_access *a, char *s) 81 { 82 int len = strlen(s) + 1; 83 char *t = pci_malloc(a, len); 84 memcpy(t, s, len); 85 return t; 86 } 87 88 static void 89 pci_generic_error(char *msg, ...) 90 { 91 va_list args; 92 93 va_start(args, msg); 94 fputs("pcilib: ", stderr); 95 vfprintf(stderr, msg, args); 96 fputc('\n', stderr); 97 exit(1); 98 } 99 100 static void 101 pci_generic_warn(char *msg, ...) 102 { 103 va_list args; 104 105 va_start(args, msg); 106 fputs("pcilib: ", stderr); 107 vfprintf(stderr, msg, args); 108 fputc('\n', stderr); 109 } 110 111 static void 112 pci_generic_debug(char *msg, ...) 113 { 114 va_list args; 115 116 va_start(args, msg); 117 vfprintf(stdout, msg, args); 118 va_end(args); 119 } 120 121 static void 122 pci_null_debug(char *msg UNUSED, ...) 123 { 124 } 125 126 int 127 pci_lookup_method(char *name) 128 { 129 int i; 130 131 for (i=0; i<PCI_ACCESS_MAX; i++) 132 if (pci_methods[i] && !strcmp(pci_methods[i]->name, name)) 133 return i; 134 return -1; 135 } 136 137 char * 138 pci_get_method_name(int index) 139 { 140 if (index < 0 || index >= PCI_ACCESS_MAX) 141 return NULL; 142 else if (!pci_methods[index]) 143 return ""; 144 else 145 return pci_methods[index]->name; 146 } 147 148 struct pci_access * 149 pci_alloc(void) 150 { 151 struct pci_access *a = malloc(sizeof(struct pci_access)); 152 int i; 153 154 memset(a, 0, sizeof(*a)); 155 pci_set_name_list_path(a, PCI_PATH_IDS_DIR "/" PCI_IDS, 0); 156 #ifdef PCI_USE_DNS 157 pci_define_param(a, "net.domain", PCI_ID_DOMAIN, "DNS domain used for resolving of ID's"); 158 pci_define_param(a, "net.cache_name", "~/.pciids-cache", "Name of the ID cache file"); 159 a->id_lookup_mode = PCI_LOOKUP_CACHE; 160 #endif 161 for (i=0; i<PCI_ACCESS_MAX; i++) 162 if (pci_methods[i] && pci_methods[i]->config) 163 pci_methods[i]->config(a); 164 return a; 165 } 166 167 void 168 pci_init(struct pci_access *a) 169 { 170 if (!a->error) 171 a->error = pci_generic_error; 172 if (!a->warning) 173 a->warning = pci_generic_warn; 174 if (!a->debug) 175 a->debug = pci_generic_debug; 176 if (!a->debugging) 177 a->debug = pci_null_debug; 178 179 if (a->method) 180 { 181 if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method]) 182 a->error("This access method is not supported."); 183 a->methods = pci_methods[a->method]; 184 } 185 else 186 { 187 unsigned int i; 188 for (i=0; i<PCI_ACCESS_MAX; i++) 189 if (pci_methods[i]) 190 { 191 a->debug("Trying method %d...", i); 192 if (pci_methods[i]->detect(a)) 193 { 194 a->debug("...OK\n"); 195 a->methods = pci_methods[i]; 196 a->method = i; 197 break; 198 } 199 a->debug("...No.\n"); 200 } 201 if (!a->methods) 202 a->error("Cannot find any working access method."); 203 } 204 a->debug("Decided to use %s\n", a->methods->name); 205 a->methods->init(a); 206 } 207 208 void 209 pci_cleanup(struct pci_access *a) 210 { 211 struct pci_dev *d, *e; 212 213 for (d=a->devices; d; d=e) 214 { 215 e = d->next; 216 pci_free_dev(d); 217 } 218 if (a->methods) 219 a->methods->cleanup(a); 220 pci_free_name_list(a); 221 pci_free_params(a); 222 pci_set_name_list_path(a, NULL, 0); 223 pci_mfree(a); 224 } 225