From 4d155cbf37ca909daff06dd8c7119274d0861f6c Mon Sep 17 00:00:00 2001 From: Bob Gilligan Date: Sun, 16 Jan 2011 22:44:12 -0800 Subject: Merge upstream version 0.3.4. (cherry picked from commit 21eb1c8d6fefa5dcd3a9a800b4add06d5c30c01f) --- AUTHORS | 6 - ChangeLog | 4 + Makefile.am | 32 +- biosdevname.1 | 53 ++- biosdevname.rules.in | 12 +- biosdevname.spec.fedora.in | 59 ++- biosdevname.spec.suse.in | 36 +- configure.ac | 14 +- src/Makefile.am | 10 +- src/bios_dev_name.c | 35 +- src/bios_dev_name.h | 1 + src/bios_device.c | 156 +++----- src/bios_device.h | 10 +- src/cistpl.h | 605 ------------------------------- src/dmidecode/dmidecode.c | 107 +++--- src/dmidecode/dmidecode.h | 13 + src/dmidecode/dmioem.c | 1 + src/dmidecode/util.c | 3 - src/eths.c | 3 - src/libbiosdevname.h | 11 +- src/naming_policy.c | 130 ++++--- src/naming_policy.h | 2 +- src/parse_cis.c | 882 --------------------------------------------- src/pci.c | 526 +++++++++++++++++++++++---- src/pci.h | 38 +- src/pcmcia.c | 295 --------------- src/pcmcia.h | 35 -- src/pirq.c | 10 +- src/read-cis.c | 275 -------------- src/read_proc.c | 6 +- src/state.h | 5 +- src/sysfs.c | 68 ++++ src/sysfs.h | 2 + 33 files changed, 937 insertions(+), 2508 deletions(-) delete mode 100644 src/cistpl.h delete mode 100644 src/parse_cis.c delete mode 100644 src/pcmcia.c delete mode 100644 src/pcmcia.h delete mode 100644 src/read-cis.c create mode 100644 src/sysfs.c create mode 100644 src/sysfs.h diff --git a/AUTHORS b/AUTHORS index 4a31cc8..04ca7ae 100644 --- a/AUTHORS +++ b/AUTHORS @@ -10,12 +10,6 @@ read_proc.c: ethtool-copy.h: Cribbed from ethtool -pcmcia.c, cistpl.h, parse_cis.c, read-cis.c: - Cribbed from pcmciautils-014 - -pcmcia.c sysfs_path_is_file() - Cribbed from sysfsutils-2.1.0 (LGPLv2+, relicensed and used here as GPLv2) - dmidecode/* Cribbed from dmidecode 2.9 diff --git a/ChangeLog b/ChangeLog index 3997e39..8bfc10e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +* Mon Jul 27 2009 +- add SMBIOS naming policy +- fix return error check for mmap + * Wed Nov 28 2006 - fix usage() being printed on success - don't assign BIOS device names to Linux virtual devices (tun0) diff --git a/Makefile.am b/Makefile.am index 80548a8..6b65b5e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,15 +1,19 @@ AUTOMAKE_OPTIONS = subdir-objects SUBDIRS = +EXTRA_DIST = pkg dist_noinst_DATA = biosdevname.rules.in biosdevname.spec.fedora biosdevname.spec.suse biosdevname.1 -CLEANFILES = biosdevname.rules version -biosdevname.rules: biosdevname.rules.in - sed -e 's#/usr/sbin#$(sbindir)#' $(top_srcdir)/biosdevname.rules.in > $(top_builddir)/biosdevname.rules -install-data-local: biosdevname.rules + +CLEANFILES = version +install-data-local: mkdir -p $(DESTDIR)@sysconfdir@/udev/rules.d - $(INSTALL_DATA) $(top_builddir)/biosdevname.rules $(DESTDIR)@sysconfdir@/udev/rules.d/@RULEDEST@ + $(INSTALL_DATA) $(top_srcdir)/biosdevname.rules.in $(DESTDIR)@sysconfdir@/udev/rules.d/71-netdevice.rules + mkdir -p $(DESTDIR)/lib/udev + +uninstall-local: + rm -f $(DESTDIR)@sysconfdir@/udev/rules.d/@RULEDEST@ include src/Makefile.am @@ -34,10 +38,24 @@ srpm: dist deb: dist oldpwd=`pwd` ; \ tmp_dir=`mktemp -d /tmp/$(PACKAGE_NAME).XXXXXXXX` ; \ - cp $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz $${tmpdir}/$(PACKAGE_NAME)_$(PACKAGE_VERSION).orig.tar.gz \ +cp $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz $${tmp_dir}/$(PACKAGE_NAME)_$(PACKAGE_VERSION).orig.tar.gz ; \ tar -C $${tmp_dir} -xzf $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz ; \ - mv $${tmp_dir}/$(PACKAGE_NAME)-$(PACKAGE_VERSION)/pkg/debian $${tmp_dir}/$(PACKAGE_NAME)-$(PACKAGE_VERSION)/debian ; \ cd $${tmp_dir}/$(PACKAGE_NAME)-$(PACKAGE_VERSION) ; \ + mv pkg/debian debian ; \ + rmdir pkg/ ; \ pdebuild --buildresult $$oldpwd/.. ; \ cd - ;\ rm -rf $${tmp_dir} + +sdeb: dist + oldpwd=`pwd` ; \ + tmp_dir=`mktemp -d /tmp/biosdevname.XXXXXXXX` ; \ + cp $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz $${tmp_dir}/$(PACKAGE_NAME)_$(PACKAGE_VERSION).orig.tar.gz ; \ + tar -C $${tmp_dir} -xzf $(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz ; \ + mv $${tmp_dir}/$(PACKAGE_NAME)-$(PACKAGE_VERSION)/pkg/debian $${tmp_dir}/$(PACKAGE_NAME)-$(PACKAGE_VERSION)/debian ; \ + rmdir pkg/ ; \ + cd $${tmp_dir}/$(PACKAGE_NAME)-$(PACKAGE_VERSION) ; \ + dpkg-buildpackage -S -sa -rfakeroot -k92F0FC09 ; \ + mv ../biosdevname_* $$oldpwd/.. ; \ + cd - ;\ + rm -rf $${tmp_dir} diff --git a/biosdevname.1 b/biosdevname.1 index 7cf4e4d..fd0f99b 100644 --- a/biosdevname.1 +++ b/biosdevname.1 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH BIOSDEVNAME 1 "May 16, 2007" +.TH BIOSDEVNAME 1 "Nov 28, 2010" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -21,7 +21,7 @@ biosdevname \- give BIOS-given name of a device .B biosdevname .RI [options]\ [args]... .SH DESCRIPTION -biosdevname in its simplest form takes a kernel device name as an +biosdevname takes a kernel device name as an argument, and returns the BIOS-given name it "should" be. .SH OPTIONS .TP @@ -31,10 +31,53 @@ Treat [args] as ethernet devs .B \-d, \-\-debug Enable debugging .TP -.B \-n, \-\-nosort -Don't sort the PCI device list breadth-first +.B \-\-policy \fI[physical|all_ethN] .TP -.B \-\-policy \fI[kernelnames|all_ethN|all_names|embedded_ethN_slots_names] +.B \-\-prefix \fI[string] +string use for embedded NICs in the physical policy (default=em) +.SH POLICIES +.br +The +.B physical +policy is the current default. However, when invoking biosdevname in +udev rules, one should always specify the policy you want, as the +default has changed over time. +.br +The +.B physical +policy uses the following scheme: +.TP +em +for embedded NICs +.TP +pci#_ +for cards in PCI slots +.br +.TP +The +.B all_ethN +policy makes a best guess at what the device order should be, with +embedded devices first, PCI cards in ascending slot order, and ports +in ascending PCI bus/device/function order breadth-first. However, +this policy +.I does not work +if your PCI devices are hot-plugged or hot-pluggable, including the +virtual functions on an SR-IOV device. In a hot-plug scenario, each separate +udev instance will be invoked in parallel, while the device tree is +still being populated with new devices. Each udev instance will see a +different PCI tree, and thus cannot provide consistent enumeration. +Use of this policy should be limited to only scenarios where all PCI +devices are present at boot (cold-plug). + +.SH RETURN CODES +Returns 0 on success, with BIOS-suggested name printed to stdout. +.br +Returns 1 on provided device name lookup failure. +.br +Returns 2 if system BIOS does not provide naming information. +biosdevname requires system BIOS to provide naming information, either +via SMBIOS or sysfs files. + .SH SEE ALSO .br http://linux.dell.com/files/biosdevname/ diff --git a/biosdevname.rules.in b/biosdevname.rules.in index 6159382..a3be69c 100644 --- a/biosdevname.rules.in +++ b/biosdevname.rules.in @@ -1,7 +1,9 @@ -KERNEL!="eth*", GOTO="biosdevname_end" -ACTION!="add", GOTO="biosdevname_end" -NAME=="?*", GOTO="biosdevname_end" +SUBSYSTEM!="net", GOTO="netdevicename_end" +KERNEL!="eth*", GOTO="netdevicename_end" +ACTION!="add", GOTO="netdevicename_end" -PROGRAM="/sbin/biosdevname --policy=all_ethN -i %k", ENV{INTERFACE_NAME}="%c" +# using NAME= instead of setting INTERFACE_NAME, so that persistent +# names aren't generated for these devices, they are "named" on each boot. +PROGRAM="/sbin/biosdevname --policy physical -i %k", NAME="%c", OPTIONS+="string_escape=replace" -LABEL="biosdevname_end" +LABEL="netdevicename_end" diff --git a/biosdevname.spec.fedora.in b/biosdevname.spec.fedora.in index 9a40dcc..7c77405 100644 --- a/biosdevname.spec.fedora.in +++ b/biosdevname.spec.fedora.in @@ -6,12 +6,11 @@ Summary: Udev helper for naming devices per BIOS names Group: System Environment/Base License: GPLv2 URL: http://linux.dell.com/files/%{name} -# SMBIOS and PCI IRQ Routing Tables only exist on these arches. It's -# also likely that other arches don't expect the PCI bus to be sorted -# breadth-first, or of so, there haven't been any comments about that -# on LKML. +# SMBIOS only exists on these arches. It's also likely that other +# arches don't expect the PCI bus to be sorted breadth-first, or of +# so, there haven't been any comments about that on LKML. ExclusiveArch: %{ix86} x86_64 ia64 -Source0: http://linux.dell.com/files/%{name}/%{name}-%{version}.tar.gz +Source0: http://linux.dell.com/files/%{name}/permalink/%{name}-%{version}.tar.gz BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildRequires: pciutils-devel, zlib-devel # to figure out how to name the rules file @@ -19,7 +18,6 @@ BuildRequires: udev # for ownership of /etc/udev/rules.d Requires: udev - %description biosdevname in its simplest form takes a kernel device name as an argument, and returns the BIOS-given name it "should" be. This is necessary @@ -38,7 +36,7 @@ make %{?_smp_mflags} %install rm -rf %{buildroot} -make install DESTDIR=%{buildroot} +make install install-data DESTDIR=%{buildroot} rm %{buildroot}/sbin/%{name}S || : %clean @@ -48,11 +46,54 @@ rm -rf %{buildroot} %defattr(-,root,root,-) %doc COPYING README /sbin/%{name} -%config(noreplace) %{_sysconfdir}/udev/rules.d/*%{name}.rules -%{_mandir}/1/%{name}.1 +%config(noreplace) %{_sysconfdir}/udev/rules.d/*.rules +%{_mandir}/man1/%{name}.1* %changelog +* Thu Dec 16 2010 Matt Domsch - 0.3.4-1 +- drop unnecessary explicit version requirement on udev +- bugfix: start indices at 1 not 0, to match Dell and HP server port designations +- bugfix: don't assign names to unknown devices +- bugfix: don't assign duplicate names + +* Thu Dec 9 2010 Matt Domsch - 0.3.3-1 +- add back in use of PCI IRQ Routing Table, if info is not provided by + sysfs or SMBIOS + +* Thu Dec 2 2010 Matt Domsch - 0.3.2-1 +- fix for multi-port cards with bridges +- removal of code for seriously obsolete systems + +* Mon Nov 28 2010 Matt Domsch 0.3.1-1 +- remove all policies except 'physical' and 'all_ethN' +- handle SR-IOV devices properly + +* Wed Nov 10 2010 Matt Domsch 0.3.0-1 +- add --policy=loms, make it default +- read index and labels from sysfs if available + +* Mon Jul 27 2009 Jordan Hargrave 0.2.5-1 +- fix mmap error checking + +* Fri Jul 24 2009 Fedora Release Engineering - 0.2.4-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Mon Feb 23 2009 Fedora Release Engineering - 0.2.4-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Tue May 06 2008 Matt Domsch 0.2.4-5 +- use policy=all_names to find breakage + +* Sun Feb 10 2008 Matt Domsch 0.2.4-4 +- rebuild for gcc43 + +* Fri Sep 21 2007 Matt Domsch 0.2.4-3 +- fix manpage entry in files + +* Fri Sep 21 2007 Matt Domsch 0.2.4-2 +- rebuild with Requires: udev > 115-3.20070920git + * Fri Sep 21 2007 Matt Domsch 0.2.4-1 - coordinate udev rules usage with udev maintainer - fix crashes in pcmcia search, in_ethernet(), and incorrect command diff --git a/biosdevname.spec.suse.in b/biosdevname.spec.suse.in index 9a40dcc..de00eaf 100644 --- a/biosdevname.spec.suse.in +++ b/biosdevname.spec.suse.in @@ -6,12 +6,11 @@ Summary: Udev helper for naming devices per BIOS names Group: System Environment/Base License: GPLv2 URL: http://linux.dell.com/files/%{name} -# SMBIOS and PCI IRQ Routing Tables only exist on these arches. It's -# also likely that other arches don't expect the PCI bus to be sorted -# breadth-first, or of so, there haven't been any comments about that -# on LKML. +# SMBIOS only exists on these arches. It's also likely that other +# arches don't expect the PCI bus to be sorted breadth-first, or of +# so, there haven't been any comments about that on LKML. ExclusiveArch: %{ix86} x86_64 ia64 -Source0: http://linux.dell.com/files/%{name}/%{name}-%{version}.tar.gz +Source0: http://linux.dell.com/files/%{name}/permalink/%{name}-%{version}.tar.gz BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildRequires: pciutils-devel, zlib-devel # to figure out how to name the rules file @@ -49,10 +48,35 @@ rm -rf %{buildroot} %doc COPYING README /sbin/%{name} %config(noreplace) %{_sysconfdir}/udev/rules.d/*%{name}.rules -%{_mandir}/1/%{name}.1 +%{_mandir}/man1/%{name}.1* %changelog +* Thu Dec 16 2010 Matt Domsch - 0.3.4-1 +- drop unnecessary explicit version requirement on udev +- bugfix: start indices at 1 not 0, to match Dell and HP server port designations +- bugfix: don't assign names to unknown devices +- bugfix: don't assign duplicate names + +* Thu Dec 9 2010 Matt Domsch - 0.3.3-1 +- add back in use of PCI IRQ Routing Table, if info is not provided by + sysfs or SMBIOS + +* Thu Dec 2 2010 Matt Domsch - 0.3.2-1 +- fix for multi-port cards with bridges +- removal of code for seriously obsolete systems + +* Mon Nov 28 2010 Matt Domsch 0.3.1-1 +- remove all policies except 'physical' and 'all_ethN' +- handle SR-IOV devices properly + +* Wed Nov 10 2010 Matt Domsch 0.3.0-1 +- add --policy=loms, make it default +- read index and labels from sysfs if available + +* Mon Jul 27 2009 Jordan Hargrave 0.2.5-1 +- fix mmap error checking + * Fri Sep 21 2007 Matt Domsch 0.2.4-1 - coordinate udev rules usage with udev maintainer - fix crashes in pcmcia search, in_ethernet(), and incorrect command diff --git a/configure.ac b/configure.ac index 5ee9c32..9c1b8d0 100644 --- a/configure.ac +++ b/configure.ac @@ -3,8 +3,9 @@ # vim:tw=0:ts=8:sw=8:et AC_PREREQ(2.59) -AC_INIT([biosdevname],[0.2.4],[Matt_Domsch@dell.com]) +AC_INIT([biosdevname],[0.3.4],[Matt_Domsch@dell.com]) AC_LANG([C]) +AC_USE_SYSTEM_EXTENSIONS AC_CONFIG_SRCDIR([src/read_proc.c]) AC_CONFIG_HEADER([config.h]) AC_PREFIX_DEFAULT() @@ -16,15 +17,17 @@ AC_PROG_AWK AC_PROG_CC AM_PROG_CC_C_O AC_PROG_LN_S +AC_PROG_CXX +AC_PROG_RANLIB AC_CHECK_PROGS([READELF], [readelf]) - +AC_CHECK_FUNCS([realpath]) # Checks for libraries. AC_CHECK_LIB([c], [snprintf]) # libz has to come before libpci because libpci needs it now. AC_CHECK_LIB([z], [gzopen], [], - [AC_MSG_ERROR([You must install zlib-devel or equivalent])]) + [AC_MSG_ERROR([You must install zlib-devel (Fedora/Red Hat/SuSE), libzip-dev (Debian/Ubuntu), or equivalent])]) AC_CHECK_LIB([pci], [pci_alloc], [], - [AC_MSG_ERROR([You must install pciutils or equivalent])], + [AC_MSG_ERROR([You must install pciutils-devel (Fedora/Red Hat/SuSE), pciutils-dev (Debian/Ubuntu), or equivalent])], -lz) # Checks for header files. @@ -44,6 +47,9 @@ AC_C_CONST AC_C_INLINE AC_TYPE_OFF_T AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T +AC_TYPE_UINT8_T +AC_TYPE_UINT16_T AC_HEADER_TIME AC_STRUCT_TM 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 #include #include +#include #include #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 - * . 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 #include #include +#include #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 = ""; static const char *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 - * . 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 -#include -#include -#include -#include -#include - -#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<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 * Licensed under the GNU General Public license, version 2. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include #include +#include #include -#include "pirq.h" +#include +#include #include #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 #include #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 - * - * Partly based on tools from pcmciautils-014, which states - * in its header: - * (C) 2004-2005 Dominik Brodowski - * - * 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 - * . 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#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 - * 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 - * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * (C) 1999 David A. Hinds - */ - -#include -#include -#include -#include -#include -#include - -#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; inode); - 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 #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 +#include +#include +#include +#include +#include +#include + +/** + * 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); -- cgit v1.2.3