summaryrefslogtreecommitdiff
path: root/lib/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/init.c')
-rw-r--r--lib/init.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/lib/init.c b/lib/init.c
new file mode 100644
index 0000000..be45f81
--- /dev/null
+++ b/lib/init.c
@@ -0,0 +1,224 @@
+/*
+ * The PCI Library -- Initialization and related things
+ *
+ * Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "internal.h"
+
+static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
+ NULL,
+#ifdef PCI_HAVE_PM_LINUX_SYSFS
+ &pm_linux_sysfs,
+#else
+ NULL,
+#endif
+#ifdef PCI_HAVE_PM_LINUX_PROC
+ &pm_linux_proc,
+#else
+ NULL,
+#endif
+#ifdef PCI_HAVE_PM_INTEL_CONF
+ &pm_intel_conf1,
+ &pm_intel_conf2,
+#else
+ NULL,
+ NULL,
+#endif
+#ifdef PCI_HAVE_PM_FBSD_DEVICE
+ &pm_fbsd_device,
+#else
+ NULL,
+#endif
+#ifdef PCI_HAVE_PM_AIX_DEVICE
+ &pm_aix_device,
+#else
+ NULL,
+#endif
+#ifdef PCI_HAVE_PM_NBSD_LIBPCI
+ &pm_nbsd_libpci,
+#else
+ NULL,
+#endif
+#ifdef PCI_HAVE_PM_OBSD_DEVICE
+ &pm_obsd_device,
+#else
+ NULL,
+#endif
+#ifdef PCI_HAVE_PM_DUMP
+ &pm_dump,
+#else
+ NULL,
+#endif
+};
+
+void *
+pci_malloc(struct pci_access *a, int size)
+{
+ void *x = malloc(size);
+
+ if (!x)
+ a->error("Out of memory (allocation of %d bytes failed)", size);
+ return x;
+}
+
+void
+pci_mfree(void *x)
+{
+ if (x)
+ free(x);
+}
+
+char *
+pci_strdup(struct pci_access *a, char *s)
+{
+ int len = strlen(s) + 1;
+ char *t = pci_malloc(a, len);
+ memcpy(t, s, len);
+ return t;
+}
+
+static void
+pci_generic_error(char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ fputs("pcilib: ", stderr);
+ vfprintf(stderr, msg, args);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+static void
+pci_generic_warn(char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ fputs("pcilib: ", stderr);
+ vfprintf(stderr, msg, args);
+ fputc('\n', stderr);
+}
+
+static void
+pci_generic_debug(char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ vfprintf(stdout, msg, args);
+ va_end(args);
+}
+
+static void
+pci_null_debug(char *msg UNUSED, ...)
+{
+}
+
+int
+pci_lookup_method(char *name)
+{
+ int i;
+
+ for (i=0; i<PCI_ACCESS_MAX; i++)
+ if (pci_methods[i] && !strcmp(pci_methods[i]->name, name))
+ return i;
+ return -1;
+}
+
+char *
+pci_get_method_name(int index)
+{
+ if (index < 0 || index >= PCI_ACCESS_MAX)
+ return NULL;
+ else if (!pci_methods[index])
+ return "";
+ else
+ return pci_methods[index]->name;
+}
+
+struct pci_access *
+pci_alloc(void)
+{
+ struct pci_access *a = malloc(sizeof(struct pci_access));
+ int i;
+
+ memset(a, 0, sizeof(*a));
+ pci_set_name_list_path(a, PCI_PATH_IDS_DIR "/" PCI_IDS, 0);
+#ifdef PCI_USE_DNS
+ pci_define_param(a, "net.domain", PCI_ID_DOMAIN, "DNS domain used for resolving of ID's");
+ pci_define_param(a, "net.cache_name", "~/.pciids-cache", "Name of the ID cache file");
+ a->id_lookup_mode = PCI_LOOKUP_CACHE;
+#endif
+ for(i=0; i<PCI_ACCESS_MAX; i++)
+ if (pci_methods[i] && pci_methods[i]->config)
+ pci_methods[i]->config(a);
+ return a;
+}
+
+void
+pci_init(struct pci_access *a)
+{
+ if (!a->error)
+ a->error = pci_generic_error;
+ if (!a->warning)
+ a->warning = pci_generic_warn;
+ if (!a->debug)
+ a->debug = pci_generic_debug;
+ if (!a->debugging)
+ a->debug = pci_null_debug;
+
+ if (a->method)
+ {
+ if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method])
+ a->error("This access method is not supported.");
+ a->methods = pci_methods[a->method];
+ }
+ else
+ {
+ unsigned int i;
+ for(i=0; i<PCI_ACCESS_MAX; i++)
+ if (pci_methods[i])
+ {
+ a->debug("Trying method %d...", i);
+ if (pci_methods[i]->detect(a))
+ {
+ a->debug("...OK\n");
+ a->methods = pci_methods[i];
+ a->method = i;
+ break;
+ }
+ a->debug("...No.\n");
+ }
+ if (!a->methods)
+ a->error("Cannot find any working access method.");
+ }
+ a->debug("Decided to use %s\n", a->methods->name);
+ a->methods->init(a);
+}
+
+void
+pci_cleanup(struct pci_access *a)
+{
+ struct pci_dev *d, *e;
+
+ for(d=a->devices; d; d=e)
+ {
+ e = d->next;
+ pci_free_dev(d);
+ }
+ if (a->methods)
+ a->methods->cleanup(a);
+ pci_free_name_list(a);
+ pci_free_params(a);
+ pci_set_name_list_path(a, NULL, 0);
+ pci_mfree(a);
+}