summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <brodo@isilmar.linta.de>2005-12-06 20:21:40 +0100
committerDominik Brodowski <brodo@isilmar.linta.de>2005-12-06 20:21:40 +0100
commit48166159e549890157aad9a9428e311d2a6ad5a2 (patch)
treeda1fe0bbb60362bee8f137a6d791171a756e1291
downloadpcmciautils-48166159e549890157aad9a9428e311d2a6ad5a2.tar.gz
Release of pcmciautils-001 (2005-03-04)
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r--COPYING340
-rw-r--r--Makefile214
-rw-r--r--build/ccdv.c387
-rw-r--r--config/config.opts63
-rwxr-xr-xhotplug/pcmcia.agent53
-rwxr-xr-xhotplug/pcmcia.rc53
-rwxr-xr-xhotplug/pcmcia_socket.agent38
-rwxr-xr-xhotplug/pcmcia_socket.rc49
-rw-r--r--src/cistpl.h598
-rw-r--r--src/lex_config.l220
-rw-r--r--src/pccardctl.c329
-rw-r--r--src/pcmcia-check-broken-cis.c90
-rw-r--r--src/pcmcia-modalias.c149
-rw-r--r--src/read-cis.c266
-rw-r--r--src/startup.c223
-rw-r--r--src/startup.h54
-rw-r--r--src/yacc_config.h35
-rw-r--r--src/yacc_config.y131
18 files changed, 3292 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7410827
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,214 @@
+# Makefile for pcmciautils
+#
+# Copyright (C) 2005 Dominik Brodowski <linux@dominikbrodowski.net>
+#
+# Based largely on the Makefile for udev by:
+#
+# Copyright (C) 2003,2004 Greg Kroah-Hartman <greg@kroah.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+# Set the following to `true' to log the debug
+# and make a unstripped, unoptimized binary.
+# Leave this set to `false' for production use.
+DEBUG = false
+
+PCCARDCTL = pccardctl
+PCMCIA_CHECK_BROKEN_CIS = pcmcia-check-broken-cis
+PCMCIA_MODALIAS = pcmcia-modalias
+PCMCIA_SOCKET_STARTUP = pcmcia-socket-startup
+
+VERSION = 001
+#INSTALL_DIR = /usr/local/sbin
+RELEASE_NAME = pcmciautils-$(VERSION)
+
+#DESTDIR =
+
+KERNEL_DIR = /lib/modules/${shell uname -r}/build
+
+# override this to make udev look in a different location for it's config files
+prefix =
+exec_prefix = ${prefix}
+etcdir = ${prefix}/etc
+sbindir = ${exec_prefix}/sbin
+srcdir = .
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+
+# place to put our hotplug scripts nodes
+hotplugdir = ${prefix}/etc/hotplug
+
+# place where PCMICIA config is put to
+pcmciaconfdir = ${prefix}${etcdir}/pcmcia
+
+# make the build silent. Set this to something else to make it noisy again.
+V=false
+
+# set up PWD so that older versions of make will work with our build.
+PWD = $(shell pwd)
+
+# If you are running a cross compiler, you may want to set this
+# to something more interesting, like "arm-linux-". If you want
+# to compile vs uClibc, that can be done here as well.
+CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
+CC = $(CROSS)gcc
+LD = $(CROSS)gcc
+AR = $(CROSS)ar
+STRIP = $(CROSS)strip
+RANLIB = $(CROSS)ranlib
+HOSTCC = gcc
+
+export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS ARCH_LIB_OBJS CRT0
+
+# code taken from uClibc to determine the current arch
+ARCH := ${shell $(CC) -dumpmachine | sed -e s'/-.*//' -e 's/i.86/i386/' -e 's/sparc.*/sparc/' \
+ -e 's/arm.*/arm/g' -e 's/m68k.*/m68k/' -e 's/powerpc/ppc/g'}
+
+# code taken from uClibc to determine the gcc include dir
+GCCINCDIR := ${shell LC_ALL=C $(CC) -print-search-dirs | sed -ne "s/install: \(.*\)/\1include/gp"}
+
+# code taken from uClibc to determine the libgcc.a filename
+GCC_LIB := $(shell $(CC) -print-libgcc-file-name )
+
+# use '-Os' optimization if available, else use -O2
+OPTIMIZATION := ${shell if $(CC) -Os -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \
+ then echo "-Os"; else echo "-O2" ; fi}
+
+# check if compiler option is supported
+cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;}
+
+WARNINGS := -Wall -fno-builtin -Wchar-subscripts -Wpointer-arith -Wsign-compare
+WARNINGS += $(call cc-supports,-Wno-pointer-sign)
+WARNINGS += $(call cc-supports,-Wdeclaration-after-statement)
+WARNINGS += -Wshadow
+
+CFLAGS := -pipe
+
+HEADERS = \
+ src/cistpl.h \
+ src/startup.h \
+ src/yacc_config.h
+
+
+OBJS = \
+ src/lex_config.l \
+ src/pccardctl.c \
+ src/pcmcia-check-broken-cis.c \
+ src/pcmcia-modalias.c \
+ src/read-cis.c \
+ src/startup.c \
+ src/startup.h \
+ src/yacc_config.h \
+ src/yacc_config.y
+
+CFLAGS += -I$(PWD)/src
+
+#LIBC =
+CFLAGS += $(WARNINGS) -I$(GCCINCDIR)
+LIB_OBJS = -lc -lsysfs
+#LDFLAGS =
+
+ifeq ($(strip $(V)),false)
+ QUIET=@$(PWD)/build/ccdv
+ HOST_PROGS=build/ccdv
+else
+ QUIET=
+ HOST_PROGS=
+endif
+
+# if DEBUG is enabled, then we do not strip or optimize
+ifeq ($(strip $(DEBUG)),true)
+ CFLAGS += -O1 -g -DDEBUG -D_GNU_SOURCE
+ LDFLAGS += -Wl,-warn-common
+ STRIPCMD = /bin/true -Since_we_are_debugging
+else
+ CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer -D_GNU_SOURCE
+ LDFLAGS += -s -Wl,-warn-common
+ STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
+endif
+
+
+all: ccdv $(PCCARDCTL) $(PCMCIA_CHECK_BROKEN_CIS) $(PCMCIA_MODALIAS) $(PCMCIA_SOCKET_STARTUP)
+
+ccdv:
+ @echo "Building ccdv"
+ @$(HOSTCC) -O1 build/ccdv.c -o build/ccdv
+
+.c.o:
+ $(QUIET) $(CC) $(CFLAGS) -c -o $@ $<
+
+$(PCCARDCTL): $(LIBC) src/$(PCCARDCTL).o $(OBJS) $(HEADERS)
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) src/$(PCCARDCTL).o $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
+
+$(PCMCIA_CHECK_BROKEN_CIS): $(LIBC) src/$(PCMCIA_CHECK_BROKEN_CIS).o src/read-cis.o $(OBJS) $(HEADERS)
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) src/$(PCMCIA_CHECK_BROKEN_CIS).o src/read-cis.o $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
+
+$(PCMCIA_MODALIAS): $(LIBC) src/$(PCMCIA_MODALIAS).o $(OBJS) $(HEADERS)
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) src/$(PCMCIA_MODALIAS).o $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
+
+$(PCMCIA_SOCKET_STARTUP): $(LIBC) src/startup.o src/yacc_config.o src/lex_config.o $(OBJS) $(HEADERS)
+ $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) src/startup.o src/yacc_config.o src/lex_config.o $(LIB_OBJS) $(ARCH_LIB_OBJS)
+ $(QUIET) $(STRIPCMD) $@
+
+yacc_config.o lex_config.o: %.o: %.c
+ $(CC) -c -MD -O -pipe $(CPPFLAGS) $<
+
+clean:
+ -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
+ | xargs rm -f
+ -rm -f $(PCCARDCTL) $(PCMCIA_CHECK_BROKEN_CIS) $(PCMCIA_MODALIAS) $(PCMCIA_SOCKET_STARTUP)
+ -rm -f src/yacc_config.c src/yacc_config.d src/lex_config.c src/lex_config.d
+ -rm -f build/ccdv
+
+install-hotplug:
+ $(INSTALL) -d $(DESTDIR)$(hotplugdir)
+ $(INSTALL_PROGRAM) -D hotplug/pcmcia.agent $(DESTDIR)$(hotplugdir)/pcmcia.agent
+ $(INSTALL_PROGRAM) -D hotplug/pcmcia.rc $(DESTDIR)$(hotplugdir)/pcmcia.rc
+ $(INSTALL_PROGRAM) -D hotplug/pcmcia_socket.agent $(DESTDIR)$(hotplugdir)/pcmcia_socket.agent
+ $(INSTALL_PROGRAM) -D hotplug/pcmcia_socket.rc $(DESTDIR)$(hotplugdir)/pcmcia_socket.rc
+
+uninstall-hotplug:
+ - rm -f $(hotplugdir)/pcmcia.agent $(hotplugdir)/pcmcia.rc
+ - rm -f $(hotplugdir)/pcmcia_socket.agent $(hotplugdir)/pcmcia_socket.rc
+
+install-tools:
+ $(INSTALL) -d $(DESTDIR)$(sbindir)
+ $(INSTALL_PROGRAM) -D $(PCMCIA_MODALIAS) $(DESTDIR)$(sbindir)/$(PCMCIA_MODALIAS)
+ $(INSTALL_PROGRAM) -D $(PCMCIA_SOCKET_STARTUP) $(DESTDIR)$(sbindir)/$(PCMCIA_SOCKET_STARTUP)
+ $(INSTALL_PROGRAM) -D $(PCCARDCTL) $(DESTDIR)$(sbindir)/$(PCCARDCTL)
+ $(INSTALL_PROGRAM) -D $(PCMCIA_CHECK_BROKEN_CIS) $(DESTDIR)$(sbindir)/$(PCMCIA_CHECK_BROKEN_CIS)
+
+uninstall-tools:
+ - rm -f $(sbindir)/$(PCMCIA_MODALIAS)
+ - rm -f $(sbindir)/$(PCMCIA_SOCKET_STARTUP)
+ - rm -f $(sbindir)/$(PCCARDCTL)
+ - rm -f $(sbindir)/$(PCMCIA_CHECK_BROKEN_CIS)
+
+install-config:
+ $(INSTALL) -d $(DESTDIR)$(pcmciaconfdir)
+ $(INSTALL_DATA) -D config/config.opts $(DESTDIR)$(pcmciaconfdir)/config.opts
+
+uninstall-config:
+# - rm -f $(pcmciaconfdir)/config.opts
+
+install: install-tools install-hotplug install-config
+
+uninstall: uninstall-tools uninstall-hotplug uninstall-config
diff --git a/build/ccdv.c b/build/ccdv.c
new file mode 100644
index 0000000..e3ae9da
--- /dev/null
+++ b/build/ccdv.c
@@ -0,0 +1,387 @@
+/* ccdv.c
+ *
+ * Copyright (C) 2002-2003, by Mike Gleason, NcFTP Software.
+ * All Rights Reserved.
+ *
+ * Licensed under the GNU Public License.
+ */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define SETCOLOR_SUCCESS (gANSIEscapes ? "\033\1331;32m" : "")
+#define SETCOLOR_FAILURE (gANSIEscapes ? "\033\1331;31m" : "")
+#define SETCOLOR_WARNING (gANSIEscapes ? "\033\1331;33m" : "")
+#define SETCOLOR_NORMAL (gANSIEscapes ? "\033\1330;39m" : "")
+
+#define TEXT_BLOCK_SIZE 8192
+#define INDENT 2
+
+#define TERMS "vt100:vt102:vt220:vt320:xterm:xterm-color:ansi:linux:scoterm:scoansi:dtterm:cons25:cygwin"
+
+size_t gNBufUsed = 0, gNBufAllocated = 0;
+char *gBuf = NULL;
+int gCCPID;
+char gAction[200] = "";
+char gTarget[200] = "";
+char gAr[32] = "";
+char gArLibraryTarget[64] = "";
+int gDumpCmdArgs = 0;
+char gArgsStr[1000];
+int gColumns = 80;
+int gANSIEscapes = 0;
+int gExitStatus = 95;
+
+static void DumpFormattedOutput(void)
+{
+ char *cp;
+ char spaces[8 + 1] = " ";
+ char *saved;
+ int curcol;
+ int i;
+
+ curcol = 0;
+ saved = NULL;
+ for (cp = gBuf + ((gDumpCmdArgs == 0) ? strlen(gArgsStr) : 0); ; cp++) {
+ if (*cp == '\0') {
+ if (saved != NULL) {
+ cp = saved;
+ saved = NULL;
+ } else break;
+ }
+ if (*cp == '\r')
+ continue;
+ if (*cp == '\t') {
+ saved = cp + 1;
+ cp = spaces + 8 - (8 - ((curcol - INDENT - 1) % 8));
+ }
+ if (curcol == 0) {
+ for (i = INDENT; --i >= 0; )
+ putchar(' ');
+ curcol = INDENT;
+ }
+ putchar(*cp);
+ if (++curcol == (gColumns - 1)) {
+ putchar('\n');
+ curcol = 0;
+ } else if (*cp == '\n')
+ curcol = 0;
+ }
+ free(gBuf);
+} /* DumpFormattedOutput */
+
+
+
+/* Difftime(), only for timeval structures. */
+static void TimeValSubtract(struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
+{
+ tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+ tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
+ if (tdiff->tv_usec < 0) {
+ tdiff->tv_sec--;
+ tdiff->tv_usec += 1000000;
+ }
+} /* TimeValSubtract */
+
+
+
+static void Wait(void)
+{
+ int pid2, status;
+
+ do {
+ status = 0;
+ pid2 = (int) waitpid(gCCPID, &status, 0);
+ } while (((pid2 >= 0) && (! WIFEXITED(status))) || ((pid2 < 0) && (errno == EINTR)));
+ if (WIFEXITED(status))
+ gExitStatus = WEXITSTATUS(status);
+} /* Wait */
+
+
+
+static int SlurpProgress(int fd)
+{
+ char s1[71];
+ char *newbuf;
+ int nready;
+ size_t ntoread;
+ ssize_t nread;
+ struct timeval now, tnext, tleft;
+ fd_set ss;
+ fd_set ss2;
+ const char *trail = "/-\\|", *trailcp;
+
+ trailcp = trail;
+ snprintf(s1, sizeof(s1), "%s%s%s... ", gAction, gTarget[0] ? " " : "", gTarget);
+ printf("\r%-70s%-9s", s1, "");
+ fflush(stdout);
+
+ gettimeofday(&now, NULL);
+ tnext = now;
+ tnext.tv_sec++;
+ tleft.tv_sec = 1;
+ tleft.tv_usec = 0;
+ FD_ZERO(&ss2);
+ FD_SET(fd, &ss2);
+ for(;;) {
+ if (gNBufUsed == (gNBufAllocated - 1)) {
+ if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) {
+ perror("ccdv: realloc");
+ return (-1);
+ }
+ gNBufAllocated += TEXT_BLOCK_SIZE;
+ gBuf = newbuf;
+ }
+ for (;;) {
+ ss = ss2;
+ nready = select(fd + 1, &ss, NULL, NULL, &tleft);
+ if (nready == 1)
+ break;
+ if (nready < 0) {
+ if (errno != EINTR) {
+ perror("ccdv: select");
+ return (-1);
+ }
+ continue;
+ }
+ gettimeofday(&now, NULL);
+ if ((now.tv_sec > tnext.tv_sec) || ((now.tv_sec == tnext.tv_sec) && (now.tv_usec >= tnext.tv_usec))) {
+ tnext = now;
+ tnext.tv_sec++;
+ tleft.tv_sec = 1;
+ tleft.tv_usec = 0;
+ printf("\r%-71s%c%-7s", s1, *trailcp, "");
+ fflush(stdout);
+ if (*++trailcp == '\0')
+ trailcp = trail;
+ } else {
+ TimeValSubtract(&tleft, &tnext, &now);
+ }
+ }
+ ntoread = (gNBufAllocated - gNBufUsed - 1);
+ nread = read(fd, gBuf + gNBufUsed, ntoread);
+ if (nread < 0) {
+ if (errno == EINTR)
+ continue;
+ perror("ccdv: read");
+ return (-1);
+ } else if (nread == 0) {
+ break;
+ }
+ gNBufUsed += nread;
+ gBuf[gNBufUsed] = '\0';
+ }
+ snprintf(s1, sizeof(s1), "%s%s%s: ", gAction, gTarget[0] ? " " : "", gTarget);
+ Wait();
+ if (gExitStatus == 0) {
+ printf("\r%-70s", s1);
+ printf("[%s%s%s]", ((gNBufUsed - strlen(gArgsStr)) < 4) ? SETCOLOR_SUCCESS : SETCOLOR_WARNING, "OK", SETCOLOR_NORMAL);
+ printf("%-5s\n", " ");
+ } else {
+ printf("\r%-70s", s1);
+ printf("[%s%s%s]", SETCOLOR_FAILURE, "ERROR", SETCOLOR_NORMAL);
+ printf("%-2s\n", " ");
+ gDumpCmdArgs = 1; /* print cmd when there are errors */
+ }
+ fflush(stdout);
+ return (0);
+} /* SlurpProgress */
+
+
+
+static int SlurpAll(int fd)
+{
+ char *newbuf;
+ size_t ntoread;
+ ssize_t nread;
+
+ printf("%s%s%s.\n", gAction, gTarget[0] ? " " : "", gTarget);
+ fflush(stdout);
+
+ for(;;) {
+ if (gNBufUsed == (gNBufAllocated - 1)) {
+ if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) {
+ perror("ccdv: realloc");
+ return (-1);
+ }
+ gNBufAllocated += TEXT_BLOCK_SIZE;
+ gBuf = newbuf;
+ }
+ ntoread = (gNBufAllocated - gNBufUsed - 1);
+ nread = read(fd, gBuf + gNBufUsed, ntoread);
+ if (nread < 0) {
+ if (errno == EINTR)
+ continue;
+ perror("ccdv: read");
+ return (-1);
+ } else if (nread == 0) {
+ break;
+ }
+ gNBufUsed += nread;
+ gBuf[gNBufUsed] = '\0';
+ }
+ Wait();
+ gDumpCmdArgs = (gExitStatus != 0); /* print cmd when there are errors */
+ return (0);
+} /* SlurpAll */
+
+
+
+static const char *Basename(const char *path)
+{
+ const char *cp;
+ cp = strrchr(path, '/');
+ if (cp == NULL)
+ return (path);
+ return (cp + 1);
+} /* Basename */
+
+
+
+static const char * Extension(const char *path)
+{
+ const char *cp = path;
+ cp = strrchr(path, '.');
+ if (cp == NULL)
+ return ("");
+ // printf("Extension='%s'\n", cp);
+ return (cp);
+} /* Extension */
+
+
+
+static void Usage(void)
+{
+ fprintf(stderr, "Usage: ccdv /path/to/cc CFLAGS...\n\n");
+ fprintf(stderr, "I wrote this to reduce the deluge Make output to make finding actual problems\n");
+ fprintf(stderr, "easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\n");
+ fprintf(stderr, "\t.c.o:\n");
+ fprintf(stderr, "\t\t$(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n");
+ fprintf(stderr, "\nRewrite your rule so it looks like:\n\n");
+ fprintf(stderr, "\t.c.o:\n");
+ fprintf(stderr, "\t\t@ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\n");
+ fprintf(stderr, "ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n");
+ fprintf(stderr, " -- Mike Gleason, NcFTP Software <http://www.ncftp.com>\n");
+ exit(96);
+} /* Usage */
+
+
+
+int main(int argc, char **argv)
+{
+ int pipe1[2];
+ int devnull;
+ char emerg[256];
+ int fd;
+ int nread;
+ int i;
+ int cc = 0, pch = 0;
+ const char *quote;
+
+ if (argc < 2)
+ Usage();
+
+ snprintf(gAction, sizeof(gAction), "Running %s", Basename(argv[1]));
+ memset(gArgsStr, 0, sizeof(gArgsStr));
+ for (i = 1; i < argc; i++) {
+ // printf("argv[%d]='%s'\n", i, argv[i]);
+ quote = (strchr(argv[i], ' ') != NULL) ? "\"" : "";
+ snprintf(gArgsStr + strlen(gArgsStr), sizeof(gArgsStr) - strlen(gArgsStr), "%s%s%s%s%s", (i == 1) ? "" : " ", quote, argv[i], quote, (i == (argc - 1)) ? "\n" : "");
+ if ((strcmp(argv[i], "-o") == 0) && ((i + 1) < argc)) {
+ if (strcasecmp(Extension(argv[i + 1]), ".o") != 0) {
+ strcpy(gAction, "Linking");
+ snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i + 1]));
+ }
+ } else if (strchr("-+", (int) argv[i][0]) != NULL) {
+ continue;
+ } else if (strncasecmp(Extension(argv[i]), ".c", 2) == 0) {
+ cc++;
+ snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i]));
+ // printf("gTarget='%s'\n", gTarget);
+ } else if ((strncasecmp(Extension(argv[i]), ".h", 2) == 0) && (cc == 0)) {
+ pch++;
+ snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i]));
+ } else if ((i == 1) && (strcmp(Basename(argv[i]), "ar") == 0)) {
+ snprintf(gAr, sizeof(gAr), "%s", Basename(argv[i]));
+ } else if ((gArLibraryTarget[0] == '\0') && (strcasecmp(Extension(argv[i]), ".a") == 0)) {
+ snprintf(gArLibraryTarget, sizeof(gArLibraryTarget), "%s", Basename(argv[i]));
+ }
+ }
+ if ((gAr[0] != '\0') && (gArLibraryTarget[0] != '\0')) {
+ strcpy(gAction, "Creating library");
+ snprintf(gTarget, sizeof(gTarget), "%s", gArLibraryTarget);
+ } else if (pch > 0) {
+ strcpy(gAction, "Precompiling");
+ } else if (cc > 0) {
+ strcpy(gAction, "Compiling");
+ }
+
+ if (pipe(pipe1) < 0) {
+ perror("ccdv: pipe");
+ exit(97);
+ }
+
+ (void) close(0);
+ devnull = open("/dev/null", O_RDWR, 00666);
+ if ((devnull != 0) && (dup2(devnull, 0) == 0))
+ close(devnull);
+
+ gCCPID = (int) fork();
+ if (gCCPID < 0) {
+ (void) close(pipe1[0]);
+ (void) close(pipe1[1]);
+ perror("ccdv: fork");
+ exit(98);
+ } else if (gCCPID == 0) {
+ /* Child */
+ (void) close(pipe1[0]); /* close read end */
+ if (pipe1[1] != 1) { /* use write end on stdout */
+ (void) dup2(pipe1[1], 1);
+ (void) close(pipe1[1]);
+ }
+ (void) dup2(1, 2); /* use write end on stderr */
+ execvp(argv[1], argv + 1);
+ perror(argv[1]);
+ exit(99);
+ }
+
+ /* parent */
+ (void) close(pipe1[1]); /* close write end */
+ fd = pipe1[0]; /* use read end */
+
+ gColumns = (getenv("COLUMNS") != NULL) ? atoi(getenv("COLUMNS")) : 80;
+ gANSIEscapes = (getenv("TERM") != NULL) && (strstr(TERMS, getenv("TERM")) != NULL);
+ gBuf = (char *) malloc(TEXT_BLOCK_SIZE);
+ if (gBuf == NULL)
+ goto panic;
+ gNBufUsed = 0;
+ gNBufAllocated = TEXT_BLOCK_SIZE;
+ if (strlen(gArgsStr) < (gNBufAllocated - 1)) {
+ strcpy(gBuf, gArgsStr);
+ gNBufUsed = strlen(gArgsStr);
+ }
+
+ if (isatty(1)) {
+ if (SlurpProgress(fd) < 0)
+ goto panic;
+ } else {
+ if (SlurpAll(fd) < 0)
+ goto panic;
+ }
+ DumpFormattedOutput();
+ exit(gExitStatus);
+
+panic:
+ gDumpCmdArgs = 1; /* print cmd when there are errors */
+ DumpFormattedOutput();
+ while ((nread = read(fd, emerg, (size_t) sizeof(emerg))) > 0)
+ (void) write(2, emerg, (size_t) nread);
+ Wait();
+ exit(gExitStatus);
+} /* main */
diff --git a/config/config.opts b/config/config.opts
new file mode 100644
index 0000000..9ceac75
--- /dev/null
+++ b/config/config.opts
@@ -0,0 +1,63 @@
+#
+# Local PCMCIA Configuration File
+#
+#----------------------------------------------------------------------
+#
+# System resources available for PCMCIA cards
+#
+# NOTE: these settings have no effect on resources assigned to a
+# CardBus bridge device itself; this file only affects resources
+# assigned to cards. Also, interrupt settings here will only affect
+# ISA bus interrupts assigned to 16-bit cards. PCI interrupts
+# generally can't be reconfigured.
+#
+# With the kernel PCMCIA subsystem, these settings also have no effect
+# at all on resources used for 32-bit CardBus cards. Those are set by
+# the PCI hotplug subsystem.
+#
+
+include port 0x100-0x4ff, port 0x800-0x8ff, port 0xc00-0xcff
+include memory 0xc0000-0xfffff
+include memory 0xa0000000-0xa0ffffff, memory 0x60000000-0x60ffffff
+
+# High port numbers do not always work...
+# include port 0x1000-0x17ff
+
+# Extra port range for IBM Token Ring
+include port 0xa00-0xaff
+
+# Resources we should not use, even if they appear to be available
+
+# First built-in serial port
+exclude irq 4
+# Second built-in serial port
+#exclude irq 3
+# First built-in parallel port
+exclude irq 7
+
+#----------------------------------------------------------------------
+
+# Examples of options for loadable modules
+
+# To fix sluggish network with IBM ethernet adapter...
+#module "pcnet_cs" opts "mem_speed=600"
+
+# Options for IBM Token Ring adapters
+#module "ibmtr_cs" opts "mmiobase=0xd0000 srambase=0xd4000"
+
+# Options for Raylink/WebGear driver: uncomment only one line...
+# Generic ad-hoc network
+module "ray_cs" opts "essid=ADHOC_ESSID hop_dwell=128 beacon_period=256 translate=1"
+# Infrastructure network for older cards
+#module "ray_cs" opts "net_type=1 essid=ESSID1"
+# Infrastructure network for WebGear
+#module "ray_cs" opts "net_type=1 essid=ESSID1 translate=1 hop_dwell=128 beacon_period=256"
+
+# Options for WaveLAN/IEEE driver (AccessPoint mode)...
+#module "wvlan_cs" opts "station_name=MY_PC"
+# Options for WaveLAN/IEEE driver (ad-hoc mode)...
+#module "wvlan_cs" opts "port_type=3 channel=1 station_name=MY_PC"
+
+# Options for Xircom Netwave driver...
+#module "netwave_cs" opts "domain=0x100 scramble_key=0x0"
+
diff --git a/hotplug/pcmcia.agent b/hotplug/pcmcia.agent
new file mode 100755
index 0000000..7ef9454
--- /dev/null
+++ b/hotplug/pcmcia.agent
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# PCMCIA-specific hotplug policy agent
+#
+# $Id$
+#
+
+#DEBUG=yes; export DEBUG
+SYSFS=/sys
+
+cd /etc/hotplug
+. ./hotplug.functions
+
+if [ "$ACTION" = "" ]; then
+ mesg Bad PCMCIA agent invocation, no action
+ exit 1
+fi
+
+debug_mesg $SOCKET_NO $DEVICE_NO $MODNAME $DEVPATH
+
+case $ACTION in
+
+add)
+ modprobe $MODNAME
+
+ # check whether the CIS is completely broken
+ if [ ! -h $SYSFS$DEVPATH/driver ]; then
+ CISFILE=$(pcmcia-check-broken-cis $SOCKET_NO)
+ debug_mesg $CISFILE;
+ if [ ! -z $CISFILE ]; then
+ if [ -f /etc/pcmcia/cis/$CISFILE ]; then
+ cat /etc/pcmcia/cis/$CISFILE > /sys/class/pcmcia_socket/pcmcia_socket$(SOCKET_NO)/cis
+ elif [ -f /lib/firmware/cis/$CISFILE ]; then
+ cat /lib/firmware/cis/$CISFILE > /sys/class/pcmcia_socket/pcmcia_socket$(SOCKET_NO)/cis
+ fi;
+ fi;
+ fi;
+
+ # allow a match solely based on the "function ID" field
+ if [ ! -h $SYSFS$DEVPATH/driver ]; then
+ if [ -w $SYSFS$DEVPATH/allow_func_id_match ]; then
+ debug_mesg allowing func_id based match for PCMCIA device $SOCKET_NO.$DEVICE_NO
+ echo -n "42" > $SYSFS$DEVPATH/allow_func_id_match;
+ fi;
+ fi;
+ ;;
+remove)
+ ;;
+*)
+ debug_mesg "PCMCIA '$ACTION' event not supported"
+ ;;
+
+esac
diff --git a/hotplug/pcmcia.rc b/hotplug/pcmcia.rc
new file mode 100755
index 0000000..4d874dc
--- /dev/null
+++ b/hotplug/pcmcia.rc
@@ -0,0 +1,53 @@
+#!/bin/sh
+# vim: syntax=sh
+#
+# pcmcia.rc recover lost boot-time pcmcia_socket hotplug events
+#
+# $Id: $
+#
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+#DEBUG=yes; export DEBUG
+
+cd /etc/hotplug
+. ./hotplug.functions
+
+pcmcia_boot_events ()
+{
+ if [ -d /sys/bus/pcmcia/devices/ ]; then
+ # 2.6 kernels
+ cd /sys/bus/pcmcia/devices/
+ for PCMCIA_DEVICE in *; do
+ if [ $PCMCIA_DEVICE == \* ]; then
+ continue;
+ fi;
+ MODNAME=$(pcmcia-modalias $PCMCIA_DEVICE)
+ debug_mesg $MODNAME $PCMICA_DEVICE
+ if [ -z $MODNAME ]; then
+ continue;
+ fi;
+ ACTION=add
+ export MODNAME ACTION
+ /sbin/hotplug pcmcia
+ done;
+ fi;
+
+ return 0
+}
+
+# See how we were called.
+case "$1" in
+ start)
+ pcmcia_boot_events
+ ;;
+ stop)
+ # echo $"pcmcia stop -- ignored"
+ ;;
+ restart)
+ # always invoke by absolute path, else PATH=$PATH:
+ $0 stop && $0 start
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart}"
+ exit 1
+esac
diff --git a/hotplug/pcmcia_socket.agent b/hotplug/pcmcia_socket.agent
new file mode 100755
index 0000000..e64157f
--- /dev/null
+++ b/hotplug/pcmcia_socket.agent
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# PCMCIA-socket-specific hotplug policy agent
+#
+# $Id$
+#
+
+#DEBUG=yes; export DEBUG
+
+cd /etc/hotplug
+. ./hotplug.functions
+
+if [ "$ACTION" = "" ]; then
+ mesg Bad PCMCIA socket agent invocation, no action
+ exit 1
+fi
+
+debug_mesg socket number: $SOCKET_NO
+
+case $ACTION in
+
+add)
+ sleep 1;
+ pcmcia-socket-startup $SOCKET_NO
+ DONE_FILE=/sys/class/pcmcia_socket/pcmcia_socket$SOCKET_NO/available_resources_setup_done
+ if [ -f $DONE_FILE ]; then
+ if [ -w $DONE_FILE ]; then
+ echo -n "42" > $DONE_FILE
+ fi;
+ fi;
+ ;;
+remove)
+ ;;
+*)
+ debug_mesg "PCMCIA socket '$ACTION' event not supported"
+ ;;
+
+esac
diff --git a/hotplug/pcmcia_socket.rc b/hotplug/pcmcia_socket.rc
new file mode 100755
index 0000000..dedb18d
--- /dev/null
+++ b/hotplug/pcmcia_socket.rc
@@ -0,0 +1,49 @@
+#!/bin/sh
+# vim: syntax=sh
+#
+# pcmcia.rc recover lost boot-time pcmcia_socket hotplug events
+#
+# $Id: $
+#
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+#DEBUG=yes; export DEBUG
+
+cd /etc/hotplug
+. ./hotplug.functions
+
+pcmcia_boot_events ()
+{
+ if [ -d /sys/class/pcmcia_socket/ ]; then
+ # 2.6 kernels
+ cd /sys/class/pcmcia_socket/
+ for PCMCIA_SOCKET in *; do
+ if [ $PCMCIA_SOCKET == \* ]; then
+ continue;
+ fi;
+ SOCKET_NO=$(echo $PCMCIA_SOCKET | cut -b14-)
+ ACTION=add
+ export SOCKET_NO ACTION
+ /sbin/hotplug pcmcia_socket
+ done;
+ fi;
+
+ return 0
+}
+
+# See how we were called.
+case "$1" in
+ start)
+ pcmcia_boot_events
+ ;;
+ stop)
+ # echo $"pcmcia stop -- ignored"
+ ;;
+ restart)
+ # always invoke by absolute path, else PATH=$PATH:
+ $0 stop && $0 start
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart}"
+ exit 1
+esac
diff --git a/src/cistpl.h b/src/cistpl.h
new file mode 100644
index 0000000..e4b07a3
--- /dev/null
+++ b/src/cistpl.h
@@ -0,0 +1,598 @@
+/*
+ * cistpl.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
+
+#ifndef _LINUX_CISTPL_H
+#define _LINUX_CISTPL_H
+
+#define CISTPL_NULL 0x00
+#define CISTPL_DEVICE 0x01
+#define CISTPL_LONGLINK_CB 0x02
+#define CISTPL_INDIRECT 0x03
+#define CISTPL_CONFIG_CB 0x04
+#define CISTPL_CFTABLE_ENTRY_CB 0x05
+#define CISTPL_LONGLINK_MFC 0x06
+#define CISTPL_BAR 0x07
+#define CISTPL_PWR_MGMNT 0x08
+#define CISTPL_EXTDEVICE 0x09
+#define CISTPL_CHECKSUM 0x10
+#define CISTPL_LONGLINK_A 0x11
+#define CISTPL_LONGLINK_C 0x12
+#define CISTPL_LINKTARGET 0x13
+#define CISTPL_NO_LINK 0x14
+#define CISTPL_VERS_1 0x15
+#define CISTPL_ALTSTR 0x16
+#define CISTPL_DEVICE_A 0x17
+#define CISTPL_JEDEC_C 0x18
+#define CISTPL_JEDEC_A 0x19
+#define CISTPL_CONFIG 0x1a
+#define CISTPL_CFTABLE_ENTRY 0x1b
+#define CISTPL_DEVICE_OC 0x1c
+#define CISTPL_DEVICE_OA 0x1d
+#define CISTPL_DEVICE_GEO 0x1e
+#define CISTPL_DEVICE_GEO_A 0x1f
+#define CISTPL_MANFID 0x20
+#define CISTPL_FUNCID 0x21
+#define CISTPL_FUNCE 0x22
+#define CISTPL_SWIL 0x23
+#define CISTPL_END 0xff
+/* Layer 2 tuples */
+#define CISTPL_VERS_2 0x40
+#define CISTPL_FORMAT 0x41
+#define CISTPL_GEOMETRY 0x42
+#define CISTPL_BYTEORDER 0x43
+#define CISTPL_DATE 0x44
+#define CISTPL_BATTERY 0x45
+#define CISTPL_FORMAT_A 0x47
+/* Layer 3 tuples */
+#define CISTPL_ORG 0x46
+#define CISTPL_SPCL 0x90
+
+typedef struct cistpl_longlink_t {
+ unsigned int addr;
+} cistpl_longlink_t;
+
+typedef struct cistpl_checksum_t {
+ unsigned short addr;
+ unsigned short len;
+ unsigned char sum;
+} cistpl_checksum_t;
+
+#define CISTPL_MAX_FUNCTIONS 8
+#define CISTPL_MFC_ATTR 0x00
+#define CISTPL_MFC_COMMON 0x01
+
+typedef struct cistpl_longlink_mfc_t {
+ unsigned char nfn;
+ struct {
+ unsigned char space;
+ unsigned int addr;
+ } fn[CISTPL_MAX_FUNCTIONS];
+} cistpl_longlink_mfc_t;
+
+#define CISTPL_MAX_ALTSTR_STRINGS 4
+
+typedef struct cistpl_altstr_t {
+ unsigned char ns;
+ unsigned char ofs[CISTPL_MAX_ALTSTR_STRINGS];
+ char str[254];
+} cistpl_altstr_t;
+
+#define CISTPL_DTYPE_NULL 0x00
+#define CISTPL_DTYPE_ROM 0x01
+#define CISTPL_DTYPE_OTPROM 0x02
+#define CISTPL_DTYPE_EPROM 0x03
+#define CISTPL_DTYPE_EEPROM 0x04
+#define CISTPL_DTYPE_FLASH 0x05
+#define CISTPL_DTYPE_SRAM 0x06
+#define CISTPL_DTYPE_DRAM 0x07
+#define CISTPL_DTYPE_FUNCSPEC 0x0d
+#define CISTPL_DTYPE_EXTEND 0x0e
+
+#define CISTPL_MAX_DEVICES 4
+
+typedef struct cistpl_device_t {
+ unsigned char ndev;
+ struct {
+ unsigned char type;
+ unsigned char wp;
+ unsigned int speed;
+ unsigned int size;
+ } dev[CISTPL_MAX_DEVICES];
+} cistpl_device_t;
+
+#define CISTPL_DEVICE_MWAIT 0x01
+#define CISTPL_DEVICE_3VCC 0x02
+
+typedef struct cistpl_device_o_t {
+ unsigned char flags;
+ cistpl_device_t device;
+} cistpl_device_o_t;
+
+#define CISTPL_VERS_1_MAX_PROD_STRINGS 4
+
+typedef struct cistpl_vers_1_t {
+ unsigned char major;
+ unsigned char minor;
+ unsigned char ns;
+ unsigned char ofs[CISTPL_VERS_1_MAX_PROD_STRINGS];
+ char str[254];
+} cistpl_vers_1_t;
+
+typedef struct cistpl_jedec_t {
+ unsigned char nid;
+ struct {
+ unsigned char mfr;
+ unsigned char info;
+ } id[CISTPL_MAX_DEVICES];
+} cistpl_jedec_t;
+
+typedef struct cistpl_manfid_t {
+ unsigned short manf;
+ unsigned short card;
+} cistpl_manfid_t;
+
+#define CISTPL_FUNCID_MULTI 0x00
+#define CISTPL_FUNCID_MEMORY 0x01
+#define CISTPL_FUNCID_SERIAL 0x02
+#define CISTPL_FUNCID_PARALLEL 0x03
+#define CISTPL_FUNCID_FIXED 0x04
+#define CISTPL_FUNCID_VIDEO 0x05
+#define CISTPL_FUNCID_NETWORK 0x06
+#define CISTPL_FUNCID_AIMS 0x07
+#define CISTPL_FUNCID_SCSI 0x08
+
+#define CISTPL_SYSINIT_POST 0x01
+#define CISTPL_SYSINIT_ROM 0x02
+
+typedef struct cistpl_funcid_t {
+ unsigned char func;
+ unsigned char sysinit;
+} cistpl_funcid_t;
+
+typedef struct cistpl_funce_t {
+ unsigned char type;
+ unsigned char data[0];
+} cistpl_funce_t;
+
+/*======================================================================
+
+ Modem Function Extension Tuples
+
+======================================================================*/
+
+#define CISTPL_FUNCE_SERIAL_IF 0x00
+#define CISTPL_FUNCE_SERIAL_CAP 0x01
+#define CISTPL_FUNCE_SERIAL_SERV_DATA 0x02
+#define CISTPL_FUNCE_SERIAL_SERV_FAX 0x03
+#define CISTPL_FUNCE_SERIAL_SERV_VOICE 0x04
+#define CISTPL_FUNCE_SERIAL_CAP_DATA 0x05
+#define CISTPL_FUNCE_SERIAL_CAP_FAX 0x06
+#define CISTPL_FUNCE_SERIAL_CAP_VOICE 0x07
+#define CISTPL_FUNCE_SERIAL_IF_DATA 0x08
+#define CISTPL_FUNCE_SERIAL_IF_FAX 0x09
+#define CISTPL_FUNCE_SERIAL_IF_VOICE 0x0a
+
+/* UART identification */
+#define CISTPL_SERIAL_UART_8250 0x00
+#define CISTPL_SERIAL_UART_16450 0x01
+#define CISTPL_SERIAL_UART_16550 0x02
+#define CISTPL_SERIAL_UART_8251 0x03
+#define CISTPL_SERIAL_UART_8530 0x04
+#define CISTPL_SERIAL_UART_85230 0x05
+
+/* UART capabilities */
+#define CISTPL_SERIAL_UART_SPACE 0x01
+#define CISTPL_SERIAL_UART_MARK 0x02
+#define CISTPL_SERIAL_UART_ODD 0x04
+#define CISTPL_SERIAL_UART_EVEN 0x08
+#define CISTPL_SERIAL_UART_5BIT 0x01
+#define CISTPL_SERIAL_UART_6BIT 0x02
+#define CISTPL_SERIAL_UART_7BIT 0x04
+#define CISTPL_SERIAL_UART_8BIT 0x08
+#define CISTPL_SERIAL_UART_1STOP 0x10
+#define CISTPL_SERIAL_UART_MSTOP 0x20
+#define CISTPL_SERIAL_UART_2STOP 0x40
+
+typedef struct cistpl_serial_t {
+ unsigned char uart_type;
+ unsigned char uart_cap_0;
+ unsigned char uart_cap_1;
+} cistpl_serial_t;
+
+typedef struct cistpl_modem_cap_t {
+ unsigned char flow;
+ unsigned char cmd_buf;
+ unsigned char rcv_buf_0, rcv_buf_1, rcv_buf_2;
+ unsigned char xmit_buf_0, xmit_buf_1, xmit_buf_2;
+} cistpl_modem_cap_t;
+
+#define CISTPL_SERIAL_MOD_103 0x01
+#define CISTPL_SERIAL_MOD_V21 0x02
+#define CISTPL_SERIAL_MOD_V23 0x04
+#define CISTPL_SERIAL_MOD_V22 0x08
+#define CISTPL_SERIAL_MOD_212A 0x10
+#define CISTPL_SERIAL_MOD_V22BIS 0x20
+#define CISTPL_SERIAL_MOD_V26 0x40
+#define CISTPL_SERIAL_MOD_V26BIS 0x80
+#define CISTPL_SERIAL_MOD_V27BIS 0x01
+#define CISTPL_SERIAL_MOD_V29 0x02
+#define CISTPL_SERIAL_MOD_V32 0x04
+#define CISTPL_SERIAL_MOD_V32BIS 0x08
+#define CISTPL_SERIAL_MOD_V34 0x10
+
+#define CISTPL_SERIAL_ERR_MNP2_4 0x01
+#define CISTPL_SERIAL_ERR_V42_LAPM 0x02
+
+#define CISTPL_SERIAL_CMPR_V42BIS 0x01
+#define CISTPL_SERIAL_CMPR_MNP5 0x02
+
+#define CISTPL_SERIAL_CMD_AT1 0x01
+#define CISTPL_SERIAL_CMD_AT2 0x02
+#define CISTPL_SERIAL_CMD_AT3 0x04
+#define CISTPL_SERIAL_CMD_MNP_AT 0x08
+#define CISTPL_SERIAL_CMD_V25BIS 0x10
+#define CISTPL_SERIAL_CMD_V25A 0x20
+#define CISTPL_SERIAL_CMD_DMCL 0x40
+
+typedef struct cistpl_data_serv_t {
+ unsigned char max_data_0;
+ unsigned char max_data_1;
+ unsigned char modulation_0;
+ unsigned char modulation_1;
+ unsigned char error_control;
+ unsigned char compression;
+ unsigned char cmd_protocol;
+ unsigned char escape;
+ unsigned char encrypt;
+ unsigned char misc_features;
+ unsigned char ccitt_code[0];
+} cistpl_data_serv_t;
+
+typedef struct cistpl_fax_serv_t {
+ unsigned char max_data_0;
+ unsigned char max_data_1;
+ unsigned char modulation;
+ unsigned char encrypt;
+ unsigned char features_0;
+ unsigned char features_1;
+ unsigned char ccitt_code[0];
+} cistpl_fax_serv_t;
+
+typedef struct cistpl_voice_serv_t {
+ unsigned char max_data_0;
+ unsigned char max_data_1;
+} cistpl_voice_serv_t;
+
+/*======================================================================
+
+ LAN Function Extension Tuples
+
+======================================================================*/
+
+#define CISTPL_FUNCE_LAN_TECH 0x01
+#define CISTPL_FUNCE_LAN_SPEED 0x02
+#define CISTPL_FUNCE_LAN_MEDIA 0x03
+#define CISTPL_FUNCE_LAN_NODE_ID 0x04
+#define CISTPL_FUNCE_LAN_CONNECTOR 0x05
+
+/* LAN technologies */
+#define CISTPL_LAN_TECH_ARCNET 0x01
+#define CISTPL_LAN_TECH_ETHERNET 0x02
+#define CISTPL_LAN_TECH_TOKENRING 0x03
+#define CISTPL_LAN_TECH_LOCALTALK 0x04
+#define CISTPL_LAN_TECH_FDDI 0x05
+#define CISTPL_LAN_TECH_ATM 0x06
+#define CISTPL_LAN_TECH_WIRELESS 0x07
+
+typedef struct cistpl_lan_tech_t {
+ unsigned char tech;
+} cistpl_lan_tech_t;
+
+typedef struct cistpl_lan_speed_t {
+ unsigned int speed;
+} cistpl_lan_speed_t;
+
+/* LAN media definitions */
+#define CISTPL_LAN_MEDIA_UTP 0x01
+#define CISTPL_LAN_MEDIA_STP 0x02
+#define CISTPL_LAN_MEDIA_THIN_COAX 0x03
+#define CISTPL_LAN_MEDIA_THICK_COAX 0x04
+#define CISTPL_LAN_MEDIA_FIBER 0x05
+#define CISTPL_LAN_MEDIA_900MHZ 0x06
+#define CISTPL_LAN_MEDIA_2GHZ 0x07
+#define CISTPL_LAN_MEDIA_5GHZ 0x08
+#define CISTPL_LAN_MEDIA_DIFF_IR 0x09
+#define CISTPL_LAN_MEDIA_PTP_IR 0x0a
+
+typedef struct cistpl_lan_media_t {
+ unsigned char media;
+} cistpl_lan_media_t;
+
+typedef struct cistpl_lan_node_id_t {
+ unsigned char nb;
+ unsigned char id[16];
+} cistpl_lan_node_id_t;
+
+typedef struct cistpl_lan_connector_t {
+ unsigned char code;
+} cistpl_lan_connector_t;
+
+/*======================================================================
+
+ IDE Function Extension Tuples
+
+======================================================================*/
+
+#define CISTPL_IDE_INTERFACE 0x01
+
+typedef struct cistpl_ide_interface_t {
+ unsigned char interface;
+} cistpl_ide_interface_t;
+
+/* First feature byte */
+#define CISTPL_IDE_SILICON 0x04
+#define CISTPL_IDE_UNIQUE 0x08
+#define CISTPL_IDE_DUAL 0x10
+
+/* Second feature byte */
+#define CISTPL_IDE_HAS_SLEEP 0x01
+#define CISTPL_IDE_HAS_STANDBY 0x02
+#define CISTPL_IDE_HAS_IDLE 0x04
+#define CISTPL_IDE_LOW_POWER 0x08
+#define CISTPL_IDE_REG_INHIBIT 0x10
+#define CISTPL_IDE_HAS_INDEX 0x20
+#define CISTPL_IDE_IOIS16 0x40
+
+typedef struct cistpl_ide_feature_t {
+ unsigned char feature1;
+ unsigned char feature2;
+} cistpl_ide_feature_t;
+
+#define CISTPL_FUNCE_IDE_IFACE 0x01
+#define CISTPL_FUNCE_IDE_MASTER 0x02
+#define CISTPL_FUNCE_IDE_SLAVE 0x03
+
+/*======================================================================
+
+ Configuration Table Entries
+
+======================================================================*/
+
+#define CISTPL_BAR_SPACE 0x07
+#define CISTPL_BAR_SPACE_IO 0x10
+#define CISTPL_BAR_PREFETCH 0x20
+#define CISTPL_BAR_CACHEABLE 0x40
+#define CISTPL_BAR_1MEG_MAP 0x80
+
+typedef struct cistpl_bar_t {
+ unsigned char attr;
+ unsigned int size;
+} cistpl_bar_t;
+
+typedef struct cistpl_config_t {
+ unsigned char last_idx;
+ unsigned int base;
+ unsigned int rmask[4];
+ unsigned char subtuples;
+} cistpl_config_t;
+
+/* These are bits in the 'present' field, and indices in 'param' */
+#define CISTPL_POWER_VNOM 0
+#define CISTPL_POWER_VMIN 1
+#define CISTPL_POWER_VMAX 2
+#define CISTPL_POWER_ISTATIC 3
+#define CISTPL_POWER_IAVG 4
+#define CISTPL_POWER_IPEAK 5
+#define CISTPL_POWER_IDOWN 6
+
+#define CISTPL_POWER_HIGHZ_OK 0x01
+#define CISTPL_POWER_HIGHZ_REQ 0x02
+
+typedef struct cistpl_power_t {
+ unsigned char present;
+ unsigned char flags;
+ unsigned int param[7];
+} cistpl_power_t;
+
+typedef struct cistpl_timing_t {
+ unsigned int wait, waitscale;
+ unsigned int ready, rdyscale;
+ unsigned int reserved, rsvscale;
+} cistpl_timing_t;
+
+#define CISTPL_IO_LINES_MASK 0x1f
+#define CISTPL_IO_8BIT 0x20
+#define CISTPL_IO_16BIT 0x40
+#define CISTPL_IO_RANGE 0x80
+
+#define CISTPL_IO_MAX_WIN 16
+
+typedef struct cistpl_io_t {
+ unsigned char flags;
+ unsigned char nwin;
+ struct {
+ unsigned int base;
+ unsigned int len;
+ } win[CISTPL_IO_MAX_WIN];
+} cistpl_io_t;
+
+typedef struct cistpl_irq_t {
+ unsigned int IRQInfo1;
+ unsigned int IRQInfo2;
+} cistpl_irq_t;
+
+#define CISTPL_MEM_MAX_WIN 8
+
+typedef struct cistpl_mem_t {
+ unsigned char flags;
+ unsigned char nwin;
+ struct {
+ unsigned int len;
+ unsigned int card_addr;
+ unsigned int host_addr;
+ } win[CISTPL_MEM_MAX_WIN];
+} cistpl_mem_t;
+
+#define CISTPL_CFTABLE_DEFAULT 0x0001
+#define CISTPL_CFTABLE_BVDS 0x0002
+#define CISTPL_CFTABLE_WP 0x0004
+#define CISTPL_CFTABLE_RDYBSY 0x0008
+#define CISTPL_CFTABLE_MWAIT 0x0010
+#define CISTPL_CFTABLE_AUDIO 0x0800
+#define CISTPL_CFTABLE_READONLY 0x1000
+#define CISTPL_CFTABLE_PWRDOWN 0x2000
+
+typedef struct cistpl_cftable_entry_t {
+ unsigned char index;
+ unsigned short flags;
+ unsigned char interface;
+ cistpl_power_t vcc, vpp1, vpp2;
+ cistpl_timing_t timing;
+ cistpl_io_t io;
+ cistpl_irq_t irq;
+ cistpl_mem_t mem;
+ unsigned char subtuples;
+} cistpl_cftable_entry_t;
+
+#define CISTPL_CFTABLE_MASTER 0x000100
+#define CISTPL_CFTABLE_INVALIDATE 0x000200
+#define CISTPL_CFTABLE_VGA_PALETTE 0x000400
+#define CISTPL_CFTABLE_PARITY 0x000800
+#define CISTPL_CFTABLE_WAIT 0x001000
+#define CISTPL_CFTABLE_SERR 0x002000
+#define CISTPL_CFTABLE_FAST_BACK 0x004000
+#define CISTPL_CFTABLE_BINARY_AUDIO 0x010000
+#define CISTPL_CFTABLE_PWM_AUDIO 0x020000
+
+typedef struct cistpl_cftable_entry_cb_t {
+ unsigned char index;
+ unsigned int flags;
+ cistpl_power_t vcc, vpp1, vpp2;
+ unsigned char io;
+ cistpl_irq_t irq;
+ unsigned char mem;
+ unsigned char subtuples;
+} cistpl_cftable_entry_cb_t;
+
+typedef struct cistpl_device_geo_t {
+ unsigned char ngeo;
+ struct {
+ unsigned char buswidth;
+ unsigned int erase_block;
+ unsigned int read_block;
+ unsigned int write_block;
+ unsigned int partition;
+ unsigned int interleave;
+ } geo[CISTPL_MAX_DEVICES];
+} cistpl_device_geo_t;
+
+typedef struct cistpl_vers_2_t {
+ unsigned char vers;
+ unsigned char comply;
+ unsigned short dindex;
+ unsigned char vspec8, vspec9;
+ unsigned char nhdr;
+ unsigned char vendor, info;
+ char str[244];
+} cistpl_vers_2_t;
+
+typedef struct cistpl_org_t {
+ unsigned char data_org;
+ char desc[30];
+} cistpl_org_t;
+
+#define CISTPL_ORG_FS 0x00
+#define CISTPL_ORG_APPSPEC 0x01
+#define CISTPL_ORG_XIP 0x02
+
+typedef struct cistpl_format_t {
+ unsigned char type;
+ unsigned char edc;
+ unsigned int offset;
+ unsigned int length;
+} cistpl_format_t;
+
+#define CISTPL_FORMAT_DISK 0x00
+#define CISTPL_FORMAT_MEM 0x01
+
+#define CISTPL_EDC_NONE 0x00
+#define CISTPL_EDC_CKSUM 0x01
+#define CISTPL_EDC_CRC 0x02
+#define CISTPL_EDC_PCC 0x03
+
+typedef union cisparse_t {
+ cistpl_device_t device;
+ cistpl_checksum_t checksum;
+ cistpl_longlink_t longlink;
+ cistpl_longlink_mfc_t longlink_mfc;
+ cistpl_vers_1_t version_1;
+ cistpl_altstr_t altstr;
+ cistpl_jedec_t jedec;
+ cistpl_manfid_t manfid;
+ cistpl_funcid_t funcid;
+ cistpl_funce_t funce;
+ cistpl_bar_t bar;
+ cistpl_config_t config;
+ cistpl_cftable_entry_t cftable_entry;
+ cistpl_cftable_entry_cb_t cftable_entry_cb;
+ cistpl_device_geo_t device_geo;
+ cistpl_vers_2_t vers_2;
+ cistpl_org_t org;
+ cistpl_format_t format;
+} cisparse_t;
+
+typedef struct tuple_t {
+ unsigned int Attributes;
+ unsigned char DesiredTuple;
+ unsigned int Flags; /* internal use */
+ unsigned int LinkOffset; /* internal use */
+ unsigned int CISOffset; /* internal use */
+ unsigned char TupleCode;
+ unsigned char TupleLink;
+ unsigned char TupleOffset;
+ unsigned char TupleDataMax;
+ unsigned char TupleDataLen;
+ unsigned char *TupleData;
+} tuple_t;
+
+/* Special unsigned char value */
+#define RETURN_FIRST_TUPLE 0xff
+
+/* Attributes for tuple calls */
+#define TUPLE_RETURN_LINK 0x01
+#define TUPLE_RETURN_COMMON 0x02
+
+/* For ValidateCIS */
+typedef struct cisinfo_t {
+ unsigned int Chains;
+} cisinfo_t;
+
+#define CISTPL_MAX_CIS_SIZE 0x200
+
+/* For ReplaceCIS */
+typedef struct cisdump_t {
+ unsigned int Length;
+ unsigned char Data[CISTPL_MAX_CIS_SIZE];
+} cisdump_t;
+
+typedef struct tuple_flags {
+ unsigned int link_space:4;
+ unsigned int has_link:1;
+ unsigned int mfc_fn:3;
+ unsigned int space:4;
+} tuple_flags;
+
+#define BIND_FN_ALL 0xff
+
+#endif /* LINUX_CISTPL_H */
diff --git a/src/lex_config.l b/src/lex_config.l
new file mode 100644
index 0000000..746edc1
--- /dev/null
+++ b/src/lex_config.l
@@ -0,0 +1,220 @@
+/* Special state for handling include files */
+%x src
+
+%{
+/*
+ * Startup tool for non statically mapped PCMCIA sockets
+ *
+ * (C) 2005 Dominik Brodowski <linux@brodo.de>
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * License: GPL v2
+ */
+
+#undef src
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <syslog.h>
+
+#ifdef HAS_WORDEXP
+#include <wordexp.h>
+#else
+#include <glob.h>
+#endif
+
+#define src 1
+
+#include "yacc_config.h"
+
+/* For assembling nice error messages */
+char *current_file;
+int current_lineno;
+
+static int lex_number(char *s);
+static int lex_string(char *s);
+static void do_source(char *fn);
+static int do_eof(void);
+
+%}
+
+int [0-9]+
+hex 0x[0-9a-fA-F]+
+str \"([^"]|\\.)*\"
+
+%%
+
+source[ \t]+ BEGIN(src); return SOURCE;
+<src>[^\n]+ do_source(yytext); BEGIN(INITIAL);
+<<EOF>> if (do_eof()) yyterminate();
+
+\n current_lineno++;
+[ \t]* /* skip */ ;
+[ ]*[#;].* /* skip */ ;
+
+exclude return EXCLUDE;
+include return INCLUDE;
+irq return IRQ_NO;
+port return PORT;
+memory return MEMORY;
+module /* skip */ ;
+
+{int} return lex_number(yytext);
+
+{hex} return lex_number(yytext);
+
+{str} return lex_string(yytext);
+
+. return yytext[0];
+
+%%
+
+#ifndef yywrap
+int yywrap() { return 1; }
+#endif
+
+/*======================================================================
+
+ Stuff to parse basic data types
+
+======================================================================*/
+
+static int lex_number(char *s)
+{
+ yylval.num = strtoul(s, NULL, 0);
+ return NUMBER;
+}
+
+static int lex_string(char *s)
+{
+ int n = strlen(s);
+ yylval.str = malloc(n-1);
+ strncpy(yylval.str, s+1, n-2);
+ yylval.str[n-2] = '\0';
+ return STRING;
+}
+
+/*======================================================================
+
+ Code to support nesting of configuration files
+
+======================================================================*/
+
+#define MAX_SOURCE_DEPTH 4
+struct source_stack {
+ YY_BUFFER_STATE buffer;
+ char *filename;
+ int lineno, fileno;
+ FILE *file;
+#ifdef HAS_WORDEXP
+ wordexp_t word;
+#else
+ glob_t glob;
+#endif
+} source_stack[MAX_SOURCE_DEPTH];
+static int source_stack_ptr = 0;
+static int parse_env = 0;
+
+static int get_glob(void)
+{
+ struct source_stack *s = &source_stack[source_stack_ptr];
+#ifdef HAS_WORDEXP
+ while (s->fileno < s->word.we_wordc) {
+ char *fn = s->word.we_wordv[s->fileno];
+#else
+ while (s->fileno < s->glob.gl_pathc) {
+ char *fn = s->glob.gl_pathv[s->fileno];
+#endif
+ s->file = fopen(fn, "r");
+ if (s->file == NULL) {
+ if (strpbrk(fn, "?*[") == NULL)
+ syslog(LOG_ERR, "could not open '%s': %m", fn);
+ s->fileno++;
+ } else {
+ current_lineno = 1;
+ current_file = strdup(fn);
+ yy_switch_to_buffer(yy_create_buffer(s->file, YY_BUF_SIZE));
+ source_stack_ptr++;
+ s->fileno++;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static void do_source(char *fn)
+{
+ struct source_stack *s = &source_stack[source_stack_ptr];
+
+ if (source_stack_ptr >= MAX_SOURCE_DEPTH) {
+ syslog(LOG_ERR, "source depth limit exceeded");
+ return;
+ }
+#ifdef HAS_WORDEXP
+ wordexp(fn, &s->word, 0);
+#else
+ glob(fn, GLOB_NOCHECK, NULL, &s->glob);
+#endif
+ s->fileno = 0;
+ s->buffer = YY_CURRENT_BUFFER;
+ s->lineno = current_lineno;
+ s->filename = current_file;
+ get_glob();
+}
+
+static int do_eof(void)
+{
+ struct source_stack *s = &source_stack[--source_stack_ptr];
+ if (source_stack_ptr < 0) {
+ if (parse_env == 0) {
+ char *t = getenv("PCMCIA_OPTS");
+ if (t == NULL) return -1;
+ parse_env = 1;
+ source_stack_ptr = 0;
+ current_file = "PCMCIA_OPTS";
+ current_lineno = 1;
+ yy_scan_string(t);
+ return 0;
+ } else
+ return -1;
+ }
+ fclose(s->file);
+ free(current_file);
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ if (get_glob() != 0) {
+ yy_switch_to_buffer(s->buffer);
+ current_lineno = s->lineno;
+ current_file = s->filename;
+ }
+ return 0;
+}
+
+/*======================================================================
+
+ The main entry point... returns -1 if the file can't be accessed.
+
+======================================================================*/
+
+int parse_configfile(char *fn)
+{
+ FILE *f;
+
+ f = fopen(fn, "r");
+ if (!f) {
+ syslog(LOG_ERR, "could not open '%s': %m", fn);
+ return -1;
+ }
+ current_lineno = 1;
+ current_file = fn;
+ source_stack_ptr = 0;
+ yyrestart(f);
+ yyparse();
+ fclose(f);
+ return 0;
+}
+
diff --git a/src/pccardctl.c b/src/pccardctl.c
new file mode 100644
index 0000000..d0220b6
--- /dev/null
+++ b/src/pccardctl.c
@@ -0,0 +1,329 @@
+/*
+ * (C) 2004-2005 Dominik Brodowski <linux@brodo.de>
+ *
+ * Partly based on cardctl.c from pcmcia-cs-3.2.7/cardmgr/, which states
+ * in its header:
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * Licensed under the terms of the GNU GPL License version 2.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libintl.h>
+#include <locale.h>
+
+#include <sysfs/libsysfs.h>
+
+#include <getopt.h>
+
+#define MAX_SOCKET 8
+
+
+static int pccardctl_echo_one(unsigned long socket_no, const char *in_file)
+{
+ int ret;
+ char file[SYSFS_PATH_MAX];
+ struct sysfs_attribute *attr;
+
+ if (!file)
+ return -EINVAL;
+
+ snprintf(file, SYSFS_PATH_MAX, "/sys/class/pcmcia_socket/pcmcia_socket%lu/%s",
+ socket_no, in_file);
+
+ attr = sysfs_open_attribute(file);
+ if (!attr)
+ return -ENODEV;
+
+ ret = sysfs_write_attribute(attr, "42", 2);
+
+ sysfs_close_attribute(attr);
+
+ return (ret);
+}
+
+static int pccardctl_socket_exists(unsigned long socket_no)
+{
+ char file[SYSFS_PATH_MAX];
+
+ snprintf(file, SYSFS_PATH_MAX,
+ "/sys/class/pcmcia_socket/pcmcia_socket%lu/card_insert",
+ socket_no);
+
+ return (!(sysfs_path_is_file(file)));
+}
+
+static char * pccardctl_get_string(unsigned long socket_no, const char *in_file)
+{
+ int ret, len;
+ char value[SYSFS_PATH_MAX];
+ char file[SYSFS_PATH_MAX];
+ char *result;
+
+ snprintf(file, SYSFS_PATH_MAX, "/sys/bus/pcmcia/devices/%lu.0/%s",
+ socket_no, in_file);
+ ret = sysfs_read_attribute_value(file, value, SYSFS_PATH_MAX);
+ if (ret)
+ return NULL;
+
+ len = strlen(value);
+ if (len < 2)
+ return NULL;
+
+ result = malloc(sizeof(char) * len);
+ if (!result)
+ return NULL;
+
+ strncpy(result, value, len);
+ result[len - 1] = '\0';
+
+ return (result);
+}
+
+static int pccardctl_get_one(unsigned long socket_no, const char *in_file, unsigned int *result)
+{
+ int ret;
+ char value[SYSFS_PATH_MAX];
+ char file[SYSFS_PATH_MAX];
+
+ snprintf(file, SYSFS_PATH_MAX, "/sys/bus/pcmcia/devices/%lu.0/%s",
+ socket_no, in_file);
+ ret = sysfs_read_attribute_value(file, value, SYSFS_PATH_MAX);
+ if (!ret)
+ sscanf(value, "0x%X", result);
+
+ return (ret);
+}
+
+static int pccardctl_ident(unsigned long socket_no)
+{
+ static char *fn[] = {
+ "multifunction",
+ "memory",
+ "serial",
+ "parallel",
+ "fixed disk",
+ "video",
+ "network",
+ "AIMS",
+ "SCSI"
+ };
+ char *prod_id[4];
+ int valid_prod_id = 0;
+ int i;
+ unsigned int manf_id, card_id;
+
+ if (!pccardctl_socket_exists(socket_no))
+ return -ENODEV;
+
+ for (i=1; i<=4; i++) {
+ char file[SYSFS_PATH_MAX];
+ snprintf(file, SYSFS_PATH_MAX, "prod_id%u", i);
+
+ prod_id[i-1] = pccardctl_get_string(socket_no, file);
+ if (prod_id[i-1])
+ valid_prod_id++;
+ }
+
+ if (valid_prod_id) {
+ printf(" product info: ");
+ for (i=0;i<4;i++) {
+ printf("%s\"%s\"", (i>0) ? ", " : "",
+ prod_id[i] ? prod_id[i] : "" );
+ if (prod_id[i])
+ free(prod_id[i]);
+ }
+ printf("\n");
+ } else
+ printf(" no product info available\n");
+
+ if (!pccardctl_get_one(socket_no, "manf_id", &manf_id))
+ if (!pccardctl_get_one(socket_no, "card_id", &card_id))
+ printf(" manfid: 0x%04x, 0x%04x\n", manf_id, card_id);
+
+ if (!pccardctl_get_one(socket_no, "func_id", &manf_id))
+ printf(" function: %d (%s)\n", manf_id, fn[manf_id]);
+
+
+ return 0;
+}
+
+static int pccardctl_info(unsigned long socket_no)
+{
+ int i;
+ unsigned int manf_id, card_id, func_id;
+ char *prod_id;
+
+ if (!pccardctl_socket_exists(socket_no))
+ return -ENODEV;
+
+ for (i=1; i<=4; i++) {
+ char file[SYSFS_PATH_MAX];
+ snprintf(file, SYSFS_PATH_MAX, "prod_id%u", i);
+
+ prod_id = pccardctl_get_string(socket_no, file);
+
+ printf("PRODID_%d=\"%s\"\n", i, (prod_id) ? prod_id : "");
+
+ free(prod_id);
+ prod_id = NULL;
+ }
+
+ printf("MANFID=%04x,%04x\n",
+ (!pccardctl_get_one(socket_no, "manf_id", &manf_id)) ? manf_id : 0,
+ (!pccardctl_get_one(socket_no, "card_id", &card_id)) ? card_id : 0);
+
+ printf("FUNCID=%d\n",
+ (!pccardctl_get_one(socket_no, "func_id", &func_id)) ? func_id : 255);
+
+ return 0;
+}
+
+static void print_header(void) {
+ printf("pccardctl (C) 2004 Dominik Brodowski, (C) 1999 David A. Hinds\n");
+ printf(gettext ("Report errors and bugs to <linux-pcmcia@lists.infradead.org>, please.\n"));
+}
+
+static void print_help(void) {
+ /* TBD */
+}
+
+static void print_unknown_arg(void) {
+ print_header();
+ printf(gettext ("invalid or unknown argument\n"));
+ print_help();
+}
+
+static struct option pccardctl_opts[] = {
+ { .name="version", .has_arg=no_argument, .flag=NULL, .val='V'},
+ { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'},
+// { .name="socket", .has_arg=required_argument, .flag=NULL, .val='s'},
+// { .name="socketdir", .has_arg=required_argument, .flag=NULL, .val='d'},
+};
+
+enum {
+ PCCARDCTL_INSERT,
+ PCCARDCTL_EJECT,
+ PCCARDCTL_SUSPEND,
+ PCCARDCTL_RESUME,
+ PCCARDCTL_RESET,
+ PCCARDCTL_INFO,
+ PCCARDCTL_STATUS,
+ PCCARDCTL_CONFIG,
+ PCCARDCTL_IDENT,
+ NCMD
+};
+
+static char *cmdname[] = {
+ "insert",
+ "eject",
+ "suspend",
+ "resume",
+ "reset",
+ "info",
+ "status",
+ "config",
+ "ident",
+};
+
+
+int main(int argc, char **argv) {
+ extern char *optarg;
+ extern int optind, opterr, optopt;
+ int ret = 0;
+ unsigned int cont = 1;
+ unsigned long socket = 0;
+ unsigned int socket_is_set = 0;
+ char *s;
+ unsigned int cmd;
+
+ do {
+ ret = getopt_long(argc, argv, "Vhc:f:s:", pccardctl_opts, NULL);
+ switch (ret) {
+ case -1:
+ cont = 0;
+ break;
+ case 'V':
+ print_header();
+ return 0;
+ case 'h':
+ print_header();
+ print_help();
+ return 0;
+ case 'c':
+ case 's':
+ case 'f':
+ /* ignored */
+ fprintf(stderr, "ignoring parameter '%c'\n", ret);
+ break;
+ default:
+ print_unknown_arg();
+ return -EINVAL;
+ }
+ } while (cont);
+
+ if ((argc == optind) || (argc > (optind + 2))) {
+ print_unknown_arg();
+ return -EINVAL;
+ }
+
+ /* determine command */
+ for (cmd = 0; cmd < NCMD; cmd++)
+ if (strcmp(argv[optind], cmdname[cmd]) == 0)
+ break;
+ if (cmd == NCMD) {
+ print_unknown_arg();
+ return -EINVAL;
+ }
+
+ if (argc == optind+2) {
+ socket_is_set = 1;
+ socket = strtol(argv[optind+1], &s, 0);
+ if ((*argv[optind+1] == '\0') || (*s != '\0') || (socket >= MAX_SOCKET)) {
+ print_unknown_arg();
+ return -EINVAL;
+ }
+ }
+
+ for (cont = 0; cont < MAX_SOCKET; cont++) {
+ if (socket_is_set && (socket != cont))
+ continue;
+
+ if (!socket_is_set && !pccardctl_socket_exists(cont))
+ continue;
+
+ if (!socket_is_set && (cmd > PCCARDCTL_INFO))
+ printf("Socket %d:\n", cont);
+
+ ret = 0;
+ switch (cmd) {
+ case PCCARDCTL_INSERT:
+ ret = pccardctl_echo_one(cont, "card_insert");
+ break;
+ case PCCARDCTL_EJECT:
+ ret = pccardctl_echo_one(cont, "card_eject");
+ break;
+ case PCCARDCTL_INFO:
+ ret = pccardctl_info(cont);
+ break;
+ case PCCARDCTL_IDENT:
+ ret = pccardctl_ident(cont);
+ break;
+ default:
+ fprintf(stderr, "command '%s' not yet handled by pccardctl\n", cmdname[cmd]);
+ return -EAGAIN;
+ }
+
+ if (ret && socket_is_set)
+ return (ret);
+ }
+
+ return 0;
+}
diff --git a/src/pcmcia-check-broken-cis.c b/src/pcmcia-check-broken-cis.c
new file mode 100644
index 0000000..b5e4c89
--- /dev/null
+++ b/src/pcmcia-check-broken-cis.c
@@ -0,0 +1,90 @@
+/*
+ * pcmcia-check-broken-cis.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ * (C) 2005 Dominik Brodowski
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+
+#include "cistpl.h"
+
+extern int read_out_cis (unsigned int socket_no);
+extern int pcmcia_get_first_tuple(unsigned int function, tuple_t *tuple);
+extern int pcmcia_get_tuple_data(tuple_t *tuple);
+
+struct needs_cis {
+ unsigned long code;
+ unsigned long ofs;
+ char *info;
+ char *cisfile;
+};
+
+#define NEEDS_CIS_ENTRY(_code, _ofs, _info, _cisfile) \
+{ .code = _code, .ofs = _ofs, .info = _info, .cisfile = _cisfile, }
+
+static struct needs_cis cis_table[] = {
+ /* "D-Link DE-650 Ethernet" */
+ NEEDS_CIS_ENTRY(0x40, 0x0009, "D-Link PC Ethernet Card", "D-Link.dat"),
+ /* "Linksys Ethernet E-CARD PC Ethernet Card */
+ NEEDS_CIS_ENTRY(0x40, 0x0009, "E-CARD PC Ethernet Card", "E-CARD.dat"),
+ { },
+};
+
+int main(int argc, char **argv) {
+ int ret;
+ unsigned int socket_no;
+ struct needs_cis * entry = NULL;
+ tuple_t tuple;
+ unsigned char buf[256];
+
+ if (argc != 2)
+ return -EINVAL;
+
+ ret = sscanf(argv[1], "%u", &socket_no);
+ if (ret != 1)
+ return -ENODEV;
+
+ ret = read_out_cis(socket_no);
+ if (ret)
+ return (ret);
+
+ entry = &cis_table[0];
+
+ while (entry) {
+ if (!entry->cisfile)
+ return 0;
+
+ tuple.DesiredTuple = entry->code;
+ tuple.Attributes = TUPLE_RETURN_COMMON;
+ tuple.TupleData = buf;
+ tuple.TupleDataMax = 255;
+ pcmcia_get_first_tuple(BIND_FN_ALL, &tuple);
+
+ tuple.TupleOffset = entry->ofs;
+
+ pcmcia_get_tuple_data(&tuple);
+
+ if (strncmp((char *) tuple.TupleData, entry->info,
+ strlen(entry->info)) != 0) {
+ entry++;
+ continue;
+ }
+
+ printf("%s", entry->cisfile);
+ };
+
+ return 0;
+}
diff --git a/src/pcmcia-modalias.c b/src/pcmcia-modalias.c
new file mode 100644
index 0000000..4aad951
--- /dev/null
+++ b/src/pcmcia-modalias.c
@@ -0,0 +1,149 @@
+/*
+ * pcmcia-modalias - generate a MODULE_ALIAS string appropriate for already insterted PCMCIA cards
+ *
+ * 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.
+ *
+ * (C) 2005 Dominik Brodowski <linux@brodo.de>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+
+#include <sysfs/libsysfs.h>
+
+
+#define PATH_TO_DEVICE "/sys/bus/pcmcia/devices/"
+
+
+unsigned int crc32(unsigned char const *p, unsigned int len)
+{
+ int i;
+ unsigned int crc = 0;
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
+ }
+ return crc;
+}
+
+static unsigned int get_one_hash(char *device, unsigned int prod_id_nr) {
+ char file[SYSFS_PATH_MAX];
+ char value[SYSFS_PATH_MAX];
+ int ret;
+
+ snprintf(file, SYSFS_PATH_MAX, PATH_TO_DEVICE "%s/prod_id%d", device, prod_id_nr);
+
+ ret = sysfs_read_attribute_value(file, value, SYSFS_PATH_MAX);
+ if (ret)
+ return 0;
+
+ if (strlen(value) < 2)
+ return 0;
+
+ return crc32(value, strlen(value) - 1);
+}
+
+
+static unsigned int read_one(char *device, char *name) {
+ char file[SYSFS_PATH_MAX];
+ char value[SYSFS_PATH_MAX];
+ unsigned int value2;
+ int ret;
+
+ snprintf(file, SYSFS_PATH_MAX, PATH_TO_DEVICE "%s/%s", device, name);
+
+ ret = sysfs_read_attribute_value(file, value, SYSFS_PATH_MAX);
+ if (ret)
+ return 0;
+
+ ret = sscanf(value, "0x%X", &value2);
+ if (ret != 1)
+ return 0;
+
+ return value2;
+}
+
+static int extract_modalias_string(char *device) {
+ char modalias_string[SYSFS_PATH_MAX]; /* that's more than enough */
+ int pos = 0;
+ unsigned int value;
+ unsigned int tmp, tmp2;
+
+ value = read_one(device, "manf_id");
+ pos += snprintf(&modalias_string[pos], SYSFS_PATH_MAX - pos,
+ "pcmcia:m%04X", value);
+ if (pos > (SYSFS_PATH_MAX - 10))
+ return -ENOMEM;
+
+ value = read_one(device, "card_id");
+ pos += snprintf(&modalias_string[pos], SYSFS_PATH_MAX - pos,
+ "c%04X", value);
+ if (pos > (SYSFS_PATH_MAX - 10))
+ return -ENOMEM;
+
+ value = read_one(device, "func_id");
+ pos += snprintf(&modalias_string[pos], SYSFS_PATH_MAX - pos,
+ "f%02X", value);
+ if (pos > (SYSFS_PATH_MAX - 10))
+ return -ENOMEM;
+
+ value = read_one(device, "function");
+ pos += snprintf(&modalias_string[pos], SYSFS_PATH_MAX - pos,
+ "pfn%02X", value);
+ if (pos > (SYSFS_PATH_MAX - 10))
+ return -ENOMEM;
+
+ tmp2 = sscanf(device, "%d.%d", &tmp, &value);
+ if (tmp2 != 2)
+ return -EIO;
+ pos += snprintf(&modalias_string[pos], SYSFS_PATH_MAX - pos,
+ "fn%02X", value);
+ if (pos > (SYSFS_PATH_MAX - 10))
+ return -ENOMEM;
+
+ value = get_one_hash(device, 1);
+ pos += snprintf(&modalias_string[pos], SYSFS_PATH_MAX - pos,
+ "pa%08X", value);
+ if (pos > (SYSFS_PATH_MAX - 10))
+ return -ENOMEM;
+
+ value = get_one_hash(device, 2);
+ pos += snprintf(&modalias_string[pos], SYSFS_PATH_MAX - pos,
+ "pb%08X", value);
+ if (pos > (SYSFS_PATH_MAX - 10))
+ return -ENOMEM;
+
+ value = get_one_hash(device, 3);
+ pos += snprintf(&modalias_string[pos], SYSFS_PATH_MAX - pos,
+ "pc%08X", value);
+ if (pos > (SYSFS_PATH_MAX - 10))
+ return -ENOMEM;
+
+ value = get_one_hash(device, 4);
+ pos += snprintf(&modalias_string[pos], SYSFS_PATH_MAX - pos,
+ "pd%08X", value);
+ if (pos > (SYSFS_PATH_MAX - 10))
+ return -ENOMEM;
+
+
+ printf("%s\n", modalias_string);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 2)
+ return -EINVAL;
+
+ extract_modalias_string(argv[1]);
+
+ return 0;
+}
diff --git a/src/read-cis.c b/src/read-cis.c
new file mode 100644
index 0000000..2a43f4c
--- /dev/null
+++ b/src/read-cis.c
@@ -0,0 +1,266 @@
+/*
+ * read-cis.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+
+#include <sysfs/libsysfs.h>
+
+#include "cistpl.h"
+
+#define MAX_TUPLES 0x200
+
+#define PATH_TO_SOCKET "/sys/class/pcmcia_socket/"
+
+/* Bits in attr field */
+#define IS_ATTR 1
+#define IS_INDIRECT 8
+
+
+static unsigned int functions;
+static unsigned char cis_copy[MAX_TUPLES];
+static unsigned int cis_length;
+
+
+#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)
+{
+ unsigned 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)
+{
+ char file[SYSFS_PATH_MAX];
+ int ret;
+ tuple_t tuple;
+ unsigned char buf[256];
+
+
+ snprintf(file, SYSFS_PATH_MAX, PATH_TO_SOCKET "pcmcia_socket%d/cis",
+ socket_no);
+
+ ret = sysfs_read_attribute_value(file, cis_copy, MAX_TUPLES);
+ if (ret)
+ return -EIO;
+
+ cis_length = strlen(cis_copy);
+ if (cis_length < 4)
+ return -EINVAL;
+
+ functions = 1;
+
+ tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
+ tuple.Attributes = TUPLE_RETURN_COMMON;
+
+ ret = pcmcia_get_first_tuple(BIND_FN_ALL, &tuple);
+ if (ret)
+ return -EBUSY;
+
+ tuple.TupleData = buf;
+ tuple.TupleOffset = 0;
+ tuple.TupleDataMax = 255;
+ ret = pcmcia_get_tuple_data(&tuple);
+ if (ret)
+ return -EBADF;
+
+ functions = tuple.TupleData[0];
+
+ return 0;
+}
diff --git a/src/startup.c b/src/startup.c
new file mode 100644
index 0000000..cce0ad6
--- /dev/null
+++ b/src/startup.c
@@ -0,0 +1,223 @@
+/*
+ * Startup tool for non statically mapped PCMCIA sockets
+ *
+ * (C) 2005 Dominik Brodowski <linux@brodo.de>
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * License: GPL v2
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <sysfs/libsysfs.h>
+
+#include "startup.h"
+
+/* uncomment for debug output */
+#ifdef DEBUG
+#define dprintf printf
+#else
+#define dprintf(...) do { } while(0);
+#endif
+
+/* Linked list of resource adjustments */
+struct adjust_list_t *root_adjust = NULL;
+
+/* path for config file, device scripts */
+static char *configpath = "/etc/pcmcia";
+
+enum {
+ RESOURCE_MEM,
+ RESOURCE_IO,
+ MAX_RESOURCE_FILES
+};
+
+
+static const char *resource_files[MAX_RESOURCE_FILES] = {
+ [RESOURCE_MEM] = "available_resources_mem",
+ [RESOURCE_IO] = "available_resources_io",
+};
+
+#define PATH_TO_SOCKET "/sys/class/pcmcia_socket/"
+
+
+static int add_available_resource(unsigned int socket_no, unsigned int type,
+ unsigned long start, unsigned long end)
+{
+ char file[SYSFS_PATH_MAX];
+ char content[SYSFS_PATH_MAX];
+ struct sysfs_attribute *attr;
+ int ret;
+ size_t len;
+
+ if (type >= MAX_RESOURCE_FILES)
+ return -EINVAL;
+
+ if (end <= start)
+ return -EINVAL;
+
+ dprintf("%d %d %lx %lx\n", socket_no, type, start, end);
+
+ snprintf(file, SYSFS_PATH_MAX, PATH_TO_SOCKET "pcmcia_socket%u/%s",
+ socket_no, resource_files[type]);
+
+ len = snprintf(content, SYSFS_PATH_MAX, "0x%08lx - 0x%08lx", start, end);
+
+ dprintf("content is %s\n", content);
+
+ dprintf("file is %s\n", file);
+
+ attr = sysfs_open_attribute(file);
+ if (!attr)
+ return -ENODEV;
+
+ dprintf("open, len %d\n", len);
+
+ ret = sysfs_write_attribute(attr, content, len);
+
+ dprintf("ret is %d\n", ret);
+
+ sysfs_close_attribute(attr);
+
+ return (ret);
+}
+
+static int setup_done(unsigned int socket_no)
+{
+ int ret;
+ char file[SYSFS_PATH_MAX];
+ struct sysfs_attribute *attr;
+
+ snprintf(file, SYSFS_PATH_MAX, PATH_TO_SOCKET
+ "pcmcia_socket%u/available_resources_setup_done",
+ socket_no);
+
+ attr = sysfs_open_attribute(file);
+ if (!attr)
+ return -ENODEV;
+
+ sysfs_write_attribute(attr, "42", 2);
+
+ sysfs_close_attribute(attr);
+
+ return (ret);
+}
+
+
+static int disallow_irq(unsigned int socket_no, unsigned int irq)
+{
+ char file[SYSFS_PATH_MAX];
+ char content[SYSFS_PATH_MAX];
+ struct sysfs_attribute *attr;
+ unsigned int mask = 0xfff;
+ unsigned int new_mask;
+ int ret;
+ size_t len;
+
+ if (irq >= 32)
+ return -EINVAL;
+
+ snprintf(file, SYSFS_PATH_MAX, PATH_TO_SOCKET
+ "pcmcia_socket%u/card_irq_mask",
+ socket_no);
+
+ attr = sysfs_open_attribute(file);
+ if (!attr)
+ return -ENODEV;
+
+ dprintf("open, len %d\n", len);
+
+ ret = sysfs_read_attribute(attr);
+ if (ret) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!attr->value || (attr->len < 6)) {
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = sscanf(attr->value, "0x%x\n", &mask);
+
+ new_mask = 1 << irq;
+
+ mask &= ~new_mask;
+
+ len = snprintf(content, SYSFS_PATH_MAX, "0x%04x", mask);
+
+ dprintf("content is %s\n", content);
+
+ ret = sysfs_write_attribute(attr, content, len);
+
+ out:
+ sysfs_close_attribute(attr);
+
+ return (ret);
+}
+
+
+static void load_config(void)
+{
+ if (chdir(configpath) != 0) {
+ syslog(LOG_ERR, "chdir to %s failed: %m", configpath);
+ exit(EXIT_FAILURE);
+ }
+ parse_configfile("config.opts");
+ return;
+}
+
+
+static void adjust_resources(unsigned int socket_no)
+{
+ adjust_list_t *al;
+ char tmp[64];
+
+ for (al = root_adjust; al; al = al->next) {
+ switch (al->adj.Resource) {
+ case RES_MEMORY_RANGE:
+ add_available_resource(socket_no, RESOURCE_MEM,
+ al->adj.resource.memory.Base,
+ al->adj.resource.memory.Base +
+ al->adj.resource.memory.Size - 1);
+ break;
+ case RES_IO_RANGE:
+ add_available_resource(socket_no, RESOURCE_IO,
+ al->adj.resource.io.BasePort,
+ al->adj.resource.io.BasePort +
+ al->adj.resource.io.NumPorts - 1);
+ break;
+ case RES_IRQ:
+ disallow_irq(socket_no, al->adj.resource.irq.IRQ);
+ break;
+ }
+ syslog(LOG_WARNING, "could not adjust resource: %s: %m", tmp);
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ unsigned long socket;
+
+ if (argc != 2)
+ return -EINVAL;
+
+ socket = strtoul(argv[1], NULL, 0);
+
+ load_config();
+
+ adjust_resources(socket);
+
+ setup_done(socket);
+
+ return 0;
+}
diff --git a/src/startup.h b/src/startup.h
new file mode 100644
index 0000000..ba6af2c
--- /dev/null
+++ b/src/startup.h
@@ -0,0 +1,54 @@
+/*
+ * Startup tool for non statically mapped PCMCIA sockets
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * License: GPL v2
+ *
+ */
+
+#define MAX_SOCKS 8
+#define MAX_BINDINGS 4
+#define MAX_MODULES 4
+
+/* for AdjustResourceInfo */
+typedef struct adjust_t {
+ unsigned int Action;
+ unsigned int Resource;
+ unsigned int Attributes;
+ union {
+ struct memory {
+ unsigned long Base;
+ unsigned long Size;
+ } memory;
+ struct io {
+ unsigned long BasePort;
+ unsigned long NumPorts;
+ unsigned int IOAddrLines;
+ } io;
+ struct irq {
+ unsigned int IRQ;
+ } irq;
+ } resource;
+} adjust_t;
+
+
+typedef struct adjust_list_t {
+ adjust_t adj;
+ struct adjust_list_t *next;
+} adjust_list_t;
+
+
+extern adjust_list_t *root_adjust;
+
+int parse_configfile(char *fn);
+
+
+#define RES_MEMORY_RANGE 1
+#define RES_IO_RANGE 2
+#define RES_IRQ 3
+#define RES_RESERVED 0x10
+#define REMOVE_MANAGED_RESOURCE 1
+#define ADD_MANAGED_RESOURCE 2
diff --git a/src/yacc_config.h b/src/yacc_config.h
new file mode 100644
index 0000000..25bfc94
--- /dev/null
+++ b/src/yacc_config.h
@@ -0,0 +1,35 @@
+#define DEVICE 257
+#define CARD 258
+#define ANONYMOUS 259
+#define TUPLE 260
+#define MANFID 261
+#define VERSION 262
+#define FUNCTION 263
+#define PCI 264
+#define BIND 265
+#define CIS 266
+#define TO 267
+#define NEEDS_MTD 268
+#define MODULE 269
+#define OPTS 270
+#define CLASS 271
+#define REGION 272
+#define JEDEC 273
+#define DTYPE 274
+#define DEFAULT 275
+#define MTD 276
+#define INCLUDE 277
+#define EXCLUDE 278
+#define RESERVE 279
+#define IRQ_NO 280
+#define PORT 281
+#define MEMORY 282
+#define STRING 283
+#define NUMBER 284
+#define SOURCE 285
+typedef union {
+ char *str;
+ u_long num;
+ struct adjust_list_t *adjust;
+} YYSTYPE;
+extern YYSTYPE yylval;
diff --git a/src/yacc_config.y b/src/yacc_config.y
new file mode 100644
index 0000000..f6df721
--- /dev/null
+++ b/src/yacc_config.y
@@ -0,0 +1,131 @@
+%{
+/*
+ * Startup tool for non statically mapped PCMCIA sockets - config file parsing
+ *
+ * (C) 2005 Dominik Brodowski <linux@brodo.de>
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * License: GPL v2
+ */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/types.h>
+
+#include "startup.h"
+
+/* If bison: generate nicer error messages */
+#define YYERROR_VERBOSE 1
+
+/* from lex_config, for nice error messages */
+extern char *current_file;
+extern int current_lineno;
+
+void yyerror(char *msg, ...);
+
+%}
+
+%token DEVICE CARD ANONYMOUS TUPLE MANFID VERSION FUNCTION PCI
+%token BIND CIS TO NEEDS_MTD MODULE OPTS CLASS
+%token REGION JEDEC DTYPE DEFAULT MTD
+%token INCLUDE EXCLUDE RESERVE IRQ_NO PORT MEMORY
+%token STRING NUMBER SOURCE
+
+%union {
+ char *str;
+ u_long num;
+ struct adjust_list_t *adjust;
+}
+
+%type <str> STRING
+%type <num> NUMBER
+%type <adjust> adjust resource
+%%
+list: /* nothing */
+ | list adjust
+ {
+ adjust_list_t **tail = &root_adjust;
+ while (*tail != NULL) tail = &(*tail)->next;
+ *tail = $2;
+ }
+ ;
+
+adjust: INCLUDE resource
+ {
+ $2->adj.Action = ADD_MANAGED_RESOURCE;
+ $$ = $2;
+ }
+ | EXCLUDE resource
+ {
+ $2->adj.Action = REMOVE_MANAGED_RESOURCE;
+ $$ = $2;
+ }
+ | RESERVE resource
+ {
+ $2->adj.Action = ADD_MANAGED_RESOURCE;
+ $2->adj.Attributes |= RES_RESERVED;
+ $$ = $2;
+ }
+ | adjust ',' resource
+ {
+ $3->adj.Action = $1->adj.Action;
+ $3->adj.Attributes = $1->adj.Attributes;
+ $3->next = $1;
+ $$ = $3;
+ }
+ ;
+
+resource: IRQ_NO NUMBER
+ {
+ $$ = calloc(sizeof(adjust_list_t), 1);
+ $$->adj.Resource = RES_IRQ;
+ $$->adj.resource.irq.IRQ = $2;
+ }
+ | PORT NUMBER '-' NUMBER
+ {
+ if (($4 < $2) || ($4 > 0xffff)) {
+ yyerror("invalid port range 0x%x-0x%x", $2, $4);
+ YYERROR;
+ }
+ $$ = calloc(sizeof(adjust_list_t), 1);
+ $$->adj.Resource = RES_IO_RANGE;
+ $$->adj.resource.io.BasePort = $2;
+ $$->adj.resource.io.NumPorts = $4 - $2 + 1;
+ }
+ | MEMORY NUMBER '-' NUMBER
+ {
+ if ($4 < $2) {
+ yyerror("invalid address range 0x%x-0x%x", $2, $4);
+ YYERROR;
+ }
+ $$ = calloc(sizeof(adjust_list_t), 1);
+ $$->adj.Resource = RES_MEMORY_RANGE;
+ $$->adj.resource.memory.Base = $2;
+ $$->adj.resource.memory.Size = $4 - $2 + 1;
+ }
+ ;
+
+%%
+void yyerror(char *msg, ...)
+{
+ va_list ap;
+ char str[256];
+
+ va_start(ap, msg);
+ sprintf(str, "error in file '%s' line %d: ",
+ current_file, current_lineno);
+ vsprintf(str+strlen(str), msg, ap);
+#if YYDEBUG
+ fprintf(stderr, "%s\n", str);
+#else
+ syslog(LOG_ERR, "%s", str);
+#endif
+ va_end(ap);
+}
+