summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am10
-rw-r--r--src/bios_dev_name.c35
-rw-r--r--src/bios_dev_name.h1
-rw-r--r--src/bios_device.c156
-rw-r--r--src/bios_device.h10
-rw-r--r--src/cistpl.h605
-rw-r--r--src/dmidecode/dmidecode.c107
-rw-r--r--src/dmidecode/dmidecode.h13
-rw-r--r--src/dmidecode/dmioem.c1
-rw-r--r--src/dmidecode/util.c3
-rw-r--r--src/eths.c3
-rw-r--r--src/libbiosdevname.h11
-rw-r--r--src/naming_policy.c130
-rw-r--r--src/naming_policy.h2
-rw-r--r--src/parse_cis.c882
-rw-r--r--src/pci.c526
-rw-r--r--src/pci.h38
-rw-r--r--src/pcmcia.c295
-rw-r--r--src/pcmcia.h35
-rw-r--r--src/pirq.c10
-rw-r--r--src/read-cis.c275
-rw-r--r--src/read_proc.c6
-rw-r--r--src/state.h5
-rw-r--r--src/sysfs.c68
-rw-r--r--src/sysfs.h2
25 files changed, 763 insertions, 2466 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 5d3562c..aedc2fd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,6 @@
INCLUDES = -I..
AM_CFLAGS = -Wall -fno-strict-aliasing
-srcPath=src/
man_MANS = biosdevname.1
sbin_PROGRAMS = src/biosdevname src/biosdevnameS
@@ -13,9 +12,7 @@ src_biosdevname_SOURCES = \
src/eths.c \
src/read_proc.c \
src/naming_policy.c \
- src/pcmcia.c \
- src/read-cis.c \
- src/parse_cis.c \
+ src/sysfs.c \
src/dmidecode/dmidecode.c \
src/dmidecode/dmioem.c \
src/dmidecode/util.c
@@ -23,7 +20,7 @@ src_biosdevname_SOURCES = \
src_biosdevnameS_SOURCES = $(src_biosdevname_SOURCES)
src_biosdevnameS_LDFLAGS = -all-static
-EXTRA_DIST = \
+EXTRA_DIST += \
src/bios_dev_name.h \
src/bios_device.h \
src/pirq.h \
@@ -33,9 +30,8 @@ EXTRA_DIST = \
src/ethtool-copy.h \
src/list.h \
src/naming_policy.h \
- src/pcmcia.h \
- src/cistpl.h \
src/state.h \
+ src/sysfs.h \
src/libbiosdevname.h \
src/dmidecode/config.h \
src/dmidecode/dmidecode.h \
diff --git a/src/bios_dev_name.c b/src/bios_dev_name.c
index ce13742..5757363 100644
--- a/src/bios_dev_name.c
+++ b/src/bios_dev_name.c
@@ -19,27 +19,23 @@ static void usage(void)
fprintf(stderr, " Options:\n");
fprintf(stderr, " -i or --interface treat [args] as ethernet devs\n");
fprintf(stderr, " -d or --debug enable debugging\n");
- fprintf(stderr, " -n or --nosort don't sort the PCI device list breadth-first\n");
- fprintf(stderr, " --policy [kernelnames | all_ethN | all_names | embedded_ethN_slots_names]\n");
+ fprintf(stderr, " --policy [physical | all_ethN ]\n");
+ fprintf(stderr, " --prefix [string] string use for embedded NICs (default='em')\n");
fprintf(stderr, " Example: biosdevname -i eth0\n");
- fprintf(stderr, " returns: eth0\n");
- fprintf(stderr, " when the BIOS name and kernel name are both eth0.\n");
- fprintf(stderr, " --nosort implies --policy kernelnames.\n");
+ fprintf(stderr, " returns: em1\n");
+ fprintf(stderr, " when eth0 is an embedded NIC with label '1' on the chassis.\n");
fprintf(stderr, " You must be root to run this, as it must read from /dev/mem.\n");
}
static int
set_policy(const char *arg)
{
- int rc = all_ethN;
- if (!strncmp("kernelnames", arg, sizeof("kernelnames")))
- rc = kernelnames;
+ int rc = physical;
+
+ if (!strncmp("physical", arg, sizeof("physical")))
+ rc = physical;
else if (!strncmp("all_ethN", arg, sizeof("all_ethN")))
rc = all_ethN;
- else if (!strncmp("all_names", arg, sizeof("all_names")))
- rc = all_names;
- else if (!strncmp("embedded_ethN_slots_names", arg, sizeof("embedded_ethN_slots_names")))
- rc = embedded_ethN_slots_names;
return rc;
}
@@ -55,8 +51,8 @@ parse_opts(int argc, char **argv)
{
{"debug", no_argument, 0, 'd'},
{"interface", no_argument, 0, 'i'},
- {"nosort", no_argument, 0, 'n'},
{"policy", required_argument, 0, 'p'},
+ {"prefix", required_argument, 0, 'P'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
@@ -71,12 +67,12 @@ parse_opts(int argc, char **argv)
case 'i':
opts.interface = 1;
break;
- case 'n':
- opts.sortroutine = nosort;
- break;
case 'p':
opts.namingpolicy = set_policy(optarg);
break;
+ case 'P':
+ opts.prefix = optarg;
+ break;
default:
usage();
exit(1);
@@ -89,8 +85,8 @@ parse_opts(int argc, char **argv)
opts.optind = optind;
}
- if (opts.sortroutine == nosort)
- opts.namingpolicy = kernelnames;
+ if (opts.prefix == NULL)
+ opts.prefix = "em";
}
int main(int argc, char *argv[])
@@ -100,9 +96,8 @@ int main(int argc, char *argv[])
void *cookie = NULL;
parse_opts(argc, argv);
- cookie = setup_bios_devices(opts.sortroutine, opts.namingpolicy);
+ cookie = setup_bios_devices(opts.namingpolicy, opts.prefix);
if (!cookie) {
- usage();
rc = 1;
goto out;
}
diff --git a/src/bios_dev_name.h b/src/bios_dev_name.h
index 658bfa3..fd4f7f6 100644
--- a/src/bios_dev_name.h
+++ b/src/bios_dev_name.h
@@ -12,6 +12,7 @@ struct bios_dev_name_opts {
int optind;
int sortroutine;
int namingpolicy;
+ const char *prefix;
unsigned int verbose:1;
unsigned int show_all:1;
unsigned int debug:1;
diff --git a/src/bios_device.c b/src/bios_device.c
index 5c275c8..24b0a77 100644
--- a/src/bios_device.c
+++ b/src/bios_device.c
@@ -6,12 +6,12 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <pci/pci.h>
#include <net/if.h>
#include "list.h"
#include "bios_device.h"
#include "state.h"
#include "libbiosdevname.h"
-#include "dmidecode/dmidecode.h"
void free_bios_devices(void *cookie)
{
@@ -28,8 +28,9 @@ void free_bios_devices(void *cookie)
static void unparse_bios_device(struct bios_device *dev)
{
- char buf[200];
- printf("BIOS device: %s\n", dev->bios_name);
+ char buf[8192];
+ memset(buf, 0, sizeof(buf));
+ printf("BIOS device: %s\n", dev->bios_name ? dev->bios_name : "");
if (dev->netdev) {
unparse_network_device(buf, sizeof(buf), dev->netdev);
printf("%s", buf);
@@ -41,12 +42,9 @@ static void unparse_bios_device(struct bios_device *dev)
unparse_pci_device(buf, sizeof(buf), dev->pcidev);
printf("%s", buf);
}
- else if (is_pcmcia(dev)) {
- unparse_pcmcia_device(buf, sizeof(buf), dev->pcmciadev);
- printf("%s", buf);
- }
-
printf("\n");
+ if (dev->duplicate)
+ printf("Duplicate: True\n");
}
void unparse_bios_devices(void *cookie)
@@ -82,8 +80,11 @@ char * kern_to_bios(void *cookie,
if (!state)
return NULL;
list_for_each_entry(dev, &state->bios_devices, node) {
- if (dev->netdev && !strcmp(dev->netdev->kernel_name, name))
+ if (dev->netdev && !strcmp(dev->netdev->kernel_name, name)) {
+ if (dev->duplicate)
+ return NULL;
return dev->bios_name;
+ }
}
return NULL;
}
@@ -116,17 +117,17 @@ static int sort_pci(const struct bios_device *bdev_a, const struct bios_device *
if (a->physical_slot < b->physical_slot) return -1;
else if (a->physical_slot > b->physical_slot) return 1;
- if (a->pci_dev.domain < b->pci_dev.domain) return -1;
- else if (a->pci_dev.domain > b->pci_dev.domain) return 1;
+ if (a->pci_dev->domain < b->pci_dev->domain) return -1;
+ else if (a->pci_dev->domain > b->pci_dev->domain) return 1;
- if (a->pci_dev.bus < b->pci_dev.bus) return -1;
- else if (a->pci_dev.bus > b->pci_dev.bus) return 1;
+ if (a->pci_dev->bus < b->pci_dev->bus) return -1;
+ else if (a->pci_dev->bus > b->pci_dev->bus) return 1;
- if (a->pci_dev.dev < b->pci_dev.dev) return -1;
- else if (a->pci_dev.dev > b->pci_dev.dev) return 1;
+ if (a->pci_dev->dev < b->pci_dev->dev) return -1;
+ else if (a->pci_dev->dev > b->pci_dev->dev) return 1;
- if (a->pci_dev.func < b->pci_dev.func) return -1;
- else if (a->pci_dev.func > b->pci_dev.func) return 1;
+ if (a->pci_dev->func < b->pci_dev->func) return -1;
+ else if (a->pci_dev->func > b->pci_dev->func) return 1;
return 0;
}
@@ -155,24 +156,8 @@ static int sort_smbios(const struct bios_device *x, const struct bios_device *y)
return sort_pci(x, y);
}
-
-static int sort_pcmcia(const struct bios_device *bdev_a, const struct bios_device *bdev_b)
-{
- const struct pcmcia_device *a = bdev_a->pcmciadev;
- const struct pcmcia_device *b = bdev_b->pcmciadev;
-
- if (a->socket < b->socket) return -1;
- else if (a->socket > b->socket) return 1;
-
- if (a->function < b->function) return -1;
- else if (a->function > b->function) return 1;
-
- return 0;
-}
-
enum bios_device_types {
IS_PCI,
- IS_PCMCIA,
IS_UNKNOWN_TYPE,
};
@@ -180,8 +165,6 @@ static int bios_device_type_num(const struct bios_device *dev)
{
if (is_pci(dev))
return IS_PCI;
- else if (is_pcmcia(dev))
- return IS_PCMCIA;
return IS_UNKNOWN_TYPE;
}
@@ -192,8 +175,6 @@ static int sort_by_type(const struct bios_device *a, const struct bios_device *b
else if (bios_device_type_num(a) == bios_device_type_num(b)) {
if (is_pci(a))
return sort_smbios(a, b);
- else if (is_pcmcia(a))
- return sort_pcmcia(a, b);
else return 0;
}
else if (bios_device_type_num(a) > bios_device_type_num(b))
@@ -215,24 +196,6 @@ static void insertion_sort_devices(struct bios_device *a, struct list_head *list
list_move_tail(&a->node, list);
}
-static int set_slot_index(struct libbiosdevname_state *state)
-{
- struct bios_device *dev;
- int prevslot=-1;
- int index=0;
-
- list_for_each_entry(dev, &state->bios_devices, node) {
- if (!dev->pcidev)
- continue;
- if (dev->pcidev->physical_slot != prevslot)
- index=0;
- else
- index++;
- dev->pcidev->index_in_slot = index;
- prevslot = dev->pcidev->physical_slot;
- }
- return 0;
-}
static void sort_device_list(struct libbiosdevname_state *state)
{
@@ -242,7 +205,6 @@ static void sort_device_list(struct libbiosdevname_state *state)
insertion_sort_devices(dev, &sorted_devices, sort_by_type);
}
list_splice(&sorted_devices, &state->bios_devices);
- set_slot_index(state);
}
static void match_eth_and_pci_devs(struct libbiosdevname_state *state)
@@ -256,7 +218,7 @@ static void match_eth_and_pci_devs(struct libbiosdevname_state *state)
if (!is_pci_network(p))
continue;
- unparse_pci_name(pci_name, sizeof(pci_name), &p->pci_dev);
+ unparse_pci_name(pci_name, sizeof(pci_name), p->pci_dev);
n = find_net_device_by_bus_info(state, pci_name);
if (!n)
continue;
@@ -273,32 +235,6 @@ static void match_eth_and_pci_devs(struct libbiosdevname_state *state)
}
}
-static void match_eth_and_pcmcia(struct libbiosdevname_state *state)
-{
- struct pcmcia_device *p;
- struct bios_device *b;
- char pcmcia_name[40];
-
- list_for_each_entry(p, &state->pcmcia_devices, node) {
- if (!is_pcmcia_network(p))
- continue;
-
- b = malloc(sizeof(*b));
- if (!b)
- continue;
- memset(b, 0, sizeof(*b));
- INIT_LIST_HEAD(&b->node);
- b->pcmciadev = p;
-
- unparse_pcmcia_name(pcmcia_name, sizeof(pcmcia_name), p);
- b->netdev = find_net_device_by_bus_info(state, pcmcia_name);
-
- memset(b->bios_name, 0, sizeof(b->bios_name));
- claim_netdev(b->netdev);
- list_add(&b->node, &state->bios_devices);
- }
-}
-
static void match_unknown_eths(struct libbiosdevname_state *state)
{
struct bios_device *b;
@@ -325,7 +261,6 @@ static void match_unknown_eths(struct libbiosdevname_state *state)
static void match_all(struct libbiosdevname_state *state)
{
match_eth_and_pci_devs(state);
- match_eth_and_pcmcia(state);
match_unknown_eths(state);
}
@@ -338,7 +273,8 @@ static struct libbiosdevname_state * alloc_state(void)
INIT_LIST_HEAD(&state->bios_devices);
INIT_LIST_HEAD(&state->pci_devices);
INIT_LIST_HEAD(&state->network_devices);
- INIT_LIST_HEAD(&state->pcmcia_devices);
+ state->pacc = NULL;
+ state->pirq_table = NULL;
return state;
}
@@ -349,11 +285,41 @@ void cleanup_bios_devices(void *cookie)
return;
free_bios_devices(state);
free_eths(state);
- free_pcmcia_devices(state);
free_pci_devices(state);
+ if (state->pacc)
+ pci_cleanup(state->pacc);
+ if (state->pirq_table)
+ pirq_free_table(state->pirq_table);
+}
+
+static int duplicates(struct bios_device *a, struct bios_device *b)
+{
+ int lenA = -1, lenB = -1, rc = -1;
+ if (a->bios_name)
+ lenA = strlen(a->bios_name);
+ if (b->bios_name)
+ lenB = strlen(b->bios_name);
+ if (lenA == lenB && lenA > 0)
+ rc = strncmp(a->bios_name, b->bios_name, lenA);
+ return !rc;
}
-void * setup_bios_devices(int sortroutine, int namingpolicy)
+static void find_duplicates(struct libbiosdevname_state *state)
+{
+ struct bios_device *a = NULL, *b = NULL;
+ list_for_each_entry(a, &state->bios_devices, node) {
+ list_for_each_entry(b, &state->bios_devices, node) {
+ if (a == b)
+ continue;
+ if (duplicates(a, b)) {
+ a->duplicate = 1;
+ b->duplicate = 1;
+ }
+ }
+ }
+}
+
+void * setup_bios_devices(int namingpolicy, const char *prefix)
{
int rc=1;
struct libbiosdevname_state *state = alloc_state();
@@ -365,18 +331,13 @@ void * setup_bios_devices(int sortroutine, int namingpolicy)
if (rc)
goto out;
- rc = get_pcmcia_devices(state);
- if (rc)
- goto out;
- rc = dmidecode_main(state);
- if (rc)
- goto out;
get_eths(state);
match_all(state);
- if (sortroutine != nosort) {
- sort_device_list(state);
- }
- assign_bios_network_names(state, sortroutine, namingpolicy);
+ sort_device_list(state);
+ rc = assign_bios_network_names(state, namingpolicy, prefix);
+ if (rc)
+ goto out;
+ find_duplicates(state);
return state;
out:
@@ -384,4 +345,3 @@ out:
free(state);
return NULL;
}
-
diff --git a/src/bios_device.h b/src/bios_device.h
index 8e76e1a..690ed6f 100644
--- a/src/bios_device.h
+++ b/src/bios_device.h
@@ -10,7 +10,6 @@
#include "list.h"
#include "eths.h"
#include "pci.h"
-#include "pcmcia.h"
#include "naming_policy.h"
@@ -18,8 +17,8 @@ struct bios_device {
struct list_head node;
struct network_device *netdev;
struct pci_device *pcidev;
- struct pcmcia_device *pcmciadev;
- char bios_name[IFNAMSIZ];
+ char *bios_name;
+ int duplicate;
};
static inline int is_pci(const struct bios_device *dev)
@@ -27,9 +26,4 @@ static inline int is_pci(const struct bios_device *dev)
return dev->pcidev != NULL;
}
-static inline int is_pcmcia(const struct bios_device *dev)
-{
- return dev->pcmciadev != NULL;
-}
-
#endif /* BIOS_DEVICE_H_INCLUDED */
diff --git a/src/cistpl.h b/src/cistpl.h
deleted file mode 100644
index 8a2f270..0000000
--- a/src/cistpl.h
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * cistpl.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * (C) 1999 David A. Hinds
- */
-
-#ifndef _LINUX_CISTPL_H
-#define _LINUX_CISTPL_H
-
-#define CISTPL_NULL 0x00
-#define CISTPL_DEVICE 0x01
-#define CISTPL_LONGLINK_CB 0x02
-#define CISTPL_INDIRECT 0x03
-#define CISTPL_CONFIG_CB 0x04
-#define CISTPL_CFTABLE_ENTRY_CB 0x05
-#define CISTPL_LONGLINK_MFC 0x06
-#define CISTPL_BAR 0x07
-#define CISTPL_PWR_MGMNT 0x08
-#define CISTPL_EXTDEVICE 0x09
-#define CISTPL_CHECKSUM 0x10
-#define CISTPL_LONGLINK_A 0x11
-#define CISTPL_LONGLINK_C 0x12
-#define CISTPL_LINKTARGET 0x13
-#define CISTPL_NO_LINK 0x14
-#define CISTPL_VERS_1 0x15
-#define CISTPL_ALTSTR 0x16
-#define CISTPL_DEVICE_A 0x17
-#define CISTPL_JEDEC_C 0x18
-#define CISTPL_JEDEC_A 0x19
-#define CISTPL_CONFIG 0x1a
-#define CISTPL_CFTABLE_ENTRY 0x1b
-#define CISTPL_DEVICE_OC 0x1c
-#define CISTPL_DEVICE_OA 0x1d
-#define CISTPL_DEVICE_GEO 0x1e
-#define CISTPL_DEVICE_GEO_A 0x1f
-#define CISTPL_MANFID 0x20
-#define CISTPL_FUNCID 0x21
-#define CISTPL_FUNCE 0x22
-#define CISTPL_SWIL 0x23
-#define CISTPL_END 0xff
-/* Layer 2 tuples */
-#define CISTPL_VERS_2 0x40
-#define CISTPL_FORMAT 0x41
-#define CISTPL_GEOMETRY 0x42
-#define CISTPL_BYTEORDER 0x43
-#define CISTPL_DATE 0x44
-#define CISTPL_BATTERY 0x45
-#define CISTPL_FORMAT_A 0x47
-/* Layer 3 tuples */
-#define CISTPL_ORG 0x46
-#define CISTPL_SPCL 0x90
-
-typedef struct cistpl_longlink_t {
- unsigned int addr;
-} cistpl_longlink_t;
-
-typedef struct cistpl_checksum_t {
- unsigned short addr;
- unsigned short len;
- unsigned char sum;
-} cistpl_checksum_t;
-
-#define CISTPL_MAX_FUNCTIONS 8
-#define CISTPL_MFC_ATTR 0x00
-#define CISTPL_MFC_COMMON 0x01
-
-typedef struct cistpl_longlink_mfc_t {
- unsigned char nfn;
- struct {
- unsigned char space;
- unsigned int addr;
- } fn[CISTPL_MAX_FUNCTIONS];
-} cistpl_longlink_mfc_t;
-
-#define CISTPL_MAX_ALTSTR_STRINGS 4
-
-typedef struct cistpl_altstr_t {
- unsigned char ns;
- unsigned char ofs[CISTPL_MAX_ALTSTR_STRINGS];
- char str[254];
-} cistpl_altstr_t;
-
-#define CISTPL_DTYPE_NULL 0x00
-#define CISTPL_DTYPE_ROM 0x01
-#define CISTPL_DTYPE_OTPROM 0x02
-#define CISTPL_DTYPE_EPROM 0x03
-#define CISTPL_DTYPE_EEPROM 0x04
-#define CISTPL_DTYPE_FLASH 0x05
-#define CISTPL_DTYPE_SRAM 0x06
-#define CISTPL_DTYPE_DRAM 0x07
-#define CISTPL_DTYPE_FUNCSPEC 0x0d
-#define CISTPL_DTYPE_EXTEND 0x0e
-
-#define CISTPL_MAX_DEVICES 4
-
-typedef struct cistpl_device_t {
- unsigned char ndev;
- struct {
- unsigned char type;
- unsigned char wp;
- unsigned int speed;
- unsigned int size;
- } dev[CISTPL_MAX_DEVICES];
-} cistpl_device_t;
-
-#define CISTPL_DEVICE_MWAIT 0x01
-#define CISTPL_DEVICE_3VCC 0x02
-
-typedef struct cistpl_device_o_t {
- unsigned char flags;
- cistpl_device_t device;
-} cistpl_device_o_t;
-
-#define CISTPL_VERS_1_MAX_PROD_STRINGS 4
-
-typedef struct cistpl_vers_1_t {
- unsigned char major;
- unsigned char minor;
- unsigned char ns;
- unsigned char ofs[CISTPL_VERS_1_MAX_PROD_STRINGS];
- char str[254];
-} cistpl_vers_1_t;
-
-typedef struct cistpl_jedec_t {
- unsigned char nid;
- struct {
- unsigned char mfr;
- unsigned char info;
- } id[CISTPL_MAX_DEVICES];
-} cistpl_jedec_t;
-
-typedef struct cistpl_manfid_t {
- unsigned short manf;
- unsigned short card;
-} cistpl_manfid_t;
-
-#define CISTPL_FUNCID_MULTI 0x00
-#define CISTPL_FUNCID_MEMORY 0x01
-#define CISTPL_FUNCID_SERIAL 0x02
-#define CISTPL_FUNCID_PARALLEL 0x03
-#define CISTPL_FUNCID_FIXED 0x04
-#define CISTPL_FUNCID_VIDEO 0x05
-#define CISTPL_FUNCID_NETWORK 0x06
-#define CISTPL_FUNCID_AIMS 0x07
-#define CISTPL_FUNCID_SCSI 0x08
-
-#define CISTPL_SYSINIT_POST 0x01
-#define CISTPL_SYSINIT_ROM 0x02
-
-typedef struct cistpl_funcid_t {
- unsigned char func;
- unsigned char sysinit;
-} cistpl_funcid_t;
-
-typedef struct cistpl_funce_t {
- unsigned char type;
- unsigned char data[0];
-} cistpl_funce_t;
-
-/*======================================================================
-
- Modem Function Extension Tuples
-
-======================================================================*/
-
-#define CISTPL_FUNCE_SERIAL_IF 0x00
-#define CISTPL_FUNCE_SERIAL_CAP 0x01
-#define CISTPL_FUNCE_SERIAL_SERV_DATA 0x02
-#define CISTPL_FUNCE_SERIAL_SERV_FAX 0x03
-#define CISTPL_FUNCE_SERIAL_SERV_VOICE 0x04
-#define CISTPL_FUNCE_SERIAL_CAP_DATA 0x05
-#define CISTPL_FUNCE_SERIAL_CAP_FAX 0x06
-#define CISTPL_FUNCE_SERIAL_CAP_VOICE 0x07
-#define CISTPL_FUNCE_SERIAL_IF_DATA 0x08
-#define CISTPL_FUNCE_SERIAL_IF_FAX 0x09
-#define CISTPL_FUNCE_SERIAL_IF_VOICE 0x0a
-
-/* UART identification */
-#define CISTPL_SERIAL_UART_8250 0x00
-#define CISTPL_SERIAL_UART_16450 0x01
-#define CISTPL_SERIAL_UART_16550 0x02
-#define CISTPL_SERIAL_UART_8251 0x03
-#define CISTPL_SERIAL_UART_8530 0x04
-#define CISTPL_SERIAL_UART_85230 0x05
-
-/* UART capabilities */
-#define CISTPL_SERIAL_UART_SPACE 0x01
-#define CISTPL_SERIAL_UART_MARK 0x02
-#define CISTPL_SERIAL_UART_ODD 0x04
-#define CISTPL_SERIAL_UART_EVEN 0x08
-#define CISTPL_SERIAL_UART_5BIT 0x01
-#define CISTPL_SERIAL_UART_6BIT 0x02
-#define CISTPL_SERIAL_UART_7BIT 0x04
-#define CISTPL_SERIAL_UART_8BIT 0x08
-#define CISTPL_SERIAL_UART_1STOP 0x10
-#define CISTPL_SERIAL_UART_MSTOP 0x20
-#define CISTPL_SERIAL_UART_2STOP 0x40
-
-typedef struct cistpl_serial_t {
- unsigned char uart_type;
- unsigned char uart_cap_0;
- unsigned char uart_cap_1;
-} cistpl_serial_t;
-
-typedef struct cistpl_modem_cap_t {
- unsigned char flow;
- unsigned char cmd_buf;
- unsigned char rcv_buf_0, rcv_buf_1, rcv_buf_2;
- unsigned char xmit_buf_0, xmit_buf_1, xmit_buf_2;
-} cistpl_modem_cap_t;
-
-#define CISTPL_SERIAL_MOD_103 0x01
-#define CISTPL_SERIAL_MOD_V21 0x02
-#define CISTPL_SERIAL_MOD_V23 0x04
-#define CISTPL_SERIAL_MOD_V22 0x08
-#define CISTPL_SERIAL_MOD_212A 0x10
-#define CISTPL_SERIAL_MOD_V22BIS 0x20
-#define CISTPL_SERIAL_MOD_V26 0x40
-#define CISTPL_SERIAL_MOD_V26BIS 0x80
-#define CISTPL_SERIAL_MOD_V27BIS 0x01
-#define CISTPL_SERIAL_MOD_V29 0x02
-#define CISTPL_SERIAL_MOD_V32 0x04
-#define CISTPL_SERIAL_MOD_V32BIS 0x08
-#define CISTPL_SERIAL_MOD_V34 0x10
-
-#define CISTPL_SERIAL_ERR_MNP2_4 0x01
-#define CISTPL_SERIAL_ERR_V42_LAPM 0x02
-
-#define CISTPL_SERIAL_CMPR_V42BIS 0x01
-#define CISTPL_SERIAL_CMPR_MNP5 0x02
-
-#define CISTPL_SERIAL_CMD_AT1 0x01
-#define CISTPL_SERIAL_CMD_AT2 0x02
-#define CISTPL_SERIAL_CMD_AT3 0x04
-#define CISTPL_SERIAL_CMD_MNP_AT 0x08
-#define CISTPL_SERIAL_CMD_V25BIS 0x10
-#define CISTPL_SERIAL_CMD_V25A 0x20
-#define CISTPL_SERIAL_CMD_DMCL 0x40
-
-typedef struct cistpl_data_serv_t {
- unsigned char max_data_0;
- unsigned char max_data_1;
- unsigned char modulation_0;
- unsigned char modulation_1;
- unsigned char error_control;
- unsigned char compression;
- unsigned char cmd_protocol;
- unsigned char escape;
- unsigned char encrypt;
- unsigned char misc_features;
- unsigned char ccitt_code[0];
-} cistpl_data_serv_t;
-
-typedef struct cistpl_fax_serv_t {
- unsigned char max_data_0;
- unsigned char max_data_1;
- unsigned char modulation;
- unsigned char encrypt;
- unsigned char features_0;
- unsigned char features_1;
- unsigned char ccitt_code[0];
-} cistpl_fax_serv_t;
-
-typedef struct cistpl_voice_serv_t {
- unsigned char max_data_0;
- unsigned char max_data_1;
-} cistpl_voice_serv_t;
-
-/*======================================================================
-
- LAN Function Extension Tuples
-
-======================================================================*/
-
-#define CISTPL_FUNCE_LAN_TECH 0x01
-#define CISTPL_FUNCE_LAN_SPEED 0x02
-#define CISTPL_FUNCE_LAN_MEDIA 0x03
-#define CISTPL_FUNCE_LAN_NODE_ID 0x04
-#define CISTPL_FUNCE_LAN_CONNECTOR 0x05
-
-/* LAN technologies */
-#define CISTPL_LAN_TECH_ARCNET 0x01
-#define CISTPL_LAN_TECH_ETHERNET 0x02
-#define CISTPL_LAN_TECH_TOKENRING 0x03
-#define CISTPL_LAN_TECH_LOCALTALK 0x04
-#define CISTPL_LAN_TECH_FDDI 0x05
-#define CISTPL_LAN_TECH_ATM 0x06
-#define CISTPL_LAN_TECH_WIRELESS 0x07
-
-typedef struct cistpl_lan_tech_t {
- unsigned char tech;
-} cistpl_lan_tech_t;
-
-typedef struct cistpl_lan_speed_t {
- unsigned int speed;
-} cistpl_lan_speed_t;
-
-/* LAN media definitions */
-#define CISTPL_LAN_MEDIA_UTP 0x01
-#define CISTPL_LAN_MEDIA_STP 0x02
-#define CISTPL_LAN_MEDIA_THIN_COAX 0x03
-#define CISTPL_LAN_MEDIA_THICK_COAX 0x04
-#define CISTPL_LAN_MEDIA_FIBER 0x05
-#define CISTPL_LAN_MEDIA_900MHZ 0x06
-#define CISTPL_LAN_MEDIA_2GHZ 0x07
-#define CISTPL_LAN_MEDIA_5GHZ 0x08
-#define CISTPL_LAN_MEDIA_DIFF_IR 0x09
-#define CISTPL_LAN_MEDIA_PTP_IR 0x0a
-
-typedef struct cistpl_lan_media_t {
- unsigned char media;
-} cistpl_lan_media_t;
-
-typedef struct cistpl_lan_node_id_t {
- unsigned char nb;
- unsigned char id[16];
-} cistpl_lan_node_id_t;
-
-typedef struct cistpl_lan_connector_t {
- unsigned char code;
-} cistpl_lan_connector_t;
-
-/*======================================================================
-
- IDE Function Extension Tuples
-
-======================================================================*/
-
-#define CISTPL_IDE_INTERFACE 0x01
-
-typedef struct cistpl_ide_interface_t {
- unsigned char interface;
-} cistpl_ide_interface_t;
-
-/* First feature byte */
-#define CISTPL_IDE_SILICON 0x04
-#define CISTPL_IDE_UNIQUE 0x08
-#define CISTPL_IDE_DUAL 0x10
-
-/* Second feature byte */
-#define CISTPL_IDE_HAS_SLEEP 0x01
-#define CISTPL_IDE_HAS_STANDBY 0x02
-#define CISTPL_IDE_HAS_IDLE 0x04
-#define CISTPL_IDE_LOW_POWER 0x08
-#define CISTPL_IDE_REG_INHIBIT 0x10
-#define CISTPL_IDE_HAS_INDEX 0x20
-#define CISTPL_IDE_IOIS16 0x40
-
-typedef struct cistpl_ide_feature_t {
- unsigned char feature1;
- unsigned char feature2;
-} cistpl_ide_feature_t;
-
-#define CISTPL_FUNCE_IDE_IFACE 0x01
-#define CISTPL_FUNCE_IDE_MASTER 0x02
-#define CISTPL_FUNCE_IDE_SLAVE 0x03
-
-/*======================================================================
-
- Configuration Table Entries
-
-======================================================================*/
-
-#define CISTPL_BAR_SPACE 0x07
-#define CISTPL_BAR_SPACE_IO 0x10
-#define CISTPL_BAR_PREFETCH 0x20
-#define CISTPL_BAR_CACHEABLE 0x40
-#define CISTPL_BAR_1MEG_MAP 0x80
-
-typedef struct cistpl_bar_t {
- unsigned char attr;
- unsigned int size;
-} cistpl_bar_t;
-
-typedef struct cistpl_config_t {
- unsigned char last_idx;
- unsigned int base;
- unsigned int rmask[4];
- unsigned char subtuples;
-} cistpl_config_t;
-
-/* These are bits in the 'present' field, and indices in 'param' */
-#define CISTPL_POWER_VNOM 0
-#define CISTPL_POWER_VMIN 1
-#define CISTPL_POWER_VMAX 2
-#define CISTPL_POWER_ISTATIC 3
-#define CISTPL_POWER_IAVG 4
-#define CISTPL_POWER_IPEAK 5
-#define CISTPL_POWER_IDOWN 6
-
-#define CISTPL_POWER_HIGHZ_OK 0x01
-#define CISTPL_POWER_HIGHZ_REQ 0x02
-
-typedef struct cistpl_power_t {
- unsigned char present;
- unsigned char flags;
- unsigned int param[7];
-} cistpl_power_t;
-
-typedef struct cistpl_timing_t {
- unsigned int wait, waitscale;
- unsigned int ready, rdyscale;
- unsigned int reserved, rsvscale;
-} cistpl_timing_t;
-
-#define CISTPL_IO_LINES_MASK 0x1f
-#define CISTPL_IO_8BIT 0x20
-#define CISTPL_IO_16BIT 0x40
-#define CISTPL_IO_RANGE 0x80
-
-#define CISTPL_IO_MAX_WIN 16
-
-typedef struct cistpl_io_t {
- unsigned char flags;
- unsigned char nwin;
- struct {
- unsigned int base;
- unsigned int len;
- } win[CISTPL_IO_MAX_WIN];
-} cistpl_io_t;
-
-typedef struct cistpl_irq_t {
- unsigned int IRQInfo1;
- unsigned int IRQInfo2;
-} cistpl_irq_t;
-
-#define CISTPL_MEM_MAX_WIN 8
-
-typedef struct cistpl_mem_t {
- unsigned char flags;
- unsigned char nwin;
- struct {
- unsigned int len;
- unsigned int card_addr;
- unsigned int host_addr;
- } win[CISTPL_MEM_MAX_WIN];
-} cistpl_mem_t;
-
-#define CISTPL_CFTABLE_DEFAULT 0x0001
-#define CISTPL_CFTABLE_BVDS 0x0002
-#define CISTPL_CFTABLE_WP 0x0004
-#define CISTPL_CFTABLE_RDYBSY 0x0008
-#define CISTPL_CFTABLE_MWAIT 0x0010
-#define CISTPL_CFTABLE_AUDIO 0x0800
-#define CISTPL_CFTABLE_READONLY 0x1000
-#define CISTPL_CFTABLE_PWRDOWN 0x2000
-
-typedef struct cistpl_cftable_entry_t {
- unsigned char index;
- unsigned short flags;
- unsigned char interface;
- cistpl_power_t vcc, vpp1, vpp2;
- cistpl_timing_t timing;
- cistpl_io_t io;
- cistpl_irq_t irq;
- cistpl_mem_t mem;
- unsigned char subtuples;
-} cistpl_cftable_entry_t;
-
-#define CISTPL_CFTABLE_MASTER 0x000100
-#define CISTPL_CFTABLE_INVALIDATE 0x000200
-#define CISTPL_CFTABLE_VGA_PALETTE 0x000400
-#define CISTPL_CFTABLE_PARITY 0x000800
-#define CISTPL_CFTABLE_WAIT 0x001000
-#define CISTPL_CFTABLE_SERR 0x002000
-#define CISTPL_CFTABLE_FAST_BACK 0x004000
-#define CISTPL_CFTABLE_BINARY_AUDIO 0x010000
-#define CISTPL_CFTABLE_PWM_AUDIO 0x020000
-
-typedef struct cistpl_cftable_entry_cb_t {
- unsigned char index;
- unsigned int flags;
- cistpl_power_t vcc, vpp1, vpp2;
- unsigned char io;
- cistpl_irq_t irq;
- unsigned char mem;
- unsigned char subtuples;
-} cistpl_cftable_entry_cb_t;
-
-typedef struct cistpl_device_geo_t {
- unsigned char ngeo;
- struct {
- unsigned char buswidth;
- unsigned int erase_block;
- unsigned int read_block;
- unsigned int write_block;
- unsigned int partition;
- unsigned int interleave;
- } geo[CISTPL_MAX_DEVICES];
-} cistpl_device_geo_t;
-
-typedef struct cistpl_vers_2_t {
- unsigned char vers;
- unsigned char comply;
- unsigned short dindex;
- unsigned char vspec8, vspec9;
- unsigned char nhdr;
- unsigned char vendor, info;
- char str[244];
-} cistpl_vers_2_t;
-
-typedef struct cistpl_org_t {
- unsigned char data_org;
- char desc[30];
-} cistpl_org_t;
-
-#define CISTPL_ORG_FS 0x00
-#define CISTPL_ORG_APPSPEC 0x01
-#define CISTPL_ORG_XIP 0x02
-
-typedef struct cistpl_format_t {
- unsigned char type;
- unsigned char edc;
- unsigned int offset;
- unsigned int length;
-} cistpl_format_t;
-
-#define CISTPL_FORMAT_DISK 0x00
-#define CISTPL_FORMAT_MEM 0x01
-
-#define CISTPL_EDC_NONE 0x00
-#define CISTPL_EDC_CKSUM 0x01
-#define CISTPL_EDC_CRC 0x02
-#define CISTPL_EDC_PCC 0x03
-
-typedef union cisparse_t {
- cistpl_device_t device;
- cistpl_checksum_t checksum;
- cistpl_longlink_t longlink;
- cistpl_longlink_mfc_t longlink_mfc;
- cistpl_vers_1_t version_1;
- cistpl_altstr_t altstr;
- cistpl_jedec_t jedec;
- cistpl_manfid_t manfid;
- cistpl_funcid_t funcid;
- cistpl_funce_t funce;
- cistpl_bar_t bar;
- cistpl_config_t config;
- cistpl_cftable_entry_t cftable_entry;
- cistpl_cftable_entry_cb_t cftable_entry_cb;
- cistpl_device_geo_t device_geo;
- cistpl_vers_2_t vers_2;
- cistpl_org_t org;
- cistpl_format_t format;
-} cisparse_t;
-
-typedef struct tuple_t {
- unsigned int Attributes;
- unsigned char DesiredTuple;
- unsigned int Flags; /* internal use */
- unsigned int LinkOffset; /* internal use */
- unsigned int CISOffset; /* internal use */
- unsigned char TupleCode;
- unsigned char TupleLink;
- unsigned char TupleOffset;
- unsigned char TupleDataMax;
- unsigned char TupleDataLen;
- unsigned char *TupleData;
-} tuple_t;
-
-/* Special unsigned char value */
-#define RETURN_FIRST_TUPLE 0xff
-
-/* Attributes for tuple calls */
-#define TUPLE_RETURN_LINK 0x01
-#define TUPLE_RETURN_COMMON 0x02
-
-/* For ValidateCIS */
-typedef struct cisinfo_t {
- unsigned int Chains;
-} cisinfo_t;
-
-#define CISTPL_MAX_CIS_SIZE 0x200
-
-/* For ReplaceCIS */
-typedef struct cisdump_t {
- unsigned int Length;
- unsigned char Data[CISTPL_MAX_CIS_SIZE];
-} cisdump_t;
-
-typedef struct tuple_flags {
- unsigned int link_space:4;
- unsigned int has_link:1;
- unsigned int mfc_fn:3;
- unsigned int space:4;
-} tuple_flags;
-
-#define BIND_FN_ALL 0xff
-
-extern int read_out_cis (unsigned int socket_no, FILE *fd);
-extern int pcmcia_get_first_tuple(unsigned int function, tuple_t *tuple);
-extern int pcmcia_get_next_tuple(unsigned int function, tuple_t *tuple);
-extern int pcmcia_get_tuple_data(tuple_t *tuple);
-extern int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse);
-extern int parse_cis_one_socket(unsigned int socket_no);
-
-#endif /* LINUX_CISTPL_H */
diff --git a/src/dmidecode/dmidecode.c b/src/dmidecode/dmidecode.c
index 5c542a6..ec91305 100644
--- a/src/dmidecode/dmidecode.c
+++ b/src/dmidecode/dmidecode.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include <ctype.h>
#include "config.h"
#include "types.h"
@@ -37,8 +38,8 @@
#include "dmioem.h"
#include "../state.h"
#include "../pci.h"
+#include "../naming_policy.h"
-static const char *out_of_spec = "<OUT OF SPEC>";
static const char *bad_index = "<BAD INDEX>";
/*
@@ -73,76 +74,48 @@ const char *dmi_string(struct dmi_header *dm, u8 s)
return bp;
}
-static const char *dmi_slot_current_usage(u8 code)
-{
- /* 3.3.10.3 */
- static const char *usage[]={
- "Other", /* 0x01 */
- "Unknown",
- "Available",
- "In Use" /* 0x04 */
- };
-
- if(code>=0x01 && code<=0x04)
- return usage[code-0x01];
- return out_of_spec;
-}
+/*
+ * Main
+ */
-static void dmi_slot_segment_bus_func(u16 code1, u8 code2, u8 code3, u8 type, const char *prefix)
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+static void strip_right(char *s)
{
- /* 3.3.10.8 */
- if (!(code1==0xFFFF && code2==0xFF && code3==0xFF))
- printf("%sSegment Group %u, Bus %u, Device %u, Function %u ",
- prefix, code1, code2, (code3>>3)&0x1F, (code3&0x7));
- switch(type)
- {
- case 0x06: /* PCI */
- case 0x0E: /* PCI */
- case 0x0F: /* AGP */
- case 0x10: /* AGP */
- case 0x11: /* AGP */
- case 0x12: /* PCI-X */
- case 0x13: /* AGP */
- case 0xA5: /* PCI Express */
- printf("\n");
- break;
- default:
- if (code1 != 0xFF || code2 != 0xFF || code3 != 0xFF)
- printf("%s\n", out_of_spec);
+ int i, len = strlen(s);
+ for (i=len; i>=0; i--) {
+ if (isspace(s[i-1]))
+ s[i-1] = '\0';
+ else
break;
}
}
-static u8 onboard_device_type(u8 code, const char *prefix)
+static void fill_one_slot_function(struct pci_device *pdev, struct dmi_header *h)
{
- /* 3.3.x.2 */
- u8 e = (code & 0x80)>>7;
- static const char *type[]={
- "Other", /* 1 */
- "Unknown",
- "Video",
- "SCSI Controller",
- "Ethernet",
- "Token Ring",
- "Sound",
- "PATA Controller",
- "SATA Controller",
- "SAS Controller" /* 0x0A */
- };
- code = code & 0x7F;
- if(code>=0x01 && code<=0x0A) {
- printf("%sStatus: %s\n", prefix, e?"Enabled":"Disabled");
- printf("%sDevice Type: %s\n", prefix, type[code-0x01]);
+ u8 *data = h->data;
+ pdev->physical_slot = WORD(data+0x09);
+ pdev->smbios_type = 0;
+ pdev->smbios_instance = 0;
+ pdev->uses_smbios |= HAS_SMBIOS_SLOT;
+ if (dmi_string(h, data[0x04])) {
+ pdev->smbios_label=strdup(dmi_string(h, data[0x04]));
+ pdev->uses_smbios |= HAS_SMBIOS_LABEL;
}
- else
- printf("%sDevice Type: %s\n", prefix, out_of_spec);
+ strip_right(pdev->smbios_label);
}
-/*
- * Main
- */
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
+static void fill_all_slot_functions(const struct libbiosdevname_state *state, int domain, int bus, int device, struct dmi_header *h)
+{
+ struct pci_device *pdev;
+ list_for_each_entry(pdev, &state->pci_devices, node) {
+ if (pdev->pci_dev->domain == domain &&
+ pdev->pci_dev->bus == bus &&
+ pdev->pci_dev->dev == device &&
+ ! (pdev->uses_smbios & HAS_SMBIOS_EXACT_MATCH))
+ fill_one_slot_function(pdev, h);
+ }
+}
static void dmi_decode(struct dmi_header *h, u16 ver, const struct libbiosdevname_state *state)
{
@@ -162,10 +135,10 @@ static void dmi_decode(struct dmi_header *h, u16 ver, const struct libbiosdevnam
function = data[0x10] & 7;
pdev = find_pci_dev_by_pci_addr(state, domain, bus, device, function);
if (pdev) {
- pdev->physical_slot = WORD(data+0x09);
- pdev->smbios_type = 0;
- pdev->smbios_instance = 0;
+ fill_one_slot_function(pdev, h);
+ pdev->uses_smbios |= HAS_SMBIOS_EXACT_MATCH;
}
+ fill_all_slot_functions(state, domain, bus, device, h);
}
}
break;
@@ -180,6 +153,12 @@ static void dmi_decode(struct dmi_header *h, u16 ver, const struct libbiosdevnam
pdev->smbios_enabled = !!(data[0x05] & 0x80);
pdev->smbios_type = data[0x05] & 0x7F;
pdev->smbios_instance = data[0x06];
+ pdev->uses_smbios |= HAS_SMBIOS_INSTANCE | HAS_SMBIOS_SLOT;
+ if (dmi_string(h, data[0x04])) {
+ pdev->smbios_label=strdup(dmi_string(h, data[0x04]));
+ pdev->uses_smbios |= HAS_SMBIOS_LABEL;
+ }
+ strip_right(pdev->smbios_label);
}
break;
diff --git a/src/dmidecode/dmidecode.h b/src/dmidecode/dmidecode.h
index db8f7bd..3427866 100644
--- a/src/dmidecode/dmidecode.h
+++ b/src/dmidecode/dmidecode.h
@@ -50,6 +50,19 @@ struct dmi_addon_device
const char *reference_designation;
};
+enum dmi_onboard_device_type {
+ DMI_OTHER=1,
+ DMI_UNKNOWN,
+ DMI_VIDEO,
+ DMI_SCSI,
+ DMI_ETHERNET,
+ DMI_TOKEN_RING,
+ DMI_SOUND,
+ DMI_PATA,
+ DMI_SATA,
+ DMI_SAS,
+};
+
struct libbiosdevname_state;
int dmidecode_main(const struct libbiosdevname_state *state);
diff --git a/src/dmidecode/dmioem.c b/src/dmidecode/dmioem.c
index 217c13a..234dbf4 100644
--- a/src/dmidecode/dmioem.c
+++ b/src/dmidecode/dmioem.c
@@ -91,6 +91,7 @@ static int dmi_decode_hp(struct dmi_header *h, const struct libbiosdevname_state
pdev->smbios_enabled = 1;
pdev->smbios_type = smbios_type;
pdev->smbios_instance = nic;
+ pdev->physical_slot = 0;
}
}
nic++;
diff --git a/src/dmidecode/util.c b/src/dmidecode/util.c
index 9eda714..b703b3a 100644
--- a/src/dmidecode/util.c
+++ b/src/dmidecode/util.c
@@ -105,7 +105,6 @@ void *mem_chunk(size_t base, size_t len, const char *devmem)
if((fd=open(devmem, O_RDONLY))==-1)
{
- perror(devmem);
return NULL;
}
@@ -129,8 +128,6 @@ void *mem_chunk(size_t base, size_t len, const char *devmem)
mmp=mmap(0, mmoffset+len, PROT_READ, MAP_SHARED, fd, base-mmoffset);
if(mmp==MAP_FAILED)
{
- fprintf(stderr, "%s: ", devmem);
- perror("mmap");
free(p);
return NULL;
}
diff --git a/src/eths.c b/src/eths.c
index 6ad5878..6a6cd31 100644
--- a/src/eths.c
+++ b/src/eths.c
@@ -54,9 +54,6 @@ static int eths_get_hwaddr(const char *devname, unsigned char *buf, int size, in
memcpy(buf, ifr.ifr_hwaddr.sa_data, min(size, sizeof(ifr.ifr_hwaddr.sa_data)));
*type = ifr.ifr_hwaddr.sa_family;
}
- else {
- perror("SIOCGIFHWADDR failed");
- }
close(fd);
return err;
}
diff --git a/src/libbiosdevname.h b/src/libbiosdevname.h
index c106a04..37eccb1 100644
--- a/src/libbiosdevname.h
+++ b/src/libbiosdevname.h
@@ -6,19 +6,12 @@
#ifndef LIBBIOSDEVNAME_H_INCLUDED
#define LIBBIOSDEVNAME_H_INCLUDED
-enum sortroutine {
- defaultsort,
- nosort,
-};
-
enum namingpolicy {
+ physical,
all_ethN,
- all_names,
- embedded_ethN_slots_names,
- kernelnames,
};
-extern void * setup_bios_devices(int sortroutine, int namingpolicy);
+extern void * setup_bios_devices(int namingpolicy, const char *prefix);
extern void cleanup_bios_devices(void *cookie);
extern char * kern_to_bios(void *cookie, const char *devname);
extern void unparse_bios_devices(void *cookie);
diff --git a/src/naming_policy.c b/src/naming_policy.c
index ffa33c8..0bb9395 100644
--- a/src/naming_policy.c
+++ b/src/naming_policy.c
@@ -11,97 +11,93 @@
#include "naming_policy.h"
#include "libbiosdevname.h"
#include "state.h"
+#include "dmidecode/dmidecode.h"
static void use_all_ethN(const struct libbiosdevname_state *state)
{
struct bios_device *dev;
unsigned int i=0;
+ char buffer[IFNAMSIZ];
+ memset(buffer, 0, sizeof(buffer));
list_for_each_entry(dev, &state->bios_devices, node) {
- if (dev->netdev)
- snprintf(dev->bios_name, sizeof(dev->bios_name), "eth%u", i++);
+ if (dev->netdev) {
+ snprintf(buffer, sizeof(buffer), "eth%u", i++);
+ dev->bios_name = strdup(buffer);
+ }
}
}
-static void use_kernel_names(const struct libbiosdevname_state *state)
+static void use_physical(const struct libbiosdevname_state *state, const char *prefix)
{
struct bios_device *dev;
+ char buffer[IFNAMSIZ];
+ char location[IFNAMSIZ];
+ char port[IFNAMSIZ];
+ char interface[IFNAMSIZ];
+ unsigned int portnum=0;
+ int known=0;
- list_for_each_entry(dev, &state->bios_devices, node) {
- if (dev->netdev)
- strncpy(dev->bios_name, dev->netdev->kernel_name, sizeof(dev->bios_name)-1);
- }
-}
-
-
-static void pcmcia_names(struct bios_device *dev)
-{
- snprintf(dev->bios_name, sizeof(dev->bios_name), "eth_pccard_%u.%u",
- dev->pcmciadev->socket, dev->pcmciadev->function);
-}
-
-static void use_embedded_ethN_slots_names(const struct libbiosdevname_state *state)
-{
- struct bios_device *dev;
- unsigned int i=0;
+ memset(buffer, 0, sizeof(buffer));
+ memset(location, 0, sizeof(location));
+ memset(port, 0, sizeof(port));
+ memset(interface, 0, sizeof(interface));
list_for_each_entry(dev, &state->bios_devices, node) {
+ known = 0;
if (is_pci(dev)) {
- if (dev->pcidev->physical_slot == 0)
- snprintf(dev->bios_name, sizeof(dev->bios_name), "eth%u", i++);
- else if (dev->pcidev->physical_slot < INT_MAX)
- snprintf(dev->bios_name, sizeof(dev->bios_name), "eth_s%d_%u",
- dev->pcidev->physical_slot,
- dev->pcidev->index_in_slot);
- else if (dev->pcidev->physical_slot == INT_MAX)
- snprintf(dev->bios_name, sizeof(dev->bios_name), "eth_unknown_%u", i++);
- }
- else if (is_pcmcia(dev))
- pcmcia_names(dev);
- }
-}
+ if (dev->pcidev->physical_slot == 0) { /* embedded devices only */
+ if (dev->pcidev->uses_sysfs & HAS_SYSFS_INDEX) {
+ portnum = dev->pcidev->sysfs_index;
+ snprintf(location, sizeof(location), "%s%u", prefix, portnum);
+ known=1;
+ }
+ else if (dev->pcidev->uses_smbios & HAS_SMBIOS_INSTANCE && is_pci_smbios_type_ethernet(dev->pcidev)) {
+ portnum = dev->pcidev->smbios_instance;
+ snprintf(location, sizeof(location), "%s%u", prefix, portnum);
+ known=1;
+ }
+ else if (dev->pcidev->embedded_index_valid) {
+ portnum = dev->pcidev->embedded_index;
+ snprintf(location, sizeof(location), "%s%u", prefix, portnum);
+ known=1;
+ }
+ }
+ else if (dev->pcidev->physical_slot < PHYSICAL_SLOT_UNKNOWN) {
+ snprintf(location, sizeof(location), "pci%u", dev->pcidev->physical_slot);
+ if (!dev->pcidev->is_sriov_virtual_function)
+ portnum = dev->pcidev->index_in_slot;
+ else
+ portnum = dev->pcidev->pf->index_in_slot;
+ snprintf(port, sizeof(port), "#%u", portnum);
+ known=1;
+ }
-static void use_all_names(const struct libbiosdevname_state *state)
-{
- struct bios_device *dev;
- unsigned int i=0;
+ if (dev->pcidev->is_sriov_virtual_function)
+ snprintf(interface, sizeof(interface), "_%u", dev->pcidev->vf_index);
- list_for_each_entry(dev, &state->bios_devices, node) {
- if (is_pci(dev)) {
- if (dev->pcidev->physical_slot < INT_MAX)
- snprintf(dev->bios_name, sizeof(dev->bios_name), "eth_s%d_%u",
- dev->pcidev->physical_slot,
- dev->pcidev->index_in_slot);
- else
- snprintf(dev->bios_name, sizeof(dev->bios_name), "eth_unknown_%u", i++);
+ if (known) {
+ snprintf(buffer, sizeof(buffer), "%s%s%s", location, port, interface);
+ dev->bios_name = strdup(buffer);
+ }
}
- else if (is_pcmcia(dev))
- pcmcia_names(dev);
}
}
-int assign_bios_network_names(const struct libbiosdevname_state *state, int sort, int policy)
+
+int assign_bios_network_names(const struct libbiosdevname_state *state, int policy, const char *prefix)
{
- if (sort != nosort) {
- switch (policy) {
- case all_ethN:
- use_all_ethN(state);
- break;
- case embedded_ethN_slots_names:
- use_embedded_ethN_slots_names(state);
- break;
- case all_names:
- use_all_names(state);
- break;
- case kernelnames:
- default:
- use_kernel_names(state);
- break;
- }
+ int rc = 0;
+ switch (policy) {
+ case all_ethN:
+ use_all_ethN(state);
+ break;
+ case physical:
+ default:
+ use_physical(state, prefix);
+ break;
}
- else
- use_kernel_names(state);
- return 0;
+ return rc;
}
diff --git a/src/naming_policy.h b/src/naming_policy.h
index 9d61b42..a2e6e1c 100644
--- a/src/naming_policy.h
+++ b/src/naming_policy.h
@@ -9,6 +9,6 @@
#include "state.h"
extern int assign_bios_network_names(const struct libbiosdevname_state *state,
- int sortroutine, int namingpolicy);
+ int namingpolicy, const char *prefix);
#endif /* NAMING_POLICY_H_INCLUDED */
diff --git a/src/parse_cis.c b/src/parse_cis.c
deleted file mode 100644
index b03d2dc..0000000
--- a/src/parse_cis.c
+++ /dev/null
@@ -1,882 +0,0 @@
-/*
- * cistpl.c -- 16-bit PCMCIA Card Information Structure parser
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * (C) 1999 David A. Hinds
- */
-
-/* Parsing routines for individual tuples */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <endian.h>
-#include <byteswap.h>
-
-#include "cistpl.h"
-
-#define IRQ_INFO2_VALID 0x10
-
-static const u_char mantissa[] = {
- 10, 12, 13, 15, 20, 25, 30, 35,
- 40, 45, 50, 55, 60, 70, 80, 90
-};
-
-static const u_int exponent[] = {
- 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
-};
-
-/* Convert an extended speed byte to a time in nanoseconds */
-#define SPEED_CVT(v) \
- (mantissa[(((v)>>3)&15)-1] * exponent[(v)&7] / 10)
-/* Convert a power byte to a current in 0.1 microamps */
-#define POWER_CVT(v) \
- (mantissa[((v)>>3)&15] * exponent[(v)&7] / 10)
-#define POWER_SCALE(v) (exponent[(v)&7])
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define le32_to_cpu(value) bswap_32(value)
-# define le16_to_cpu(value) bswap_16(value)
-#else
-# define le32_to_cpu(value) (value)
-# define le16_to_cpu(value) (value)
-#endif
-
-static int parse_device(tuple_t *tuple, cistpl_device_t *device)
-{
- int i;
- u_char scale;
- u_char *p, *q;
-
- p = (u_char *) tuple->TupleData;
- q = p + tuple->TupleDataLen;
-
- device->ndev = 0;
- for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
-
- if (*p == 0xff)
- break;
-
- device->dev[i].type = (*p >> 4);
- device->dev[i].wp = (*p & 0x08) ? 1 : 0;
- switch (*p & 0x07) {
- case 0: device->dev[i].speed = 0; break;
- case 1: device->dev[i].speed = 250; break;
- case 2: device->dev[i].speed = 200; break;
- case 3: device->dev[i].speed = 150; break;
- case 4: device->dev[i].speed = 100; break;
- case 7:
- if (++p == q) return -EINVAL;
- device->dev[i].speed = SPEED_CVT(*p);
- while (*p & 0x80)
- if (++p == q) return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
-
- if (++p == q)
- return -EINVAL;
- if (*p == 0xff)
- break;
- scale = *p & 7;
- if (scale == 7)
- return -EINVAL;
- device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
- device->ndev++;
- if (++p == q)
- break;
- }
-
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
-{
- u_char *p;
- if (tuple->TupleDataLen < 5)
- return -EINVAL;
- p = (u_char *)tuple->TupleData;
- csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2;
- csum->len = le16_to_cpu(*(u_short *)(p + 2));
- csum->sum = *(p+4);
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
-{
- if (tuple->TupleDataLen < 4)
- return -EINVAL;
- link->addr = le32_to_cpu(*(u_int *)tuple->TupleData);
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_longlink_mfc(tuple_t *tuple,
- cistpl_longlink_mfc_t *link)
-{
- u_char *p;
- int i;
-
- p = (u_char *)tuple->TupleData;
-
- link->nfn = *p; p++;
- if (tuple->TupleDataLen <= link->nfn*5)
- return -EINVAL;
- for (i = 0; i < link->nfn; i++) {
- link->fn[i].space = *p; p++;
- link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4;
- }
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_strings(u_char *p, u_char *q, int max,
- char *s, u_char *ofs, u_char *found)
-{
- int i, j, ns;
-
- if (p == q)
- return -EINVAL;
- ns = 0; j = 0;
- for (i = 0; i < max; i++) {
- if (*p == 0xff)
- break;
- ofs[i] = j;
- ns++;
- for (;;) {
- s[j++] = (*p == 0xff) ? '\0' : *p;
- if ((*p == '\0') || (*p == 0xff))
- break;
- if (++p == q)
- return -EINVAL;
- }
- if ((*p == 0xff) || (++p == q))
- break;
- }
- if (found) {
- *found = ns;
- return 0;
- } else {
- return (ns == max) ? 0 : -EINVAL;
- }
-}
-
-/*====================================================================*/
-
-static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
-{
- u_char *p, *q;
-
- p = (u_char *) tuple->TupleData;
- q = p + tuple->TupleDataLen;
-
- vers_1->major = *p; p++;
- vers_1->minor = *p; p++;
- if (p >= q)
- return -EINVAL;
-
- return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
- vers_1->str, vers_1->ofs, &vers_1->ns);
-}
-
-/*====================================================================*/
-
-static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr)
-{
- u_char *p, *q;
-
- p = (u_char *) tuple->TupleData;
- q = p + tuple->TupleDataLen;
-
- return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
- altstr->str, altstr->ofs, &altstr->ns);
-}
-
-/*====================================================================*/
-
-static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
-{
- u_char *p, *q;
- int nid;
-
- p = (u_char *)tuple->TupleData;
- q = p + tuple->TupleDataLen;
-
- for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) {
- if (p > q-2)
- break;
- jedec->id[nid].mfr = p[0];
- jedec->id[nid].info = p[1];
- p += 2;
- }
- jedec->nid = nid;
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
-{
- u_short *p;
- if (tuple->TupleDataLen < 4)
- return -EINVAL;
- p = (u_short *)tuple->TupleData;
- m->manf = le16_to_cpu(p[0]);
- m->card = le16_to_cpu(p[1]);
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
-{
- u_char *p;
- if (tuple->TupleDataLen < 2)
- return -EINVAL;
- p = (u_char *)tuple->TupleData;
- f->func = p[0];
- f->sysinit = p[1];
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
-{
- u_char *p;
- int i;
- if (tuple->TupleDataLen < 1)
- return -EINVAL;
- p = (u_char *)tuple->TupleData;
- f->type = p[0];
- for (i = 1; i < tuple->TupleDataLen; i++)
- f->data[i-1] = p[i];
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_config(tuple_t *tuple, cistpl_config_t *config)
-{
- int rasz, rmsz, i;
- u_char *p;
-
- p = (u_char *)tuple->TupleData;
- rasz = *p & 0x03;
- rmsz = (*p & 0x3c) >> 2;
- if (tuple->TupleDataLen < rasz+rmsz+4)
- return -EINVAL;
- config->last_idx = *(++p);
- p++;
- config->base = 0;
- for (i = 0; i <= rasz; i++)
- config->base += p[i] << (8*i);
- p += rasz+1;
- for (i = 0; i < 4; i++)
- config->rmask[i] = 0;
- for (i = 0; i <= rmsz; i++)
- config->rmask[i>>2] += p[i] << (8*(i%4));
- config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
- return 0;
-}
-
-/*======================================================================
-
- The following routines are all used to parse the nightmarish
- config table entries.
-
-======================================================================*/
-
-static u_char *parse_power(u_char *p, u_char *q,
- cistpl_power_t *pwr)
-{
- int i;
- u_int scale;
-
- if (p == q) return NULL;
- pwr->present = *p;
- pwr->flags = 0;
- p++;
- for (i = 0; i < 7; i++)
- if (pwr->present & (1<<i)) {
- if (p == q)
- return NULL;
- pwr->param[i] = POWER_CVT(*p);
- scale = POWER_SCALE(*p);
- while (*p & 0x80) {
- if (++p == q)
- return NULL;
- if ((*p & 0x7f) < 100)
- pwr->param[i] += (*p & 0x7f) * scale / 100;
- else if (*p == 0x7d)
- pwr->flags |= CISTPL_POWER_HIGHZ_OK;
- else if (*p == 0x7e)
- pwr->param[i] = 0;
- else if (*p == 0x7f)
- pwr->flags |= CISTPL_POWER_HIGHZ_REQ;
- else
- return NULL;
- }
- p++;
- }
- return p;
-}
-
-/*====================================================================*/
-
-static u_char *parse_timing(u_char *p, u_char *q,
- cistpl_timing_t *timing)
-{
- u_char scale;
-
- if (p == q)
- return NULL;
- scale = *p;
- if ((scale & 3) != 3) {
- if (++p == q)
- return NULL;
- timing->wait = SPEED_CVT(*p);
- timing->waitscale = exponent[scale & 3];
- } else
- timing->wait = 0;
- scale >>= 2;
- if ((scale & 7) != 7) {
- if (++p == q)
- return NULL;
- timing->ready = SPEED_CVT(*p);
- timing->rdyscale = exponent[scale & 7];
- } else
- timing->ready = 0;
- scale >>= 3;
- if (scale != 7) {
- if (++p == q)
- return NULL;
- timing->reserved = SPEED_CVT(*p);
- timing->rsvscale = exponent[scale];
- } else
- timing->reserved = 0;
- p++;
- return p;
-}
-
-/*====================================================================*/
-
-static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io)
-{
- int i, j, bsz, lsz;
-
- if (p == q) return NULL;
- io->flags = *p;
-
- if (!(*p & 0x80)) {
- io->nwin = 1;
- io->win[0].base = 0;
- io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK));
- return p+1;
- }
-
- if (++p == q)
- return NULL;
- io->nwin = (*p & 0x0f) + 1;
- bsz = (*p & 0x30) >> 4;
- if (bsz == 3)
- bsz++;
- lsz = (*p & 0xc0) >> 6;
- if (lsz == 3)
- lsz++;
- p++;
-
- for (i = 0; i < io->nwin; i++) {
- io->win[i].base = 0;
- io->win[i].len = 1;
- for (j = 0; j < bsz; j++, p++) {
- if (p == q)
- return NULL;
- io->win[i].base += *p << (j*8);
- }
- for (j = 0; j < lsz; j++, p++) {
- if (p == q)
- return NULL;
- io->win[i].len += *p << (j*8);
- }
- }
- return p;
-}
-
-/*====================================================================*/
-
-static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
-{
- int i, j, asz, lsz, has_ha;
- u_int len, ca, ha;
-
- if (p == q)
- return NULL;
-
- mem->nwin = (*p & 0x07) + 1;
- lsz = (*p & 0x18) >> 3;
- asz = (*p & 0x60) >> 5;
- has_ha = (*p & 0x80);
- if (++p == q)
- return NULL;
-
- for (i = 0; i < mem->nwin; i++) {
- len = ca = ha = 0;
- for (j = 0; j < lsz; j++, p++) {
- if (p == q)
- return NULL;
- len += *p << (j*8);
- }
- for (j = 0; j < asz; j++, p++) {
- if (p == q)
- return NULL;
- ca += *p << (j*8);
- }
- if (has_ha)
- for (j = 0; j < asz; j++, p++) {
- if (p == q)
- return NULL;
- ha += *p << (j*8);
- }
- mem->win[i].len = len << 8;
- mem->win[i].card_addr = ca << 8;
- mem->win[i].host_addr = ha << 8;
- }
- return p;
-}
-
-/*====================================================================*/
-
-static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
-{
- if (p == q)
- return NULL;
- irq->IRQInfo1 = *p; p++;
- if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
- if (p+2 > q)
- return NULL;
- irq->IRQInfo2 = (p[1]<<8) + p[0];
- p += 2;
- }
- return p;
-}
-
-/*====================================================================*/
-
-static int parse_cftable_entry(tuple_t *tuple,
- cistpl_cftable_entry_t *entry)
-{
- u_char *p, *q, features;
-
- p = tuple->TupleData;
- q = p + tuple->TupleDataLen;
- entry->index = *p & 0x3f;
- entry->flags = 0;
- if (*p & 0x40)
- entry->flags |= CISTPL_CFTABLE_DEFAULT;
- if (*p & 0x80) {
- if (++p == q)
- return -EINVAL;
- if (*p & 0x10)
- entry->flags |= CISTPL_CFTABLE_BVDS;
- if (*p & 0x20)
- entry->flags |= CISTPL_CFTABLE_WP;
- if (*p & 0x40)
- entry->flags |= CISTPL_CFTABLE_RDYBSY;
- if (*p & 0x80)
- entry->flags |= CISTPL_CFTABLE_MWAIT;
- entry->interface = *p & 0x0f;
- } else
- entry->interface = 0;
-
- /* Process optional features */
- if (++p == q)
- return -EINVAL;
- features = *p; p++;
-
- /* Power options */
- if ((features & 3) > 0) {
- p = parse_power(p, q, &entry->vcc);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->vcc.present = 0;
- if ((features & 3) > 1) {
- p = parse_power(p, q, &entry->vpp1);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->vpp1.present = 0;
- if ((features & 3) > 2) {
- p = parse_power(p, q, &entry->vpp2);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->vpp2.present = 0;
-
- /* Timing options */
- if (features & 0x04) {
- p = parse_timing(p, q, &entry->timing);
- if (p == NULL)
- return -EINVAL;
- } else {
- entry->timing.wait = 0;
- entry->timing.ready = 0;
- entry->timing.reserved = 0;
- }
-
- /* I/O window options */
- if (features & 0x08) {
- p = parse_io(p, q, &entry->io);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->io.nwin = 0;
-
- /* Interrupt options */
- if (features & 0x10) {
- p = parse_irq(p, q, &entry->irq);
- if (p == NULL) return -EINVAL;
- } else
- entry->irq.IRQInfo1 = 0;
-
- switch (features & 0x60) {
- case 0x00:
- entry->mem.nwin = 0;
- break;
- case 0x20:
- entry->mem.nwin = 1;
- entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
- entry->mem.win[0].card_addr = 0;
- entry->mem.win[0].host_addr = 0;
- p += 2;
- if (p > q)
- return -EINVAL;
- break;
- case 0x40:
- entry->mem.nwin = 1;
- entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
- entry->mem.win[0].card_addr =
- le16_to_cpu(*(u_short *)(p+2)) << 8;
- entry->mem.win[0].host_addr = 0;
- p += 4;
- if (p > q)
- return -EINVAL;
- break;
- case 0x60:
- p = parse_mem(p, q, &entry->mem);
- if (p == NULL)
- return -EINVAL;
- break;
- }
-
- /* Misc features */
- if (features & 0x80) {
- if (p == q)
- return -EINVAL;
- entry->flags |= (*p << 8);
- while (*p & 0x80)
- if (++p == q)
- return -EINVAL;
- p++;
- }
-
- entry->subtuples = q-p;
-
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
-{
- u_char *p;
- if (tuple->TupleDataLen < 6)
- return -EINVAL;
- p = (u_char *)tuple->TupleData;
- bar->attr = *p;
- p += 2;
- bar->size = le32_to_cpu(*(u_int *)p);
- return 0;
-}
-
-static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
-{
- u_char *p;
-
- p = (u_char *)tuple->TupleData;
- if ((*p != 3) || (tuple->TupleDataLen < 6))
- return -EINVAL;
- config->last_idx = *(++p);
- p++;
- config->base = le32_to_cpu(*(u_int *)p);
- config->subtuples = tuple->TupleDataLen - 6;
- return 0;
-}
-
-static int parse_cftable_entry_cb(tuple_t *tuple,
- cistpl_cftable_entry_cb_t *entry)
-{
- u_char *p, *q, features;
-
- p = tuple->TupleData;
- q = p + tuple->TupleDataLen;
- entry->index = *p & 0x3f;
- entry->flags = 0;
- if (*p & 0x40)
- entry->flags |= CISTPL_CFTABLE_DEFAULT;
-
- /* Process optional features */
- if (++p == q)
- return -EINVAL;
- features = *p; p++;
-
- /* Power options */
- if ((features & 3) > 0) {
- p = parse_power(p, q, &entry->vcc);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->vcc.present = 0;
- if ((features & 3) > 1) {
- p = parse_power(p, q, &entry->vpp1);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->vpp1.present = 0;
- if ((features & 3) > 2) {
- p = parse_power(p, q, &entry->vpp2);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->vpp2.present = 0;
-
- /* I/O window options */
- if (features & 0x08) {
- if (p == q)
- return -EINVAL;
- entry->io = *p; p++;
- } else
- entry->io = 0;
-
- /* Interrupt options */
- if (features & 0x10) {
- p = parse_irq(p, q, &entry->irq);
- if (p == NULL)
- return -EINVAL;
- } else
- entry->irq.IRQInfo1 = 0;
-
- if (features & 0x20) {
- if (p == q)
- return -EINVAL;
- entry->mem = *p; p++;
- } else
- entry->mem = 0;
-
- /* Misc features */
- if (features & 0x80) {
- if (p == q)
- return -EINVAL;
- entry->flags |= (*p << 8);
- if (*p & 0x80) {
- if (++p == q)
- return -EINVAL;
- entry->flags |= (*p << 16);
- }
- while (*p & 0x80)
- if (++p == q)
- return -EINVAL;
- p++;
- }
-
- entry->subtuples = q-p;
-
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
-{
- u_char *p, *q;
- int n;
-
- p = (u_char *)tuple->TupleData;
- q = p + tuple->TupleDataLen;
-
- for (n = 0; n < CISTPL_MAX_DEVICES; n++) {
- if (p > q-6)
- break;
- geo->geo[n].buswidth = p[0];
- geo->geo[n].erase_block = 1 << (p[1]-1);
- geo->geo[n].read_block = 1 << (p[2]-1);
- geo->geo[n].write_block = 1 << (p[3]-1);
- geo->geo[n].partition = 1 << (p[4]-1);
- geo->geo[n].interleave = 1 << (p[5]-1);
- p += 6;
- }
- geo->ngeo = n;
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
-{
- u_char *p, *q;
-
- if (tuple->TupleDataLen < 10)
- return -EINVAL;
-
- p = tuple->TupleData;
- q = p + tuple->TupleDataLen;
-
- v2->vers = p[0];
- v2->comply = p[1];
- v2->dindex = le16_to_cpu(*(u_short *)(p+2));
- v2->vspec8 = p[6];
- v2->vspec9 = p[7];
- v2->nhdr = p[8];
- p += 9;
- return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);
-}
-
-/*====================================================================*/
-
-static int parse_org(tuple_t *tuple, cistpl_org_t *org)
-{
- u_char *p, *q;
- int i;
-
- p = tuple->TupleData;
- q = p + tuple->TupleDataLen;
- if (p == q)
- return -EINVAL;
- org->data_org = *p;
- if (++p == q)
- return -EINVAL;
- for (i = 0; i < 30; i++) {
- org->desc[i] = *p;
- if (*p == '\0') break;
- if (++p == q)
- return -EINVAL;
- }
- return 0;
-}
-
-/*====================================================================*/
-
-static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
-{
- u_char *p;
-
- if (tuple->TupleDataLen < 10)
- return -EINVAL;
-
- p = tuple->TupleData;
-
- fmt->type = p[0];
- fmt->edc = p[1];
- fmt->offset = le32_to_cpu(*(u_int *)(p+2));
- fmt->length = le32_to_cpu(*(u_int *)(p+6));
-
- return 0;
-}
-
-/*====================================================================*/
-
-int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse)
-{
- int ret = 0;
-
- if (tuple->TupleDataLen > tuple->TupleDataMax)
- return -EINVAL;
- switch (tuple->TupleCode) {
- case CISTPL_DEVICE:
- case CISTPL_DEVICE_A:
- ret = parse_device(tuple, &parse->device);
- break;
- case CISTPL_BAR:
- ret = parse_bar(tuple, &parse->bar);
- break;
- case CISTPL_CONFIG_CB:
- ret = parse_config_cb(tuple, &parse->config);
- break;
- case CISTPL_CFTABLE_ENTRY_CB:
- ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
- break;
- case CISTPL_CHECKSUM:
- ret = parse_checksum(tuple, &parse->checksum);
- break;
- case CISTPL_LONGLINK_A:
- case CISTPL_LONGLINK_C:
- ret = parse_longlink(tuple, &parse->longlink);
- break;
- case CISTPL_LONGLINK_MFC:
- ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
- break;
- case CISTPL_VERS_1:
- ret = parse_vers_1(tuple, &parse->version_1);
- break;
- case CISTPL_ALTSTR:
- ret = parse_altstr(tuple, &parse->altstr);
- break;
- case CISTPL_JEDEC_A:
- case CISTPL_JEDEC_C:
- ret = parse_jedec(tuple, &parse->jedec);
- break;
- case CISTPL_MANFID:
- ret = parse_manfid(tuple, &parse->manfid);
- break;
- case CISTPL_FUNCID:
- ret = parse_funcid(tuple, &parse->funcid);
- break;
- case CISTPL_FUNCE:
- ret = parse_funce(tuple, &parse->funce);
- break;
- case CISTPL_CONFIG:
- ret = parse_config(tuple, &parse->config);
- break;
- case CISTPL_CFTABLE_ENTRY:
- ret = parse_cftable_entry(tuple, &parse->cftable_entry);
- break;
- case CISTPL_DEVICE_GEO:
- case CISTPL_DEVICE_GEO_A:
- ret = parse_device_geo(tuple, &parse->device_geo);
- break;
- case CISTPL_VERS_2:
- ret = parse_vers_2(tuple, &parse->vers_2);
- break;
- case CISTPL_ORG:
- ret = parse_org(tuple, &parse->org);
- break;
- case CISTPL_FORMAT:
- case CISTPL_FORMAT_A:
- ret = parse_format(tuple, &parse->format);
- break;
- case CISTPL_NO_LINK:
- case CISTPL_LINKTARGET:
- ret = 0;
- break;
- default:
- ret = -EINVAL;
- break;
- }
- return ret;
-}
diff --git a/src/pci.c b/src/pci.c
index c5ae788..a7ec6f9 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -1,67 +1,317 @@
/*
- * Copyright (c) 2006 Dell, Inc.
+ * Copyright (c) 2006-2010 Dell, Inc.
* by Matt Domsch <Matt_Domsch@dell.com>
* Licensed under the GNU General Public license, version 2.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <limits.h>
-#include "pirq.h"
+#include <unistd.h>
+#include <dirent.h>
#include <pci/pci.h>
#include "pci.h"
+#include "sysfs.h"
+#include "dmidecode/dmidecode.h"
+#include "pirq.h"
-static int
-is_parent_bridge(struct pci_dev *p, unsigned int target_bus)
+static int read_pci_sysfs_path(char *buf, size_t bufsize, const struct pci_dev *pdev)
{
- unsigned int primary, secondary;
+ char path[PATH_MAX];
+ char pci_name[16];
+ ssize_t size;
+ unparse_pci_name(pci_name, sizeof(pci_name), pdev);
+ snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s", pci_name);
+ size = readlink(path, buf, bufsize);
+ if (size == -1)
+ return 1;
+ return 0;
+}
- if ( (pci_read_word(p, PCI_HEADER_TYPE) & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
- return 0;
+static int read_pci_sysfs_physfn(char *buf, size_t bufsize, const struct pci_dev *pdev)
+{
+ char path[PATH_MAX];
+ char pci_name[16];
+ ssize_t size;
+ unparse_pci_name(pci_name, sizeof(pci_name), pdev);
+ snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/physfn", pci_name);
+ size = readlink(path, buf, bufsize);
+ if (size == -1)
+ return 1;
+ return 0;
+}
- primary=pci_read_byte(p, PCI_PRIMARY_BUS);
- secondary=pci_read_byte(p, PCI_SECONDARY_BUS);
+static int virtfn_filter(const struct dirent *dent)
+{
+ return (!strncmp(dent->d_name,"virtfn",6));
+}
- if (secondary != target_bus)
- return 0;
+static int _read_virtfn_index(unsigned int *index, const char *path, const char *basename, const char *pci_name)
+{
+ char buf[PATH_MAX], *b;
+ char fullpath[PATH_MAX];
+ ssize_t size;
+ unsigned int u=INT_MAX;
+ int scanned, rc=1;
+
+ snprintf(fullpath, sizeof(fullpath), "%s/%s", path, basename);
+ size = readlink(fullpath, buf, sizeof(buf));
+ if (size > 0) {
+ /* form is ../0000:05:10.0 */
+ b=buf+3; /* skip ../ */
+ if (strlen(b) == strlen(pci_name) &&
+ !strncmp(b, pci_name, strlen(pci_name))) {
+ scanned = sscanf(basename, "virtfn%u", &u);
+ if (scanned == 1) {
+ rc = 0;
+ *index = u;
+ }
+ }
+ }
+ return rc;
+}
- return 1;
+static int read_virtfn_index(unsigned int *index, const struct pci_dev *pdev)
+{
+ char pci_name[16];
+ char path[PATH_MAX];
+ char cpath[PATH_MAX];
+ struct dirent **namelist;
+ int n, rc=1;
+
+ unparse_pci_name(pci_name, sizeof(pci_name), pdev);
+ snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/physfn", pci_name);
+ if (realpath(path, cpath) == NULL)
+ return rc;
+
+ n = scandir(cpath, &namelist, virtfn_filter, versionsort);
+ if (n < 0)
+ return rc;
+ else {
+ while (n--) {
+ if (rc)
+ rc = _read_virtfn_index(index, cpath, namelist[n]->d_name, pci_name);
+ free(namelist[n]);
+ }
+ free(namelist);
+ }
+
+ return rc;
}
-static struct pci_dev *
-find_parent(struct pci_access *pacc, unsigned int target_bus)
+static int parse_pci_name(const char *s, int *domain, int *bus, int *dev, int *func)
{
- struct pci_dev *p;
+ int err;
+/* The domain part was added in 2.6 kernels. Test for that first. */
+ err = sscanf(s, "%x:%2x:%2x.%x", domain, bus, dev, func);
+ if (err != 4) {
+ err = sscanf(s, "%2x:%2x.%x", bus, dev, func);
+ if (err != 3) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static struct pci_dev * find_pdev_by_pci_name(struct pci_access *pacc, const char *s)
+{
+ int domain=0, bus=0, device=0, func=0;
+ if (parse_pci_name(s, &domain, &bus, &device, &func))
+ return NULL;
+ return pci_get_dev(pacc, domain, bus, device, func);
+}
- for (p=pacc->devices; p; p=p->next)
- if (is_parent_bridge(p, target_bus))
- return p;
+static struct pci_device *
+find_physfn(struct libbiosdevname_state *state, struct pci_device *dev)
+{
+ int rc;
+ char path[PATH_MAX];
+ char *c;
+ struct pci_dev *pdev;
+ memset(path, 0, sizeof(path));
+ rc = read_pci_sysfs_physfn(path, sizeof(path), dev->pci_dev);
+ if (rc != 0)
+ return NULL;
+ /* we get back a string like
+ ../0000:05:0.0
+ where the last component is the parent device
+ */
+ /* find the last backslash */
+ c = rindex(path, '/');
+ c++;
+ pdev = find_pdev_by_pci_name(state->pacc, c);
+ dev = find_dev_by_pci(state, pdev);
+ return dev;
+}
+static int is_same_pci(const struct pci_dev *a, const struct pci_dev *b)
+{
+ if (pci_domain_nr(a) == pci_domain_nr(b) &&
+ a->bus == b->bus &&
+ a->dev == b->dev &&
+ a->func == b->func)
+ return 1;
+ return 0;
+}
+
+static void try_add_vf_to_pf(struct libbiosdevname_state *state, struct pci_device *vf)
+{
+ struct pci_device *pf;
+ unsigned int index=0;
+ int rc;
+ pf = find_physfn(state, vf);
+
+ if (!pf)
+ return;
+ list_add_tail(&vf->vfnode, &pf->vfs);
+ rc = read_virtfn_index(&index, vf->pci_dev);
+ if (!rc) {
+ vf->vf_index = index;
+ pf->is_sriov_physical_function = 1;
+ }
+ vf->pf = pf;
+ vf->physical_slot = pf->physical_slot;
+}
+
+static struct pci_device *
+find_parent(struct libbiosdevname_state *state, struct pci_device *dev)
+{
+ int rc;
+ char path[PATH_MAX];
+ char *c;
+ struct pci_device *physfn;
+ struct pci_dev *pdev;
+ memset(path, 0, sizeof(path));
+ /* if this device has a physfn pointer, then treat _that_ as the parent */
+ physfn = find_physfn(state, dev);
+ if (physfn) {
+ dev->is_sriov_virtual_function=1;
+ return physfn;
+ }
+
+ rc = read_pci_sysfs_path(path, sizeof(path), dev->pci_dev);
+ if (rc != 0)
+ return NULL;
+ /* we get back a string like
+ ../../../devices/pci0000:00/0000:00:09.0/0000:05:17.4
+ where the last component is the device we asked for
+ */
+ /* find the last backslash */
+ c = rindex(path, '/');
+ *c = '\0';
+ /* find the last backslash again */
+ c = rindex(path, '/');
+ c++;
+ pdev = find_pdev_by_pci_name(state->pacc, c);
+ if (pdev) {
+ dev = find_dev_by_pci(state, pdev);
+ return dev;
+ }
return NULL;
}
/*
- * Check our parent in case the device itself isn't listed
- * in the PCI IRQ Routing Table. This has a problem, as
+ * Check our parents in case the device itself isn't listed
+ * in the SMBIOS table. This has a problem, as
* our parent bridge on a card may not be included
- * in the $PIR table. In that case, it falls back to "unknown".
+ * in the SMBIOS table. In that case, it falls back to "unknown".
*/
-static int pci_dev_to_slot(struct routing_table *table, struct pci_access *pacc, struct pci_dev *p)
+static int pci_dev_to_slot(struct libbiosdevname_state *state, struct pci_device *dev)
+{
+ struct pci_device *d = dev;
+ int slot = d->physical_slot;
+ while (d && slot == PHYSICAL_SLOT_UNKNOWN) {
+ d = find_parent(state, d);
+ if (d)
+ slot = d->physical_slot;
+ }
+ return slot;
+}
+
+static int pirq_dev_to_slot(struct libbiosdevname_state *state, struct pci_device *dev)
+{
+ struct pci_device *d = dev;
+ int slot;
+ slot = pirq_pci_dev_to_slot(state->pirq_table, d->pci_dev->bus, d->pci_dev->dev);
+ while (d && slot == PHYSICAL_SLOT_UNKNOWN) {
+ d = find_parent(state, d);
+ if (d)
+ slot = pirq_pci_dev_to_slot(state->pirq_table, d->pci_dev->bus, d->pci_dev->dev);
+ }
+ return slot;
+}
+
+static void dev_to_slot(struct libbiosdevname_state *state, struct pci_device *dev)
+{
+ int slot;
+ slot = pci_dev_to_slot(state, dev);
+ if (slot == PHYSICAL_SLOT_UNKNOWN) {
+ slot = pirq_dev_to_slot(state, dev);
+ }
+ dev->physical_slot = slot;
+}
+
+static char *read_pci_sysfs_label(const struct pci_dev *pdev)
+{
+ char path[PATH_MAX];
+ char pci_name[16];
+ int rc;
+ char *label = NULL;
+
+ unparse_pci_name(pci_name, sizeof(pci_name), pdev);
+ snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/label", pci_name);
+ rc = sysfs_read_file(path, &label);
+ if (rc == 0)
+ return label;
+ return NULL;
+}
+
+static int read_pci_sysfs_index(unsigned int *index, const struct pci_dev *pdev)
{
+ char path[PATH_MAX];
+ char pci_name[16];
int rc;
- rc = pirq_pci_dev_to_slot(table, p->bus, p->dev);
- if (rc == INT_MAX) {
- p = find_parent(pacc, p->bus);
- if (p)
- rc = pirq_pci_dev_to_slot(table, p->bus, p->dev);
+ char *indexstr = NULL;
+ unsigned int i;
+ unparse_pci_name(pci_name, sizeof(pci_name), pdev);
+ snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/index", pci_name);
+ rc = sysfs_read_file(path, &indexstr);
+ if (rc == 0) {
+ rc = sscanf(indexstr, "%u", &i);
+ if (rc == 1) {
+ *index = i;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void fill_pci_dev_sysfs(struct pci_device *dev, struct pci_dev *p)
+{
+ int rc;
+ unsigned int index = 0;
+ char *label = NULL;
+ char buf[PATH_MAX];
+ unparse_pci_name(buf, sizeof(buf), p);
+ rc = read_pci_sysfs_index(&index, p);
+ if (!rc) {
+ dev->sysfs_index = index;
+ dev->uses_sysfs |= HAS_SYSFS_INDEX;
+ }
+ label = read_pci_sysfs_label(p);
+ if (label) {
+ dev->sysfs_label = label;
+ dev->uses_sysfs |= HAS_SYSFS_LABEL;
}
- return rc;
}
static void add_pci_dev(struct libbiosdevname_state *state,
- struct routing_table *table,
- struct pci_access *pacc, struct pci_dev *p)
+ struct pci_dev *p)
{
struct pci_device *dev;
dev = malloc(sizeof(*dev));
@@ -71,9 +321,13 @@ static void add_pci_dev(struct libbiosdevname_state *state,
}
memset(dev, 0, sizeof(*dev));
INIT_LIST_HEAD(&dev->node);
- memcpy(&dev->pci_dev, p, sizeof(*p)); /* This doesn't allow us to call PCI functions though */
- dev->physical_slot = pci_dev_to_slot(table, pacc, p);
+ INIT_LIST_HEAD(&dev->vfnode);
+ INIT_LIST_HEAD(&dev->vfs);
+ dev->pci_dev = p;
+ dev->physical_slot = PHYSICAL_SLOT_UNKNOWN;
dev->class = pci_read_word(p, PCI_CLASS_DEVICE);
+ dev->vf_index = INT_MAX;
+ fill_pci_dev_sysfs(dev, p);
list_add(&dev->node, &state->pci_devices);
}
@@ -81,60 +335,158 @@ void free_pci_devices(struct libbiosdevname_state *state)
{
struct pci_device *pos, *next;
list_for_each_entry_safe(pos, next, &state->pci_devices, node) {
+ if (pos->smbios_label)
+ free(pos->smbios_label);
+ if (pos->sysfs_label)
+ free(pos->sysfs_label);
list_del(&pos->node);
free(pos);
}
}
+static void set_pci_slots(struct libbiosdevname_state *state)
+{
+ struct pci_device *dev;
+
+ list_for_each_entry(dev, &state->pci_devices, node) {
+ dev_to_slot(state, dev);
+ }
+}
+
+
+static int set_pci_slot_index(struct libbiosdevname_state *state)
+{
+ struct pci_device *pcidev;
+ int prevslot=-1;
+ int index=1;
+
+ /* only iterate over the PCI devices, because the bios_device list may be incomplete due to renames happening in parallel */
+ list_for_each_entry(pcidev, &state->pci_devices, node) {
+ if (pcidev->physical_slot == 0) /* skip embedded devices */
+ continue;
+ if (!is_pci_network(pcidev)) /* only look at PCI network devices */
+ continue;
+ if (pcidev->is_sriov_virtual_function) /* skip sriov VFs, they're handled later */
+ continue;
+ if (pcidev->physical_slot != prevslot) {
+ index=1;
+ prevslot = pcidev->physical_slot;
+ }
+ else
+ index++;
+ pcidev->index_in_slot = index;
+ }
+ return 0;
+}
+
+static int set_embedded_index(struct libbiosdevname_state *state)
+{
+ struct pci_device *pcidev;
+ int index=1;
+
+ list_for_each_entry(pcidev, &state->pci_devices, node) {
+ if (pcidev->physical_slot != 0) /* skip non-embedded devices */
+ continue;
+ if (!is_pci_network(pcidev)) /* only look at PCI network devices */
+ continue;
+ if (pcidev->is_sriov_virtual_function) /* skip sriov VFs, they're handled later */
+ continue;
+ pcidev->embedded_index = index;
+ pcidev->embedded_index_valid = 1;
+ index++;
+ }
+ return 0;
+}
+
+static void set_sriov_pf_vf(struct libbiosdevname_state *state)
+{
+ struct pci_device *vf;
+ list_for_each_entry(vf, &state->pci_devices, node) {
+ if (!vf->is_sriov_virtual_function)
+ continue;
+ try_add_vf_to_pf(state, vf);
+ }
+}
+
+/*
+ * This sorts the PCI devices by breadth-first domain/bus/dev/fn.
+ */
+static int sort_pci(const struct pci_device *a, const struct pci_device *b)
+{
+
+ if (a->pci_dev->domain < b->pci_dev->domain) return -1;
+ else if (a->pci_dev->domain > b->pci_dev->domain) return 1;
+
+ if (a->pci_dev->bus < b->pci_dev->bus) return -1;
+ else if (a->pci_dev->bus > b->pci_dev->bus) return 1;
+
+ if (a->pci_dev->dev < b->pci_dev->dev) return -1;
+ else if (a->pci_dev->dev > b->pci_dev->dev) return 1;
+
+ if (a->pci_dev->func < b->pci_dev->func) return -1;
+ else if (a->pci_dev->func > b->pci_dev->func) return 1;
+
+ return 0;
+}
+
+static void insertion_sort_devices(struct pci_device *a, struct list_head *list,
+ int (*cmp)(const struct pci_device *, const struct pci_device *))
+{
+ struct pci_device *b;
+ list_for_each_entry(b, list, node) {
+ if (cmp(a, b) <= 0) {
+ list_move_tail(&a->node, &b->node);
+ return;
+ }
+ }
+ list_move_tail(&a->node, list);
+}
+
+static void sort_device_list(struct libbiosdevname_state *state)
+{
+ LIST_HEAD(sorted_devices);
+ struct pci_device *dev, *tmp;
+ list_for_each_entry_safe(dev, tmp, &state->pci_devices, node) {
+ insertion_sort_devices(dev, &sorted_devices, sort_pci);
+ }
+ list_splice(&sorted_devices, &state->pci_devices);
+}
+
int get_pci_devices(struct libbiosdevname_state *state)
{
struct pci_access *pacc;
struct pci_dev *p;
- struct pci_device *dev;
struct routing_table *table;
int rc=0;
+ table = pirq_alloc_read_table();
+ if (table)
+ state->pirq_table = table;
+
pacc = pci_alloc();
if (!pacc)
return rc;
-
+ state->pacc = pacc;
pci_init(pacc);
pci_scan_bus(pacc);
- table = pirq_alloc_read_table();
- if (!table)
- goto out;
-
for (p=pacc->devices; p; p=p->next) {
- dev = find_dev_by_pci(state, p);
- if (!dev)
- add_pci_dev(state, table, pacc, p);
+ add_pci_dev(state, p);
}
+ /* ordering here is important */
+ dmidecode_main(state); /* this will fail on Xen guests, that's OK */
+ sort_device_list(state);
+ set_pci_slots(state);
+ set_embedded_index(state);
+ set_pci_slot_index(state);
+ set_sriov_pf_vf(state);
- pirq_free_table(table);
-out:
- pci_cleanup(pacc);
return rc;
}
-
-static int parse_pci_name(const char *s, int *domain, int *bus, int *dev, int *func)
-{
- int err;
-/* The domain part was added in 2.6 kernels. Test for that first. */
- err = sscanf(s, "%x:%2x:%2x.%x", domain, bus, dev, func);
- if (err != 4) {
- err = sscanf(s, "%2x:%2x.%x", bus, dev, func);
- if (err != 3) {
- return 1;
- }
- }
- return 0;
-}
-
int unparse_pci_name(char *buf, int size, const struct pci_dev *pdev)
{
- return snprintf(buf, size, "%04x:%02x:%02x.%d",
+ return snprintf(buf, size, "%04x:%02x:%02x.%x",
pci_domain_nr(pdev), pdev->bus, pdev->dev, pdev->func);
}
@@ -173,15 +525,19 @@ static int unparse_smbios_type41_type(char *buf, const int size, const int type)
return (s-buf);
}
-
int unparse_pci_device(char *buf, const int size, const struct pci_device *p)
{
char *s = buf;
+ struct pci_device *dev;
+ char pci_name[16];
s += snprintf(s, size-(s-buf), "PCI name : ");
- s += unparse_pci_name(s, size-(s-buf), &p->pci_dev);
+ s += unparse_pci_name(s, size-(s-buf), p->pci_dev);
s += snprintf(s, size-(s-buf), "\n");
s += snprintf(s, size-(s-buf), "PCI Slot : ");
- s += unparse_location(s, size-(s-buf), p->physical_slot);
+ if (p->physical_slot < INT_MAX)
+ s += unparse_location(s, size-(s-buf), p->physical_slot);
+ else
+ s += snprintf(s, size-(s-buf), "Unknown");
s += snprintf(s, size-(s-buf), "\n");
if (p->smbios_type) {
s += snprintf(s, size-(s-buf), "SMBIOS Device Type: ");
@@ -189,17 +545,26 @@ int unparse_pci_device(char *buf, const int size, const struct pci_device *p)
s += snprintf(s, size-(s-buf), "SMBIOS Instance: %u\n", p->smbios_instance);
s += snprintf(s, size-(s-buf), "SMBIOS Enabled: %s\n", p->smbios_instance?"True":"False");
}
- return (s-buf);
-}
+ if (p->uses_smbios & HAS_SMBIOS_LABEL && p->smbios_label)
+ s += snprintf(s, size-(s-buf), "SMBIOS Label: %s\n", p->smbios_label);
+ if (p->uses_sysfs & HAS_SYSFS_INDEX)
+ s += snprintf(s, size-(s-buf), "sysfs Index: %u\n", p->sysfs_index);
+ if (p->uses_sysfs & HAS_SYSFS_LABEL)
+ s += snprintf(s, size-(s-buf), "sysfs Label: %s\n", p->sysfs_label);
+ if (p->physical_slot > 0 && !p->is_sriov_virtual_function)
+ s += snprintf(s, size-(s-buf), "Index in slot: %u\n", p->index_in_slot);
+ if (p->embedded_index_valid)
+ s += snprintf(s, size-(s-buf), "Embededed Index: %u\n", p->embedded_index);
+
+ if (!list_empty(&p->vfs)) {
+ s += snprintf(s, size-(s-buf), "Virtual Functions:\n");
+ list_for_each_entry(dev, &p->vfs, vfnode) {
+ unparse_pci_name(pci_name, sizeof(pci_name), dev->pci_dev);
+ s += snprintf(s, size-(s-buf), "%s\n", pci_name);
+ }
+ }
-static int is_same_pci(const struct pci_dev *a, const struct pci_dev *b)
-{
- if (pci_domain_nr(a) == pci_domain_nr(b) &&
- a->bus == b->bus &&
- a->dev == b->dev &&
- a->func == b->func)
- return 1;
- return 0;
+ return (s-buf);
}
struct pci_device * find_dev_by_pci(const struct libbiosdevname_state *state,
@@ -207,7 +572,7 @@ struct pci_device * find_dev_by_pci(const struct libbiosdevname_state *state,
{
struct pci_device *dev;
list_for_each_entry(dev, &state->pci_devices, node) {
- if (is_same_pci(p, &dev->pci_dev))
+ if (is_same_pci(p, dev->pci_dev))
return dev;
}
return NULL;
@@ -217,17 +582,18 @@ struct pci_device * find_pci_dev_by_pci_addr(const struct libbiosdevname_state *
const int domain, const int bus, const int device, const int func)
{
struct pci_device *dev;
- struct pci_device p;
+ struct pci_dev p;
+ memset(&p, 0, sizeof(p));
#ifdef HAVE_STRUCT_PCI_DEV_DOMAIN
- p.pci_dev.domain = domain;
+ p.domain = domain;
#endif
- p.pci_dev.bus = bus;
- p.pci_dev.dev = device;
- p.pci_dev.func = func;
+ p.bus = bus;
+ p.dev = device;
+ p.func = func;
list_for_each_entry(dev, &state->pci_devices, node) {
- if (is_same_pci(&p.pci_dev, &dev->pci_dev))
+ if (is_same_pci(&p, dev->pci_dev))
return dev;
}
return NULL;
diff --git a/src/pci.h b/src/pci.h
index fbd195a..78d6c9f 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -7,6 +7,7 @@
#ifndef PCI_H_INCLUDED
#define PCI_H_INCLUDED
+#include <limits.h>
#include <pci/pci.h>
#include "list.h"
#include "state.h"
@@ -14,15 +15,38 @@
struct pci_device {
struct list_head node;
- struct pci_dev pci_dev;
+ struct pci_dev *pci_dev;
int physical_slot;
- unsigned int index_in_slot;
+ unsigned int index_in_slot; /* only valid if physical_slot > 0 and not a VF */
+ unsigned int embedded_index; /* only valid if embedded_index_valid */
unsigned short int class;
+ unsigned char uses_smbios;
unsigned char smbios_type;
unsigned char smbios_instance;
unsigned char smbios_enabled;
+ char *smbios_label;
+ unsigned int sysfs_index;
+ char * sysfs_label;
+ unsigned char uses_sysfs;
+ unsigned int vf_index;
+ struct pci_device *pf;
+ struct list_head vfnode;
+ struct list_head vfs;
+ unsigned int is_sriov_physical_function:1;
+ unsigned int is_sriov_virtual_function:1;
+ unsigned int embedded_index_valid:1;
};
+#define HAS_SMBIOS_INSTANCE 1
+#define HAS_SMBIOS_LABEL 2
+#define HAS_SMBIOS_SLOT 4
+#define HAS_SMBIOS_EXACT_MATCH 8
+
+#define HAS_SYSFS_INDEX 1
+#define HAS_SYSFS_LABEL 2
+#define PHYSICAL_SLOT_UNKNOWN (INT_MAX)
+#define INDEX_IN_SLOT_UNKNOWN (INT_MAX)
+
extern int get_pci_devices(struct libbiosdevname_state *state);
extern void free_pci_devices(struct libbiosdevname_state *state);
@@ -37,6 +61,16 @@ static inline int is_pci_network(struct pci_device *dev)
return (dev->class & 0xFF00) == 0x0200;
}
+static inline int is_pci_smbios_type_ethernet(struct pci_device *dev)
+{
+ return (dev->smbios_type == 0x05);
+}
+
+static inline int is_pci_bridge(struct pci_device *dev)
+{
+ return (dev->pci_dev->device_class>>8 == 0x06);
+}
+
#ifdef HAVE_STRUCT_PCI_DEV_DOMAIN
static inline int pci_domain_nr(const struct pci_dev *dev)
{
diff --git a/src/pcmcia.c b/src/pcmcia.c
deleted file mode 100644
index a2c2ff5..0000000
--- a/src/pcmcia.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (c) 2006 Dell, Inc.
- * by Matt Domsch <Matt_Domsch@dell.com>
- *
- * Partly based on tools from pcmciautils-014, which states
- * in its header:
- * (C) 2004-2005 Dominik Brodowski <linux@brodo.de>
- *
- * Partly based on cardctl.c from pcmcia-cs-3.2.7/cardmgr/, which states
- * in its header:
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * Licensed under the terms of the GNU GPL License version 2.
- */
-
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <libgen.h>
-#include <linux/limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-
-#include "state.h"
-#include "pcmcia.h"
-
-#define MAX_SOCKET 8
-
-static unsigned char get_lan_tech(cistpl_funce_t *funce)
-{
- cistpl_lan_tech_t *t;
-
- if (funce->type == CISTPL_FUNCE_LAN_TECH) {
- t = (cistpl_lan_tech_t *)(funce->data);
- return t->tech;
- }
- return 0;
-}
-
-static unsigned char parse_tuple_for_network(tuple_t *tuple, cisparse_t *parse)
-{
- static int func = 0;
- unsigned char rc = 0;
-
- switch (tuple->TupleCode) {
- case CISTPL_FUNCID:
- func = parse->funcid.func;
- break;
- case CISTPL_FUNCE:
- if (func == CISTPL_FUNCID_NETWORK)
- rc = get_lan_tech(&parse->funce);
- break;
- default:
- break;
- }
- return rc;
-}
-
-int get_network_type(unsigned int socket_no, unsigned char *network_type)
-{
- int ret = 0;
- tuple_t tuple;
- unsigned char buf[256];
- cisparse_t parse;
- unsigned char n;
-
- memset(&tuple, 0, sizeof(tuple_t));
-
- ret = read_out_cis(socket_no, NULL);
- if (ret)
- return (ret);
-
- tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON;
- tuple.DesiredTuple = RETURN_FIRST_TUPLE;
-
- ret = pcmcia_get_first_tuple(BIND_FN_ALL, &tuple);
- if (ret)
- return (ret);
-
- while(tuple.TupleCode != CISTPL_END) {
- tuple.TupleData = buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
-
- pcmcia_get_tuple_data(&tuple);
-
- ret = pccard_parse_tuple(&tuple, &parse);
- if (ret == 0) {
- n = parse_tuple_for_network(&tuple, &parse);
- if (n) {
- *network_type = n;
- break;
- }
- }
-
- ret = pcmcia_get_next_tuple(BIND_FN_ALL, &tuple);
- if (ret)
- break;
- }
-
- return (ret);
-}
-
-/**
- * sysfs_path_is_file: Check if the path supplied points to a file
- * @path: path to validate
- * Returns 0 if path points to file, 1 otherwise
- * Copied from sysfsutils-2.1.0 (which is LGPL2.1 or later), relicensed GPLv2 for use here.
- */
-static int sysfs_path_is_file(const char *path)
-{
- struct stat astats;
-
- if (!path) {
- errno = EINVAL;
- return 1;
- }
- if ((lstat(path, &astats)) != 0) {
- return 1;
- }
- if (S_ISREG(astats.st_mode))
- return 0;
-
- return 1;
-}
-
-
-
-static int pccardctl_socket_exists(unsigned long socket_no)
-{
- char file[PATH_MAX];
-
- snprintf(file, sizeof(file),
- "/sys/class/pcmcia_socket/pcmcia_socket%lu/card_insert",
- socket_no);
-
- return (!(sysfs_path_is_file(file)));
-}
-
-static int read_out_file(char * file, char **output)
-{
- int ret;
- char *result = NULL;
- int fd;
- unsigned long resultsize = 0;
- ssize_t length = 0;
-
-
- *output = NULL;
-
- resultsize = getpagesize() + 1;
- result = malloc(resultsize);
- if (!result)
- return -ENOMEM;
- memset(result, 0, resultsize);
-
- fd = open(file, O_RDONLY);
- if (fd < 0) {
- ret = -1;
- goto free_out;
- }
-
- length = read(fd, result, resultsize-1);
- if (length < 0) {
- close(fd);
- ret = -1;
- goto free_out;
- }
- result[length] = '\0';
- if (result[length-1] == '\n')
- result[length-1] = '\0';
- *output = result;
- ret = 0;
- goto out;
-free_out:
- free(result);
-out:
- return ret;
-}
-
-static int pccardctl_get_one_f(unsigned long socket_no, unsigned int dev, const char *in_file, unsigned int *result)
-{
- char *value;
- char file[PATH_MAX];
- int ret;
-
- snprintf(file, sizeof(file), "/sys/bus/pcmcia/devices/%lu.%u/%s",
- socket_no, dev, in_file);
- ret = read_out_file(file, &value);
- if (ret || !value)
- return -EINVAL;
-
- if (sscanf(value, "0x%X", result) != 1)
- return -EIO;
- return 0;
-}
-
-static int pccardctl_get_one(unsigned long socket_no, const char *in_file, unsigned int *result)
-{
- return pccardctl_get_one_f(socket_no, 0, in_file, result);
-}
-
-static int alloc_pcmcia(struct libbiosdevname_state *state,
- unsigned long int socket_no)
-{
- char file[PATH_MAX];
- char dev_s[PATH_MAX];
- char *dev;
- int ret, i;
- int rc;
-
- if (!pccardctl_socket_exists(socket_no))
- return -ENODEV;
-
- snprintf(file, sizeof(file), "/sys/class/pcmcia_socket/pcmcia_socket%lu/device", socket_no);
- ret = readlink(file, dev_s, sizeof(dev_s) - 1);
- if (ret > 0) {
- dev_s[ret]='\0';
- dev = basename(dev_s);
- } else {
- snprintf(file, sizeof(file), "/sys/class/pcmcia_socket/pcmcia_socket%lu", socket_no);
- ret = readlink(file, dev_s, sizeof(dev_s) - 1);
- if (ret <= 0)
- return -ENODEV;
- dev_s[ret]='\0';
- dev = basename(dirname(dev_s));
- }
-
- for (i=0; i<4; i++) {
- unsigned int function;
- unsigned int function_id;
- struct pcmcia_device *pdev;
- unsigned char network_type = 0;
-
- if (pccardctl_get_one_f(socket_no, i, "function", &function))
- continue;
-
- pdev = malloc(sizeof(*pdev));
- if (!pdev)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&pdev->node);
- pdev->socket = socket_no;
- pdev->function = i;
- if (!pccardctl_get_one(socket_no, "func_id", &function_id))
- pdev->function_id = function_id;
-
- rc = get_network_type(socket_no, &network_type);
- if (!rc)
- pdev->network_type = network_type;
-
- list_add_tail(&pdev->node, &state->pcmcia_devices);
- }
- return 0;
-}
-
-void free_pcmcia_devices(struct libbiosdevname_state *state)
-{
- struct pcmcia_device *pos, *next;
- list_for_each_entry_safe(pos, next, &state->pcmcia_devices, node) {
- list_del(&pos->node);
- free(pos);
- }
-}
-
-int get_pcmcia_devices(struct libbiosdevname_state *state)
-{
- unsigned long int socket_no;
- for (socket_no = 0; socket_no < MAX_SOCKET; socket_no++) {
- alloc_pcmcia(state, socket_no);
- }
- return 0;
-}
-
-int unparse_pcmcia_name(char *buf, int size, const struct pcmcia_device *pdev)
-{
- return snprintf(buf, size, "%u.%u", pdev->socket, pdev->function);
-}
-
-int unparse_pcmcia_device(char *buf, const int size, const struct pcmcia_device *p)
-{
- char *s = buf;
- s += snprintf(s, size-(s-buf), "PCMCIA location : ");
- s += unparse_pcmcia_name(s, size-(s-buf), p);
- s += snprintf(s, size-(s-buf), "\n");
- return (s-buf);
-}
-
diff --git a/src/pcmcia.h b/src/pcmcia.h
deleted file mode 100644
index a8aea93..0000000
--- a/src/pcmcia.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2006 Dell, Inc.
- * by Matt Domsch <Matt_Domsch@dell.com>
- * Licensed under the GNU General Public license, version 2.
- */
-
-#ifndef PCMCIA_H_INCLUDED
-#define PCMCIA_H_INCLUDED
-
-#include "list.h"
-#include "cistpl.h"
-#include "state.h"
-
-struct pcmcia_device {
- struct list_head node;
- unsigned int socket;
- unsigned int function;
- int function_id;
- int network_type;
-};
-
-extern int get_pcmcia_devices(struct libbiosdevname_state *state);
-extern void free_pcmcia_devices(struct libbiosdevname_state *state);
-extern int unparse_pcmcia_name(char *buf, int size, const struct pcmcia_device *pdev);
-extern int unparse_pcmcia_device(char *buf, const int size, const struct pcmcia_device *p);
-
-static inline int is_pcmcia_network(struct pcmcia_device *dev)
-{
- return dev->function_id == CISTPL_FUNCID_NETWORK &&
- (dev->network_type == CISTPL_LAN_TECH_ETHERNET ||
- dev->network_type == CISTPL_LAN_TECH_WIRELESS);
-}
-
-
-#endif /* PCMCIA_H_INCLUDED */
diff --git a/src/pirq.c b/src/pirq.c
index a342ac3..bf2ef2a 100644
--- a/src/pirq.c
+++ b/src/pirq.c
@@ -50,16 +50,11 @@ struct routing_table * pirq_alloc_read_table()
int fd=open("/dev/mem", O_RDONLY);
if(fd==-1)
- {
- perror("open(/dev/mem)");
return NULL;
- }
mem = mmap(0, 64*1024, PROT_READ, MAP_SHARED, fd, 0xF0000L);
- if (!mem) {
- perror("mmap(/dev/mem)");
+ if (mem == (void *)-1LL)
goto out;
- }
while( offset < 0xFFFF)
{
@@ -94,7 +89,8 @@ out:
void pirq_free_table(struct routing_table *table)
{
- free(table);
+ if (table)
+ free(table);
}
diff --git a/src/read-cis.c b/src/read-cis.c
deleted file mode 100644
index 9ee71e2..0000000
--- a/src/read-cis.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * read-cis.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * (C) 1999 David A. Hinds
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <syslog.h>
-#include <linux/limits.h>
-
-#include "cistpl.h"
-
-#define MAX_TUPLES 0x200
-
-#define PATH_TO_SOCKET "/sys/class/pcmcia_socket/"
-
-/* Bits in attr field */
-#define IS_ATTR 1
-#define IS_INDIRECT 8
-
-
-static unsigned int functions;
-static unsigned char cis_copy[MAX_TUPLES];
-static unsigned int cis_length = MAX_TUPLES;
-
-
-#define SPACE(f) (((tuple_flags *)(&(f)))->space)
-#define HAS_LINK(f) (((tuple_flags *)(&(f)))->has_link)
-#define LINK_SPACE(f) (((tuple_flags *)(&(f)))->link_space)
-#define MFC_FN(f) (((tuple_flags *)(&(f)))->mfc_fn)
-
-
-static void read_cis(int attr, unsigned int addr, unsigned int len, void *ptr)
-{
- if (cis_length > addr+len)
- memcpy(ptr, cis_copy+addr, len);
- else
- memset(ptr, 0xff, len);
- return;
-}
-
-int pcmcia_get_next_tuple(unsigned int function, tuple_t *tuple);
-
-int pcmcia_get_first_tuple(unsigned int function, tuple_t *tuple)
-{
- tuple->TupleLink = tuple->Flags = 0;
- {
- /* Assume presence of a LONGLINK_C to address 0 */
- tuple->CISOffset = tuple->LinkOffset = 0;
- SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
- }
- if ((functions > 1) &&
- !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
- unsigned char req = tuple->DesiredTuple;
- tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
- if (!pcmcia_get_next_tuple(function, tuple)) {
- tuple->DesiredTuple = CISTPL_LINKTARGET;
- if (pcmcia_get_next_tuple(function, tuple))
- return -ENODEV;
- } else
- tuple->CISOffset = tuple->TupleLink = 0;
- tuple->DesiredTuple = req;
- }
- return pcmcia_get_next_tuple(function, tuple);
-}
-
-
-static int follow_link(tuple_t *tuple)
-{
- char link[5];
- unsigned int ofs;
-
- if (MFC_FN(tuple->Flags)) {
- /* Get indirect link from the MFC tuple */
- read_cis(LINK_SPACE(tuple->Flags),
- tuple->LinkOffset, 5, link);
- ofs = *(u_int *)(link+1);
- SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
- /* Move to the next indirect link */
- tuple->LinkOffset += 5;
- MFC_FN(tuple->Flags)--;
- } else if (HAS_LINK(tuple->Flags)) {
- ofs = tuple->LinkOffset;
- SPACE(tuple->Flags) = LINK_SPACE(tuple->Flags);
- HAS_LINK(tuple->Flags) = 0;
- } else {
- return -1;
- }
- if (SPACE(tuple->Flags)) {
- /* This is ugly, but a common CIS error is to code the long
- link offset incorrectly, so we check the right spot... */
- read_cis(SPACE(tuple->Flags), ofs, 5, link);
- if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
- (strncmp(link+2, "CIS", 3) == 0))
- return ofs;
- /* Then, we try the wrong spot... */
- ofs = ofs >> 1;
- }
- read_cis(SPACE(tuple->Flags), ofs, 5, link);
- if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
- (strncmp(link+2, "CIS", 3) == 0))
- return ofs;
- return -1;
-}
-
-int pcmcia_get_next_tuple(unsigned int function, tuple_t *tuple)
-{
- unsigned char link[2], tmp;
- int ofs, i, attr;
-
- link[1] = tuple->TupleLink;
- ofs = tuple->CISOffset + tuple->TupleLink;
- attr = SPACE(tuple->Flags);
-
- for (i = 0; i < MAX_TUPLES; i++) {
- if (link[1] == 0xff) {
- link[0] = CISTPL_END;
- } else {
- read_cis(attr, ofs, 2, link);
- if (link[0] == CISTPL_NULL) {
- ofs++; continue;
- }
- }
-
- /* End of chain? Follow long link if possible */
- if (link[0] == CISTPL_END) {
- if ((ofs = follow_link(tuple)) < 0)
- return -ENODEV;
- attr = SPACE(tuple->Flags);
- read_cis(attr, ofs, 2, link);
- }
-
- /* Is this a link tuple? Make a note of it */
- if ((link[0] == CISTPL_LONGLINK_A) ||
- (link[0] == CISTPL_LONGLINK_C) ||
- (link[0] == CISTPL_LONGLINK_MFC) ||
- (link[0] == CISTPL_LINKTARGET) ||
- (link[0] == CISTPL_INDIRECT) ||
- (link[0] == CISTPL_NO_LINK)) {
- switch (link[0]) {
- case CISTPL_LONGLINK_A:
- HAS_LINK(tuple->Flags) = 1;
- LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
- read_cis(attr, ofs+2, 4, &tuple->LinkOffset);
- break;
- case CISTPL_LONGLINK_C:
- HAS_LINK(tuple->Flags) = 1;
- LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
- read_cis(attr, ofs+2, 4, &tuple->LinkOffset);
- break;
- case CISTPL_INDIRECT:
- HAS_LINK(tuple->Flags) = 1;
- LINK_SPACE(tuple->Flags) = IS_ATTR | IS_INDIRECT;
- tuple->LinkOffset = 0;
- break;
- case CISTPL_LONGLINK_MFC:
- tuple->LinkOffset = ofs + 3;
- LINK_SPACE(tuple->Flags) = attr;
- if (function == BIND_FN_ALL) {
- /* Follow all the MFC links */
- read_cis(attr, ofs+2, 1, &tmp);
- MFC_FN(tuple->Flags) = tmp;
- } else {
- /* Follow exactly one of the links */
- MFC_FN(tuple->Flags) = 1;
- tuple->LinkOffset += function * 5;
- }
- break;
- case CISTPL_NO_LINK:
- HAS_LINK(tuple->Flags) = 0;
- break;
- }
- if ((tuple->Attributes & TUPLE_RETURN_LINK) &&
- (tuple->DesiredTuple == RETURN_FIRST_TUPLE))
- break;
- } else
- if (tuple->DesiredTuple == RETURN_FIRST_TUPLE)
- break;
-
- if (link[0] == tuple->DesiredTuple)
- break;
- ofs += link[1] + 2;
- }
- if (i == MAX_TUPLES)
- return -ENODEV;
-
- tuple->TupleCode = link[0];
- tuple->TupleLink = link[1];
- tuple->CISOffset = ofs + 2;
-
- return 0;
-}
-
-#define _MIN(a, b) (((a) < (b)) ? (a) : (b))
-
-int pcmcia_get_tuple_data(tuple_t *tuple)
-{
- unsigned int len;
-
- if (tuple->TupleLink < tuple->TupleOffset)
- return -ENODEV;
- len = tuple->TupleLink - tuple->TupleOffset;
- tuple->TupleDataLen = tuple->TupleLink;
- if (len == 0)
- return 0;
-
- read_cis (SPACE(tuple->Flags),
- tuple->CISOffset + tuple->TupleOffset,
- _MIN(len, tuple->TupleDataMax),
- tuple->TupleData);
-
- return 0;
-}
-
-
-int read_out_cis (unsigned int socket_no, FILE *fd)
-{
- char file[PATH_MAX];
- int ret, i;
- tuple_t tuple;
- unsigned char buf[256];
-
- snprintf(file, sizeof(file), PATH_TO_SOCKET "pcmcia_socket%d/cis",
- socket_no);
-
- if (!fd) {
- fd = fopen(file, "r");
- if (!fd)
- return -EIO;
- }
-
- for (i=0; i<MAX_TUPLES; i++) {
- ret = fgetc(fd);
- if (ret == EOF) {
- cis_length = i + 1;
- break;
- }
- cis_copy[i] = (unsigned char) ret;
- }
- fclose(fd);
-
- if (cis_length < 4)
- return -EINVAL;
-
- functions = 1;
-
- tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
- tuple.Attributes = TUPLE_RETURN_COMMON;
-
- ret = pcmcia_get_first_tuple(BIND_FN_ALL, &tuple);
- if (ret)
- functions = 1;
-
- tuple.TupleData = buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- ret = pcmcia_get_tuple_data(&tuple);
- if (ret)
- return -EBADF;
-
- functions = tuple.TupleData[0];
-
- return 0;
-}
diff --git a/src/read_proc.c b/src/read_proc.c
index aea203f..c89cb6d 100644
--- a/src/read_proc.c
+++ b/src/read_proc.c
@@ -25,7 +25,7 @@ static struct network_device *add_interface(struct libbiosdevname_state *state,
return NULL;
memset(i, 0, sizeof(*i));
INIT_LIST_HEAD(&i->node);
- snprintf(i->kernel_name, sizeof(i->kernel_name), name);
+ strncpy(i->kernel_name, name, sizeof(i->kernel_name));
list_add_tail(&i->node, &state->network_devices);
return i;
}
@@ -96,10 +96,8 @@ int get_interfaces(struct libbiosdevname_state *state)
s = get_name(&name, line);
add_interface(state, name);
}
- if (ferror(fh)) {
- perror(_PATH_PROCNET_DEV);
+ if (ferror(fh))
err = -1;
- }
out:
free(line);
diff --git a/src/state.h b/src/state.h
index 25bcc61..220bffd 100644
--- a/src/state.h
+++ b/src/state.h
@@ -6,13 +6,16 @@
#ifndef LIBBIOSDEVICE_STATE_H_INCLUDED
#define LIBBIOSDEVICE_STATE_H_INCLUDED
+#include <pci/pci.h>
#include "list.h"
+#include "pirq.h"
struct libbiosdevname_state {
struct list_head bios_devices;
struct list_head pci_devices;
- struct list_head pcmcia_devices;
struct list_head network_devices;
+ struct pci_access *pacc;
+ struct routing_table *pirq_table;
};
#endif /* LIBBIOSDEVICESTATE_H_INCLUDED */
diff --git a/src/sysfs.c b/src/sysfs.c
new file mode 100644
index 0000000..f2c616e
--- /dev/null
+++ b/src/sysfs.c
@@ -0,0 +1,68 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+/**
+ * sysfs_path_is_file: Check if the path supplied points to a file
+ * @path: path to validate
+ * Returns 0 if path points to file, 1 otherwise
+ * Copied from sysfsutils-2.1.0 (which is LGPL2.1 or later), relicensed GPLv2 for use here.
+ */
+int sysfs_path_is_file(const char * path)
+{
+ struct stat astats;
+
+ if (!path) {
+ errno = EINVAL;
+ return 1;
+ }
+ if ((lstat(path, &astats)) != 0) {
+ return 1;
+ }
+ if (S_ISREG(astats.st_mode))
+ return 0;
+
+ return 1;
+}
+
+int sysfs_read_file(const char * path, char **output)
+{
+ int ret;
+ char *result = NULL;
+ int fd;
+ unsigned long resultsize = 0;
+ ssize_t length = 0;
+
+ resultsize = getpagesize();
+ result = malloc(resultsize);
+ if (!result)
+ return -ENOMEM;
+ memset(result, 0, resultsize);
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ ret = fd;
+ goto free_out;
+ }
+
+ length = read(fd, result, resultsize-1);
+ if (length < 0) {
+ close(fd);
+ ret = -1;
+ goto free_out;
+ }
+ result[length] = '\0';
+ if (result[length-1] == '\n')
+ result[length-1] = '\0';
+ *output = result;
+ ret = 0;
+ goto out;
+free_out:
+ free(result);
+out:
+ return ret;
+}
diff --git a/src/sysfs.h b/src/sysfs.h
new file mode 100644
index 0000000..91bfb15
--- /dev/null
+++ b/src/sysfs.h
@@ -0,0 +1,2 @@
+extern int sysfs_path_is_file(const char *path);
+extern int sysfs_read_file(const char *path, char **output);