diff options
author | Dominik Brodowski <brodo@isilmar.linta.de> | 2005-12-06 20:21:40 +0100 |
---|---|---|
committer | Dominik Brodowski <brodo@isilmar.linta.de> | 2005-12-06 20:21:40 +0100 |
commit | 48166159e549890157aad9a9428e311d2a6ad5a2 (patch) | |
tree | da1fe0bbb60362bee8f137a6d791171a756e1291 | |
download | pcmciautils-48166159e549890157aad9a9428e311d2a6ad5a2.tar.gz |
Release of pcmciautils-001 (2005-03-04)
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | Makefile | 214 | ||||
-rw-r--r-- | build/ccdv.c | 387 | ||||
-rw-r--r-- | config/config.opts | 63 | ||||
-rwxr-xr-x | hotplug/pcmcia.agent | 53 | ||||
-rwxr-xr-x | hotplug/pcmcia.rc | 53 | ||||
-rwxr-xr-x | hotplug/pcmcia_socket.agent | 38 | ||||
-rwxr-xr-x | hotplug/pcmcia_socket.rc | 49 | ||||
-rw-r--r-- | src/cistpl.h | 598 | ||||
-rw-r--r-- | src/lex_config.l | 220 | ||||
-rw-r--r-- | src/pccardctl.c | 329 | ||||
-rw-r--r-- | src/pcmcia-check-broken-cis.c | 90 | ||||
-rw-r--r-- | src/pcmcia-modalias.c | 149 | ||||
-rw-r--r-- | src/read-cis.c | 266 | ||||
-rw-r--r-- | src/startup.c | 223 | ||||
-rw-r--r-- | src/startup.h | 54 | ||||
-rw-r--r-- | src/yacc_config.h | 35 | ||||
-rw-r--r-- | src/yacc_config.y | 131 |
18 files changed, 3292 insertions, 0 deletions
@@ -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); +} + |