aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2011-12-16 06:27:49 +0000
committerBen Hutchings <ben@decadent.org.uk>2011-12-16 06:58:02 +0000
commit0f881f047e5aeb99a9281c766ad9d58b18a81301 (patch)
tree60e4a5ae50ee3755552677986f48a88c34d2539e
downloadcis-tools-0f881f047e5aeb99a9281c766ad9d58b18a81301.tar.gz
Import CIS tools from pcmcia-cs 3.2.8
-rw-r--r--COPYING23
-rw-r--r--LICENSE563
-rw-r--r--cistpl.c1502
-rw-r--r--dump_cis.c1102
-rw-r--r--lex_cis.l234
-rw-r--r--pack_cis.c447
-rw-r--r--pack_cis.h38
-rw-r--r--pcmcia/bulkmem.h195
-rw-r--r--pcmcia/cistpl.h604
-rw-r--r--pcmcia/cs.h441
-rw-r--r--pcmcia/cs_types.h70
-rw-r--r--pcmcia/ds.h148
-rw-r--r--yacc_cis.y418
13 files changed, 5785 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..bf9c3e7
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,23 @@
+Copyright (C) 1998, 1999, 2000 David A. Hinds
+
+Unless otherwise indicated, this code is distributed under version 1.1
+of the Mozilla Public License ("MPL"), included in the LICENSE file.
+
+Alternatively, these files may be used under the terms of the GNU
+Public License version 2 (the "GPL"), in which case the provisions of
+the GPL are applicable instead of the above. If you wish to allow the
+use of your version of these files only under the terms of the GPL and
+not to allow others to use your version of these files under the MPL,
+indicate your decision by deleting the provisions above and replace
+them with the notice and other provisions required by the GPL. If you
+do not delete the provisions above, a recipient may use your version
+of these files under either the MPL or the GPL.
+
+Some of the client drivers (nmclan_cs.c, 3c589_cs.c, 3c574_cs.c,
+3c575_cb.c, ibmtr_cs.c, pcnet_cs.c, smc91c92_cs.c, fmvj18x_cs.c,
+wavelan_cs.c, wvlan_cs.c, netwave_cs.c, xirc2ps_cs.c, serial_cb.c)
+contain code written by others, subject to more restrictive (GPL)
+licensing requirements.
+
+ -- David Hinds
+ dahinds@users.sourceforge.net
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8d23a4c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,563 @@
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ----------------
+
+1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. ''Contributor'' means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. ''Contributor Version'' means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. ''Covered Code'' means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. ''Electronic Distribution Mechanism'' means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. ''Executable'' means Covered Code in any form other than Source
+ Code.
+
+ 1.6. ''Initial Developer'' means the individual or entity identified as
+ the Initial Developer in the Source Code notice required by Exhibit A.
+
+ 1.7. ''Larger Work'' means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. ''License'' means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. ''Modifications'' means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. ''Original Code'' means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this License
+ is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process, and
+ apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. ''Source Code'' means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus any
+ associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You'' (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You'' includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control'' means (a) the power, direct or indirect, to
+ cause the direction or management of such entity, whether by contract
+ or otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or selling
+ of Original Code, to make, have made, use, practice, sell, and
+ offer for sale, and/or otherwise dispose of the Original Code (or
+ portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes Original
+ Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code and/or
+ as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or selling
+ of Modifications made by that Contributor either alone and/or in
+ combination with its Contributor Version (or portions of such
+ combination), to make, use, sell, offer for sale, have made,
+ and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be distributed
+ only under the terms of this License or a future version of this
+ License released under Section 6.1, and You must include a copy of this
+ License with every copy of the Source Code You distribute. You may not
+ offer or impose any terms on any Source Code version that alters or
+ restricts the applicable version of this License or the recipients'
+ rights hereunder. However, You may include an additional document
+ offering the additional rights described in Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that the
+ Modification is derived, directly or indirectly, from Original Code
+ provided by the Initial Developer and including the name of the Initial
+ Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2, Contributor
+ must include a text file with the Source Code distribution titled
+ "LEGAL'' which describes the claim and the party making the claim
+ in sufficient detail that a recipient will know whom to contact.
+ If Contributor obtains such knowledge after the Modification is
+ made available as described in Section 3.2, Contributor shall
+ promptly modify the LEGAL file in all copies Contributor makes
+ available thereafter and shall take other steps (such as notifying
+ appropriate mailing lists or newsgroups) reasonably calculated to
+ inform those who received the Covered Code that new knowledge has
+ been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely to
+ look for such a notice. If You created one or more Modification(s) You
+ may add your name as a Contributor to the notice described in Exhibit
+ A. You must also duplicate this License in any documentation for the
+ Source Code where You describe recipients' rights or ownership rights
+ relating to Covered Code. You may choose to offer, and to charge a fee
+ for, warranty, support, indemnity or liability obligations to one or
+ more recipients of Covered Code. However, You may do so only on Your
+ own behalf, and not on behalf of the Initial Developer or any
+ Contributor. You must make it absolutely clear than any such warranty,
+ support, indemnity or liability obligation is offered by You alone, and
+ You hereby agree to indemnify the Initial Developer and every
+ Contributor for any liability incurred by the Initial Developer or such
+ Contributor as a result of warranty, support, indemnity or liability
+ terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of the
+ Covered Code is available under the terms of this License, including a
+ description of how and where You have fulfilled the obligations of
+ Section 3.2. The notice must be conspicuously included in any notice in
+ an Executable version, related documentation or collateral in which You
+ describe recipients' rights relating to the Covered Code. You may
+ distribute the Executable version of Covered Code or ownership rights
+ under a license of Your choice, which may contain terms different from
+ this License, provided that You are in compliance with the terms of
+ this License and that the license for the Executable version does not
+ attempt to limit or alter the recipient's rights in the Source Code
+ version from the rights set forth in this License. If You distribute
+ the Executable version under a different license You must make it
+ absolutely clear that any terms which differ from this License are
+ offered by You alone, not by the Initial Developer or any Contributor.
+ You hereby agree to indemnify the Initial Developer and every
+ Contributor for any liability incurred by the Initial Developer or such
+ Contributor as a result of any such terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to statute,
+ judicial order, or regulation then You must: (a) comply with the terms
+ of this License to the maximum extent possible; and (b) describe the
+ limitations and the code they affect. Such description must be included
+ in the LEGAL file described in Section 3.4 and must be included with
+ all distributions of the Source Code. Except to the extent prohibited
+ by statute or regulation, such description must be sufficiently
+ detailed for a recipient of ordinary skill to be able to understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation (''Netscape'') may publish revised
+ and/or new versions of the License from time to time. Each version will
+ be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that the
+ phrases ''Mozilla'', ''MOZILLAPL'', ''MOZPL'', ''Netscape'', "MPL",
+ ''NPL'' or any confusingly similar phrase do not appear in your license
+ (except to note that your license differs from this License) and (b)
+ otherwise make it clear that Your version of the license contains terms
+ which differ from the Mozilla Public License and Netscape Public
+ License. (Filling in the name of the Initial Developer, Original Code
+ or Contributor in the notice described in Exhibit A shall not of
+ themselves be deemed to be modifications of this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS'' BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom You
+ file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License shall,
+ upon 60 days notice from Participant terminate prospectively, unless if
+ within 60 days after receipt of notice You either: (i) agree in
+ writing to pay Participant a mutually agreeable reasonable royalty for
+ Your past and future use of Modifications made by such Participant, or
+ (ii) withdraw Your litigation claim with respect to the Contributor
+ Version against such Participant. If within 60 days of notice, a
+ reasonable royalty and payment arrangement are not mutually agreed upon
+ in writing by the parties or the litigation claim is not withdrawn, the
+ rights granted by Participant to You under Sections 2.1 and/or 2.2
+ automatically terminate at the expiration of the 60 day notice period
+ specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b) and
+ 2.2(b) are revoked effective as of the date You first made, used, sold,
+ distributed, or had made, Modifications made by that Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above, all
+ end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY
+ INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS
+ EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a ''commercial item,'' as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of ''commercial computer
+ software'' and ''commercial computer software documentation,'' as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if any,
+ provides otherwise), excluding its conflict-of-law provisions. With
+ respect to disputes in which at least one party is a citizen of, or an
+ entity chartered or registered to do business in the United States of
+ America, any litigation relating to this License shall be subject to
+ the jurisdiction of the Federal Courts of the Northern District of
+ California, with venue lying in Santa Clara County, California, with
+ the losing party responsible for costs, including without limitation,
+ court costs and reasonable attorneys' fees and expenses. The
+ application of the United Nations Convention on Contracts for the
+ International Sale of Goods is expressly excluded. Any law or
+ regulation which provides that the language of a contract shall be
+ construed against the drafter shall not apply to this License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly, out
+ of its utilization of rights under this License and You agree to work
+ with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+ ``The contents of this file are subject to the Mozilla Public License
+ Version 1.1 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF
+ ANY KIND, either express or implied. See the License for the specific
+ language governing rights and
+ limitations under the License.
+
+ The Original Code is ______________________________________.
+
+ The Initial Developer of the Original Code is ________________________.
+ Portions created by ______________________ are Copyright (C) ______
+ _______________________. All Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the terms of
+ the _____ license (the "[___] License"), in which case the provisions
+ of [______] License are applicable instead of those above. If you
+ wish to allow use of your version of this file only under the terms of
+ the [____] License and not to allow others to use your version of this
+ file under the MPL, indicate your decision by deleting the provisions
+ above and replace them with the notice and other provisions required
+ by the [___] License. If you do not delete the provisions above, a
+ recipient may use your version of this file under either the MPL or the
+ [___] License."
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
+
+ -----------------------------------------------------------------------
+
+ AMENDMENTS
+
+ The Netscape Public License Version 1.1 ("NPL") consists of the Mozilla
+ Public License Version 1.1 with the following Amendments, including
+ Exhibit A-Netscape Public License. Files identified with "Exhibit
+ A-Netscape Public License" are governed by the Netscape Public License
+ Version 1.1.
+
+ Additional Terms applicable to the Netscape Public License.
+ I. Effect.
+ These additional terms described in this Netscape Public
+ License -- Amendments shall apply to the Mozilla Communicator
+ client code and to all Covered Code under this License.
+
+ II. ''Netscape's Branded Code'' means Covered Code that Netscape
+ distributes and/or permits others to distribute under one or more
+ trademark(s) which are controlled by Netscape but which are not
+ licensed for use under this License.
+
+ III. Netscape and logo.
+ This License does not grant any rights to use the trademarks
+ "Netscape'', the "Netscape N and horizon'' logo or the "Netscape
+ lighthouse" logo, "Netcenter", "Gecko", "Java" or "JavaScript",
+ "Smart Browsing" even if such marks are included in the Original
+ Code or Modifications.
+
+ IV. Inability to Comply Due to Contractual Obligation.
+ Prior to licensing the Original Code under this License, Netscape
+ has licensed third party code for use in Netscape's Branded Code.
+ To the extent that Netscape is limited contractually from making
+ such third party code available under this License, Netscape may
+ choose to reintegrate such code into Covered Code without being
+ required to distribute such code in Source Code form, even if such
+ code would otherwise be considered ''Modifications'' under this
+ License.
+
+ V. Use of Modifications and Covered Code by Initial Developer.
+ V.1. In General.
+ The obligations of Section 3 apply to Netscape, except to the
+ extent specified in this Amendment, Section V.2 and V.3.
+
+ V.2. Other Products.
+ Netscape may include Covered Code in products other than the
+ Netscape's Branded Code which are released by Netscape during
+ the two (2) years following the release date of the Original
+ Code, without such additional products becoming subject to
+ the terms of this License, and may license such additional
+ products on different terms from those contained in this
+ License.
+
+ V.3. Alternative Licensing.
+ Netscape may license the Source Code of Netscape's Branded
+ Code, including Modifications incorporated therein, without
+ such Netscape Branded Code becoming subject to the terms of
+ this License, and may license such Netscape Branded Code on
+ different terms from those contained in this License.
+
+ VI. Litigation.
+ Notwithstanding the limitations of Section 11 above, the
+ provisions regarding litigation in Section 11(a), (b) and (c) of
+ the License shall apply to all disputes relating to this License.
+
+ EXHIBIT A-Netscape Public License.
+
+ ''The contents of this file are subject to the Netscape Public
+ License Version 1.1 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at http://www.mozilla.org/NPL/
+
+ Software distributed under the License is distributed on an "AS
+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ rights and limitations under the License.
+
+ The Original Code is Mozilla Communicator client code, released
+ March 31, 1998.
+
+ The Initial Developer of the Original Code is Netscape
+ Communications Corporation. Portions created by Netscape are
+ Copyright (C) 1998-1999 Netscape Communications Corporation. All
+ Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the
+ terms of the _____ license (the "[___] License"), in which case
+ the provisions of [______] License are applicable instead of
+ those above. If you wish to allow use of your version of this
+ file only under the terms of the [____] License and not to allow
+ others to use your version of this file under the NPL, indicate
+ your decision by deleting the provisions above and replace them
+ with the notice and other provisions required by the [___]
+ License. If you do not delete the provisions above, a recipient
+ may use your version of this file under either the NPL or the
+ [___] License."
diff --git a/cistpl.c b/cistpl.c
new file mode 100644
index 0000000..404b8e4
--- /dev/null
+++ b/cistpl.c
@@ -0,0 +1,1502 @@
+/*======================================================================
+
+ PCMCIA Card Information Structure parser
+
+ cistpl.c 1.101 2003/12/15 03:58:03
+
+ The contents of this file are subject to the Mozilla Public
+ License Version 1.1 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS
+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ rights and limitations under the License.
+
+ 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.
+
+ Alternatively, the contents of this file may be used under the
+ terms of the GNU General Public License version 2 (the "GPL"), in
+ which case the provisions of the GPL are applicable instead of the
+ above. If you wish to allow the use of your version of this file
+ only under the terms of the GPL and not to allow others to use
+ your version of this file under the MPL, indicate your decision
+ by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL. If you do not delete
+ the provisions above, a recipient may use your version of this
+ file under either the MPL or the GPL.
+
+======================================================================*/
+
+#define __NO_VERSION__
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/bus_ops.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+
+static const u_char mantissa[] = {
+ 10, 12, 13, 15, 20, 25, 30, 35,
+ 40, 45, 50, 55, 60, 70, 80, 90
+};
+
+static const u_int exponent[] = {
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
+};
+
+/* Convert an extended speed byte to a time in nanoseconds */
+#define SPEED_CVT(v) \
+ (mantissa[(((v)>>3)&15)-1] * exponent[(v)&7] / 10)
+/* Convert a power byte to a current in 0.1 microamps */
+#define POWER_CVT(v) \
+ (mantissa[((v)>>3)&15] * exponent[(v)&7] / 10)
+#define POWER_SCALE(v) (exponent[(v)&7])
+
+/* Upper limit on reasonable # of tuples */
+#define MAX_TUPLES 200
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
+
+INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */
+
+/*======================================================================
+
+ Low-level functions to read and write CIS memory. I think the
+ write routine is only useful for writing one-byte registers.
+
+======================================================================*/
+
+/* Bits in attr field */
+#define IS_ATTR 1
+#define IS_INDIRECT 8
+
+static int setup_cis_mem(socket_info_t *s);
+
+static void set_cis_map(socket_info_t *s, pccard_mem_map *mem)
+{
+ s->ss_entry(s->sock, SS_SetMemMap, mem);
+ if (s->cap.features & SS_CAP_STATIC_MAP) {
+ if (s->cis_virt)
+ bus_iounmap(s->cap.bus, s->cis_virt);
+ s->cis_virt = bus_ioremap(s->cap.bus, mem->sys_start,
+ s->cap.map_size);
+ }
+}
+
+int read_cis_mem(socket_info_t *s, int attr, u_int addr,
+ u_int len, void *ptr)
+{
+ pccard_mem_map *mem = &s->cis_mem;
+ u_char *sys, *buf = ptr;
+
+ DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
+ if (setup_cis_mem(s) != 0) {
+ memset(ptr, 0xff, len);
+ return -1;
+ }
+ mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
+
+ if (attr & IS_INDIRECT) {
+ /* Indirect accesses use a bunch of special registers at fixed
+ locations in common memory */
+ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
+ if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
+ mem->card_start = 0; mem->flags = MAP_ACTIVE;
+ set_cis_map(s, mem);
+ sys = s->cis_virt;
+ bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
+ bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
+ bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
+ bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
+ bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
+ for ( ; len > 0; len--, buf++)
+ *buf = bus_readb(s->cap.bus, sys+CISREG_IDATA0);
+ } else {
+ u_int inc = 1;
+ if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
+ sys += (addr & (s->cap.map_size-1));
+ mem->card_start = addr & ~(s->cap.map_size-1);
+ while (len) {
+ set_cis_map(s, mem);
+ sys = s->cis_virt + (addr & (s->cap.map_size-1));
+ for ( ; len > 0; len--, buf++, sys += inc) {
+ if (sys == s->cis_virt+s->cap.map_size) break;
+ *buf = bus_readb(s->cap.bus, sys);
+ }
+ mem->card_start += s->cap.map_size;
+ addr = 0;
+ }
+ }
+ DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
+ *(u_char *)(ptr+0), *(u_char *)(ptr+1),
+ *(u_char *)(ptr+2), *(u_char *)(ptr+3));
+ return 0;
+}
+
+void write_cis_mem(socket_info_t *s, int attr, u_int addr,
+ u_int len, void *ptr)
+{
+ pccard_mem_map *mem = &s->cis_mem;
+ u_char *sys, *buf = ptr;
+
+ DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
+ if (setup_cis_mem(s) != 0) return;
+ mem->flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
+
+ if (attr & IS_INDIRECT) {
+ /* Indirect accesses use a bunch of special registers at fixed
+ locations in common memory */
+ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
+ if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
+ mem->card_start = 0; mem->flags = MAP_ACTIVE;
+ set_cis_map(s, mem);
+ sys = s->cis_virt;
+ bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
+ bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
+ bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
+ bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
+ bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
+ for ( ; len > 0; len--, buf++)
+ bus_writeb(s->cap.bus, *buf, sys+CISREG_IDATA0);
+ } else {
+ int inc = 1;
+ if (attr & IS_ATTR) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
+ mem->card_start = addr & ~(s->cap.map_size-1);
+ while (len) {
+ set_cis_map(s, mem);
+ sys = s->cis_virt + (addr & (s->cap.map_size-1));
+ for ( ; len > 0; len--, buf++, sys += inc) {
+ if (sys == s->cis_virt+s->cap.map_size) break;
+ bus_writeb(s->cap.bus, *buf, sys);
+ }
+ mem->card_start += s->cap.map_size;
+ addr = 0;
+ }
+ }
+}
+
+/*======================================================================
+
+ This is tricky... when we set up CIS memory, we try to validate
+ the memory window space allocations.
+
+======================================================================*/
+
+/* Scratch pointer to the socket we use for validation */
+static socket_info_t *vs = NULL;
+
+/* Validation function for cards with a valid CIS */
+static int cis_readable(u_long base)
+{
+ cisinfo_t info1, info2;
+ int ret;
+ vs->cis_mem.sys_start = base;
+ vs->cis_mem.sys_stop = base+vs->cap.map_size-1;
+ vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size);
+ ret = validate_cis(vs->clients, &info1);
+ /* invalidate mapping and CIS cache */
+ bus_iounmap(vs->cap.bus, vs->cis_virt); vs->cis_used = 0;
+ if ((ret != 0) || (info1.Chains == 0))
+ return 0;
+ vs->cis_mem.sys_start = base+vs->cap.map_size;
+ vs->cis_mem.sys_stop = base+2*vs->cap.map_size-1;
+ vs->cis_virt = bus_ioremap(vs->cap.bus, base+vs->cap.map_size,
+ vs->cap.map_size);
+ ret = validate_cis(vs->clients, &info2);
+ bus_iounmap(vs->cap.bus, vs->cis_virt); vs->cis_used = 0;
+ return ((ret == 0) && (info1.Chains == info2.Chains));
+}
+
+/* Validation function for simple memory cards */
+static int checksum(u_long base)
+{
+ int i, a, b, d;
+ vs->cis_mem.sys_start = base;
+ vs->cis_mem.sys_stop = base+vs->cap.map_size-1;
+ vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size);
+ vs->cis_mem.card_start = 0;
+ vs->cis_mem.flags = MAP_ACTIVE;
+ vs->ss_entry(vs->sock, SS_SetMemMap, &vs->cis_mem);
+ /* Don't bother checking every word... */
+ a = 0; b = -1;
+ for (i = 0; i < vs->cap.map_size; i += 44) {
+ d = bus_readl(vs->cap.bus, vs->cis_virt+i);
+ a += d; b &= d;
+ }
+ bus_iounmap(vs->cap.bus, vs->cis_virt);
+ return (b == -1) ? -1 : (a>>1);
+}
+
+static int checksum_match(u_long base)
+{
+ int a = checksum(base), b = checksum(base+vs->cap.map_size);
+ return ((a == b) && (a >= 0));
+}
+
+static int setup_cis_mem(socket_info_t *s)
+{
+ if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
+ (s->cis_mem.sys_start == 0)) {
+ int low = !(s->cap.features & SS_CAP_PAGE_REGS);
+ vs = s;
+ validate_mem(cis_readable, checksum_match, low);
+ s->cis_mem.sys_start = 0;
+ vs = NULL;
+ if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size,
+ s->cap.map_size, low, "card services")) {
+ printk(KERN_NOTICE "cs: unable to map card memory!\n");
+ return -1;
+ }
+ s->cis_mem.sys_stop = s->cis_mem.sys_start+s->cap.map_size-1;
+ s->cis_virt = bus_ioremap(s->cap.bus, s->cis_mem.sys_start,
+ s->cap.map_size);
+ }
+ return 0;
+}
+
+void release_cis_mem(socket_info_t *s)
+{
+ if (s->cis_mem.sys_start != 0) {
+ s->cis_mem.flags &= ~MAP_ACTIVE;
+ s->ss_entry(s->sock, SS_SetMemMap, &s->cis_mem);
+ if (!(s->cap.features & SS_CAP_STATIC_MAP))
+ release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
+ bus_iounmap(s->cap.bus, s->cis_virt);
+ s->cis_mem.sys_start = 0;
+ s->cis_virt = NULL;
+ }
+}
+
+/*======================================================================
+
+ This is a wrapper around read_cis_mem, with the same interface,
+ but which caches information, for cards whose CIS may not be
+ readable all the time.
+
+======================================================================*/
+
+static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
+ u_int len, void *ptr)
+{
+ int i, ret;
+ char *caddr;
+
+ if (s->fake_cis) {
+ if (s->fake_cis_len > addr+len)
+ memcpy(ptr, s->fake_cis+addr, len);
+ else
+ memset(ptr, 0xff, len);
+ return;
+ }
+ caddr = s->cis_cache;
+ for (i = 0; i < s->cis_used; i++) {
+ if ((s->cis_table[i].addr == addr) &&
+ (s->cis_table[i].len == len) &&
+ (s->cis_table[i].attr == attr)) break;
+ caddr += s->cis_table[i].len;
+ }
+ if (i < s->cis_used) {
+ memcpy(ptr, caddr, len);
+ return;
+ }
+#ifdef CONFIG_CARDBUS
+ if (s->state & SOCKET_CARDBUS)
+ ret = read_cb_mem(s, 0, attr, addr, len, ptr);
+ else
+#endif
+ ret = read_cis_mem(s, attr, addr, len, ptr);
+ /* Copy data into the cache, if there is room */
+ if ((ret == 0) && (i < MAX_CIS_TABLE) &&
+ (caddr+len < s->cis_cache+MAX_CIS_DATA)) {
+ s->cis_table[i].addr = addr;
+ s->cis_table[i].len = len;
+ s->cis_table[i].attr = attr;
+ s->cis_used++;
+ memcpy(caddr, ptr, len);
+ }
+}
+
+/*======================================================================
+
+ This verifies if the CIS of a card matches what is in the CIS
+ cache.
+
+======================================================================*/
+
+int verify_cis_cache(socket_info_t *s)
+{
+ char *buf, *caddr;
+ int i;
+
+ buf = kmalloc(256, GFP_KERNEL);
+ if (buf == NULL)
+ return -1;
+ caddr = s->cis_cache;
+ for (i = 0; i < s->cis_used; i++) {
+#ifdef CONFIG_CARDBUS
+ if (s->state & SOCKET_CARDBUS)
+ read_cb_mem(s, 0, s->cis_table[i].attr, s->cis_table[i].addr,
+ s->cis_table[i].len, buf);
+ else
+#endif
+ read_cis_mem(s, s->cis_table[i].attr, s->cis_table[i].addr,
+ s->cis_table[i].len, buf);
+ if (memcmp(buf, caddr, s->cis_table[i].len) != 0)
+ break;
+ caddr += s->cis_table[i].len;
+ }
+ kfree(buf);
+ return (i < s->cis_used);
+}
+
+/*======================================================================
+
+ For really bad cards, we provide a facility for uploading a
+ replacement CIS.
+
+======================================================================*/
+
+int replace_cis(client_handle_t handle, cisdump_t *cis)
+{
+ socket_info_t *s;
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+ s = SOCKET(handle);
+ if (s->fake_cis != NULL) {
+ kfree(s->fake_cis);
+ s->fake_cis = NULL;
+ }
+ if (cis->Length > CISTPL_MAX_CIS_SIZE)
+ return CS_BAD_SIZE;
+ s->fake_cis = kmalloc(cis->Length, GFP_KERNEL);
+ if (s->fake_cis == NULL)
+ return CS_OUT_OF_RESOURCE;
+ s->fake_cis_len = cis->Length;
+ memcpy(s->fake_cis, cis->Data, cis->Length);
+ return CS_SUCCESS;
+}
+
+/*======================================================================
+
+ The high-level CIS tuple services
+
+======================================================================*/
+
+typedef struct tuple_flags {
+ u_int link_space:4;
+ u_int has_link:1;
+ u_int mfc_fn:3;
+ u_int space:4;
+} tuple_flags;
+
+#define LINK_SPACE(f) (((tuple_flags *)(&(f)))->link_space)
+#define HAS_LINK(f) (((tuple_flags *)(&(f)))->has_link)
+#define MFC_FN(f) (((tuple_flags *)(&(f)))->mfc_fn)
+#define SPACE(f) (((tuple_flags *)(&(f)))->space)
+
+int get_next_tuple(client_handle_t handle, tuple_t *tuple);
+
+int get_first_tuple(client_handle_t handle, tuple_t *tuple)
+{
+ socket_info_t *s;
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+ s = SOCKET(handle);
+ if (!(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+ tuple->TupleLink = tuple->Flags = 0;
+#ifdef CONFIG_CARDBUS
+ if (s->state & SOCKET_CARDBUS) {
+ u_int ptr;
+ pcibios_read_config_dword(s->cap.cardbus, 0, 0x28, &ptr);
+ tuple->CISOffset = ptr & ~7;
+ SPACE(tuple->Flags) = (ptr & 7);
+ } else
+#endif
+ {
+ /* Assume presence of a LONGLINK_C to address 0 */
+ tuple->CISOffset = tuple->LinkOffset = 0;
+ SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
+ }
+ if (!(s->state & SOCKET_CARDBUS) && (s->functions > 1) &&
+ !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
+ cisdata_t req = tuple->DesiredTuple;
+ tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
+ if (get_next_tuple(handle, tuple) == CS_SUCCESS) {
+ tuple->DesiredTuple = CISTPL_LINKTARGET;
+ if (get_next_tuple(handle, tuple) != CS_SUCCESS)
+ return CS_NO_MORE_ITEMS;
+ } else
+ tuple->CISOffset = tuple->TupleLink = 0;
+ tuple->DesiredTuple = req;
+ }
+ return get_next_tuple(handle, tuple);
+}
+
+static int follow_link(socket_info_t *s, tuple_t *tuple)
+{
+ u_char link[5];
+ u_int ofs;
+
+ if (MFC_FN(tuple->Flags)) {
+ /* Get indirect link from the MFC tuple */
+ read_cis_cache(s, LINK_SPACE(tuple->Flags),
+ tuple->LinkOffset, 5, link);
+ ofs = le32_to_cpu(*(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 (!(s->state & SOCKET_CARDBUS) && 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_cache(s, 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_cache(s, SPACE(tuple->Flags), ofs, 5, link);
+ if ((link[0] != CISTPL_LINKTARGET) || (link[1] < 3) ||
+ (strncmp(link+2, "CIS", 3) != 0))
+ return -1;
+ return ofs;
+}
+
+int get_next_tuple(client_handle_t handle, tuple_t *tuple)
+{
+ socket_info_t *s;
+ u_char link[2], tmp;
+ int ofs, i, attr;
+
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+ s = SOCKET(handle);
+ if (!(s->state & SOCKET_PRESENT))
+ return CS_NO_CARD;
+
+ 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_cache(s, 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(s, tuple)) < 0)
+ return CS_NO_MORE_ITEMS;
+ attr = SPACE(tuple->Flags);
+ read_cis_cache(s, 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_cache(s, 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_cache(s, 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 (handle->Function == BIND_FN_ALL) {
+ /* Follow all the MFC links */
+ read_cis_cache(s, attr, ofs+2, 1, &tmp);
+ MFC_FN(tuple->Flags) = tmp;
+ } else {
+ /* Follow exactly one of the links */
+ MFC_FN(tuple->Flags) = 1;
+ tuple->LinkOffset += handle->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) {
+ DEBUG(1, "cs: overrun in get_next_tuple for socket %d\n",
+ handle->Socket);
+ return CS_NO_MORE_ITEMS;
+ }
+
+ tuple->TupleCode = link[0];
+ tuple->TupleLink = link[1];
+ tuple->CISOffset = ofs + 2;
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+#define _MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+int get_tuple_data(client_handle_t handle, tuple_t *tuple)
+{
+ socket_info_t *s;
+ u_int len;
+
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+
+ s = SOCKET(handle);
+
+ if (tuple->TupleLink < tuple->TupleOffset)
+ return CS_NO_MORE_ITEMS;
+ len = tuple->TupleLink - tuple->TupleOffset;
+ tuple->TupleDataLen = tuple->TupleLink;
+ if (len == 0)
+ return CS_SUCCESS;
+ read_cis_cache(s, SPACE(tuple->Flags),
+ tuple->CISOffset + tuple->TupleOffset,
+ _MIN(len, tuple->TupleDataMax), tuple->TupleData);
+ return CS_SUCCESS;
+}
+
+/*======================================================================
+
+ Parsing routines for individual tuples
+
+======================================================================*/
+
+static int parse_device(tuple_t *tuple, cistpl_device_t *device)
+{
+ int i;
+ u_char scale;
+ u_char *p, *q;
+
+ p = (u_char *)tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+
+ device->ndev = 0;
+ for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
+
+ if (*p == 0xff) break;
+ device->dev[i].type = (*p >> 4);
+ device->dev[i].wp = (*p & 0x08) ? 1 : 0;
+ switch (*p & 0x07) {
+ case 0: device->dev[i].speed = 0; break;
+ case 1: device->dev[i].speed = 250; break;
+ case 2: device->dev[i].speed = 200; break;
+ case 3: device->dev[i].speed = 150; break;
+ case 4: device->dev[i].speed = 100; break;
+ case 7:
+ if (++p == q) return CS_BAD_TUPLE;
+ device->dev[i].speed = SPEED_CVT(*p);
+ while (*p & 0x80)
+ if (++p == q) return CS_BAD_TUPLE;
+ break;
+ default:
+ return CS_BAD_TUPLE;
+ }
+
+ if (++p == q) return CS_BAD_TUPLE;
+ if (*p == 0xff) break;
+ scale = *p & 7;
+ if (scale == 7) return CS_BAD_TUPLE;
+ device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
+ device->ndev++;
+ if (++p == q) break;
+ }
+
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
+{
+ u_char *p;
+ if (tuple->TupleDataLen < 5)
+ return CS_BAD_TUPLE;
+ p = (u_char *)tuple->TupleData;
+ csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2;
+ csum->len = le16_to_cpu(*(u_short *)(p + 2));
+ csum->sum = *(p+4);
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
+{
+ if (tuple->TupleDataLen < 4)
+ return CS_BAD_TUPLE;
+ link->addr = le32_to_cpu(*(u_int *)tuple->TupleData);
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_longlink_mfc(tuple_t *tuple,
+ cistpl_longlink_mfc_t *link)
+{
+ u_char *p;
+ int i;
+
+ p = (u_char *)tuple->TupleData;
+
+ link->nfn = *p; p++;
+ if (tuple->TupleDataLen <= link->nfn*5)
+ return CS_BAD_TUPLE;
+ for (i = 0; i < link->nfn; i++) {
+ link->fn[i].space = *p; p++;
+ link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4;
+ }
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_strings(u_char *p, u_char *q, int max,
+ char *s, u_char *ofs, u_char *found)
+{
+ int i, j, ns;
+
+ if (p == q) return CS_BAD_TUPLE;
+ ns = 0; j = 0;
+ for (i = 0; i < max; i++) {
+ if (*p == 0xff) break;
+ ofs[i] = j;
+ ns++;
+ for (;;) {
+ s[j++] = (*p == 0xff) ? '\0' : *p;
+ if ((*p == '\0') || (*p == 0xff)) break;
+ if (++p == q) return CS_BAD_TUPLE;
+ }
+ if ((*p == 0xff) || (++p == q)) break;
+ }
+ if (found) {
+ *found = ns;
+ return CS_SUCCESS;
+ } else {
+ return (ns == max) ? CS_SUCCESS : CS_BAD_TUPLE;
+ }
+}
+
+/*====================================================================*/
+
+static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
+{
+ u_char *p, *q;
+
+ p = (u_char *)tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+
+ vers_1->major = *p; p++;
+ vers_1->minor = *p; p++;
+ if (p >= q) return CS_BAD_TUPLE;
+
+ return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
+ vers_1->str, vers_1->ofs, &vers_1->ns);
+}
+
+/*====================================================================*/
+
+static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr)
+{
+ u_char *p, *q;
+
+ p = (u_char *)tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+
+ return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
+ altstr->str, altstr->ofs, &altstr->ns);
+}
+
+/*====================================================================*/
+
+static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
+{
+ u_char *p, *q;
+ int nid;
+
+ p = (u_char *)tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+
+ for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) {
+ if (p > q-2) break;
+ jedec->id[nid].mfr = p[0];
+ jedec->id[nid].info = p[1];
+ p += 2;
+ }
+ jedec->nid = nid;
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
+{
+ u_short *p;
+ if (tuple->TupleDataLen < 4)
+ return CS_BAD_TUPLE;
+ p = (u_short *)tuple->TupleData;
+ m->manf = le16_to_cpu(p[0]);
+ m->card = le16_to_cpu(p[1]);
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
+{
+ u_char *p;
+ if (tuple->TupleDataLen < 2)
+ return CS_BAD_TUPLE;
+ p = (u_char *)tuple->TupleData;
+ f->func = p[0];
+ f->sysinit = p[1];
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
+{
+ u_char *p;
+ int i;
+ if (tuple->TupleDataLen < 1)
+ return CS_BAD_TUPLE;
+ p = (u_char *)tuple->TupleData;
+ f->type = p[0];
+ for (i = 1; i < tuple->TupleDataLen; i++)
+ f->data[i-1] = p[i];
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_config(tuple_t *tuple, cistpl_config_t *config)
+{
+ int rasz, rmsz, i;
+ u_char *p;
+
+ p = (u_char *)tuple->TupleData;
+ rasz = *p & 0x03;
+ rmsz = (*p & 0x3c) >> 2;
+ if (tuple->TupleDataLen < rasz+rmsz+4)
+ return CS_BAD_TUPLE;
+ config->last_idx = *(++p);
+ p++;
+ config->base = 0;
+ for (i = 0; i <= rasz; i++)
+ config->base += p[i] << (8*i);
+ p += rasz+1;
+ for (i = 0; i < 4; i++)
+ config->rmask[i] = 0;
+ for (i = 0; i <= rmsz; i++)
+ config->rmask[i>>2] += p[i] << (8*(i%4));
+ config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
+ return CS_SUCCESS;
+}
+
+/*======================================================================
+
+ The following routines are all used to parse the nightmarish
+ config table entries.
+
+======================================================================*/
+
+static u_char *parse_power(u_char *p, u_char *q,
+ cistpl_power_t *pwr)
+{
+ int i;
+ u_int scale;
+
+ if (p == q) return NULL;
+ pwr->present = *p;
+ pwr->flags = 0;
+ p++;
+ for (i = 0; i < 7; i++)
+ if (pwr->present & (1<<i)) {
+ if (p == q) return NULL;
+ pwr->param[i] = POWER_CVT(*p);
+ scale = POWER_SCALE(*p);
+ while (*p & 0x80) {
+ if (++p == q) return NULL;
+ if ((*p & 0x7f) < 100)
+ pwr->param[i] += (*p & 0x7f) * scale / 100;
+ else if (*p == 0x7d)
+ pwr->flags |= CISTPL_POWER_HIGHZ_OK;
+ else if (*p == 0x7e)
+ pwr->param[i] = 0;
+ else if (*p == 0x7f)
+ pwr->flags |= CISTPL_POWER_HIGHZ_REQ;
+ else
+ return NULL;
+ }
+ p++;
+ }
+ return p;
+}
+
+/*====================================================================*/
+
+static u_char *parse_timing(u_char *p, u_char *q,
+ cistpl_timing_t *timing)
+{
+ u_char scale;
+
+ if (p == q) return NULL;
+ scale = *p;
+ if ((scale & 3) != 3) {
+ if (++p == q) return NULL;
+ timing->wait = SPEED_CVT(*p);
+ timing->waitscale = exponent[scale & 3];
+ } else
+ timing->wait = 0;
+ scale >>= 2;
+ if ((scale & 7) != 7) {
+ if (++p == q) return NULL;
+ timing->ready = SPEED_CVT(*p);
+ timing->rdyscale = exponent[scale & 7];
+ } else
+ timing->ready = 0;
+ scale >>= 3;
+ if (scale != 7) {
+ if (++p == q) return NULL;
+ timing->reserved = SPEED_CVT(*p);
+ timing->rsvscale = exponent[scale];
+ } else
+ timing->reserved = 0;
+ p++;
+ return p;
+}
+
+/*====================================================================*/
+
+static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io)
+{
+ int i, j, bsz, lsz;
+
+ if (p == q) return NULL;
+ io->flags = *p;
+
+ if (!(*p & 0x80)) {
+ io->nwin = 1;
+ io->win[0].base = 0;
+ io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK));
+ return p+1;
+ }
+
+ if (++p == q) return NULL;
+ io->nwin = (*p & 0x0f) + 1;
+ bsz = (*p & 0x30) >> 4;
+ if (bsz == 3) bsz++;
+ lsz = (*p & 0xc0) >> 6;
+ if (lsz == 3) lsz++;
+ p++;
+
+ for (i = 0; i < io->nwin; i++) {
+ io->win[i].base = 0;
+ io->win[i].len = 1;
+ for (j = 0; j < bsz; j++, p++) {
+ if (p == q) return NULL;
+ io->win[i].base += *p << (j*8);
+ }
+ for (j = 0; j < lsz; j++, p++) {
+ if (p == q) return NULL;
+ io->win[i].len += *p << (j*8);
+ }
+ }
+ return p;
+}
+
+/*====================================================================*/
+
+static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
+{
+ int i, j, asz, lsz, has_ha;
+ u_int len, ca, ha;
+
+ if (p == q) return NULL;
+
+ mem->nwin = (*p & 0x07) + 1;
+ lsz = (*p & 0x18) >> 3;
+ asz = (*p & 0x60) >> 5;
+ has_ha = (*p & 0x80);
+ if (++p == q) return NULL;
+
+ for (i = 0; i < mem->nwin; i++) {
+ len = ca = ha = 0;
+ for (j = 0; j < lsz; j++, p++) {
+ if (p == q) return NULL;
+ len += *p << (j*8);
+ }
+ for (j = 0; j < asz; j++, p++) {
+ if (p == q) return NULL;
+ ca += *p << (j*8);
+ }
+ if (has_ha)
+ for (j = 0; j < asz; j++, p++) {
+ if (p == q) return NULL;
+ ha += *p << (j*8);
+ }
+ mem->win[i].len = len << 8;
+ mem->win[i].card_addr = ca << 8;
+ mem->win[i].host_addr = ha << 8;
+ }
+ return p;
+}
+
+/*====================================================================*/
+
+static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
+{
+ if (p == q) return NULL;
+ irq->IRQInfo1 = *p; p++;
+ if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
+ if (p+2 > q) return NULL;
+ irq->IRQInfo2 = (p[1]<<8) + p[0];
+ p += 2;
+ }
+ return p;
+}
+
+/*====================================================================*/
+
+static int parse_cftable_entry(tuple_t *tuple,
+ cistpl_cftable_entry_t *entry)
+{
+ u_char *p, *q, features;
+
+ p = tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+ entry->index = *p & 0x3f;
+ entry->flags = 0;
+ if (*p & 0x40)
+ entry->flags |= CISTPL_CFTABLE_DEFAULT;
+ if (*p & 0x80) {
+ if (++p == q) return CS_BAD_TUPLE;
+ if (*p & 0x10)
+ entry->flags |= CISTPL_CFTABLE_BVDS;
+ if (*p & 0x20)
+ entry->flags |= CISTPL_CFTABLE_WP;
+ if (*p & 0x40)
+ entry->flags |= CISTPL_CFTABLE_RDYBSY;
+ if (*p & 0x80)
+ entry->flags |= CISTPL_CFTABLE_MWAIT;
+ entry->interface = *p & 0x0f;
+ } else
+ entry->interface = 0;
+
+ /* Process optional features */
+ if (++p == q) return CS_BAD_TUPLE;
+ features = *p; p++;
+
+ /* Power options */
+ if ((features & 3) > 0) {
+ p = parse_power(p, q, &entry->vcc);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else
+ entry->vcc.present = 0;
+ if ((features & 3) > 1) {
+ p = parse_power(p, q, &entry->vpp1);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else
+ entry->vpp1.present = 0;
+ if ((features & 3) > 2) {
+ p = parse_power(p, q, &entry->vpp2);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else
+ entry->vpp2.present = 0;
+
+ /* Timing options */
+ if (features & 0x04) {
+ p = parse_timing(p, q, &entry->timing);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else {
+ entry->timing.wait = 0;
+ entry->timing.ready = 0;
+ entry->timing.reserved = 0;
+ }
+
+ /* I/O window options */
+ if (features & 0x08) {
+ p = parse_io(p, q, &entry->io);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else
+ entry->io.nwin = 0;
+
+ /* Interrupt options */
+ if (features & 0x10) {
+ p = parse_irq(p, q, &entry->irq);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else
+ entry->irq.IRQInfo1 = 0;
+
+ switch (features & 0x60) {
+ case 0x00:
+ entry->mem.nwin = 0;
+ break;
+ case 0x20:
+ entry->mem.nwin = 1;
+ entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
+ entry->mem.win[0].card_addr = 0;
+ entry->mem.win[0].host_addr = 0;
+ p += 2;
+ if (p > q) return CS_BAD_TUPLE;
+ break;
+ case 0x40:
+ entry->mem.nwin = 1;
+ entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
+ entry->mem.win[0].card_addr =
+ le16_to_cpu(*(u_short *)(p+2)) << 8;
+ entry->mem.win[0].host_addr = 0;
+ p += 4;
+ if (p > q) return CS_BAD_TUPLE;
+ break;
+ case 0x60:
+ p = parse_mem(p, q, &entry->mem);
+ if (p == NULL) return CS_BAD_TUPLE;
+ break;
+ }
+
+ /* Misc features */
+ if (features & 0x80) {
+ if (p == q) return CS_BAD_TUPLE;
+ entry->flags |= (*p << 8);
+ while (*p & 0x80)
+ if (++p == q) return CS_BAD_TUPLE;
+ p++;
+ }
+
+ entry->subtuples = q-p;
+
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+#ifdef CONFIG_CARDBUS
+
+static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
+{
+ u_char *p;
+ if (tuple->TupleDataLen < 6)
+ return CS_BAD_TUPLE;
+ p = (u_char *)tuple->TupleData;
+ bar->attr = *p;
+ p += 2;
+ bar->size = le32_to_cpu(*(u_int *)p);
+ return CS_SUCCESS;
+}
+
+static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
+{
+ u_char *p;
+
+ p = (u_char *)tuple->TupleData;
+ if ((*p != 3) || (tuple->TupleDataLen < 6))
+ return CS_BAD_TUPLE;
+ config->last_idx = *(++p);
+ p++;
+ config->base = le32_to_cpu(*(u_int *)p);
+ config->subtuples = tuple->TupleDataLen - 6;
+ return CS_SUCCESS;
+}
+
+static int parse_cftable_entry_cb(tuple_t *tuple,
+ cistpl_cftable_entry_cb_t *entry)
+{
+ u_char *p, *q, features;
+
+ p = tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+ entry->index = *p & 0x3f;
+ entry->flags = 0;
+ if (*p & 0x40)
+ entry->flags |= CISTPL_CFTABLE_DEFAULT;
+
+ /* Process optional features */
+ if (++p == q) return CS_BAD_TUPLE;
+ features = *p; p++;
+
+ /* Power options */
+ if ((features & 3) > 0) {
+ p = parse_power(p, q, &entry->vcc);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else
+ entry->vcc.present = 0;
+ if ((features & 3) > 1) {
+ p = parse_power(p, q, &entry->vpp1);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else
+ entry->vpp1.present = 0;
+ if ((features & 3) > 2) {
+ p = parse_power(p, q, &entry->vpp2);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else
+ entry->vpp2.present = 0;
+
+ /* I/O window options */
+ if (features & 0x08) {
+ if (p == q) return CS_BAD_TUPLE;
+ entry->io = *p; p++;
+ } else
+ entry->io = 0;
+
+ /* Interrupt options */
+ if (features & 0x10) {
+ p = parse_irq(p, q, &entry->irq);
+ if (p == NULL) return CS_BAD_TUPLE;
+ } else
+ entry->irq.IRQInfo1 = 0;
+
+ if (features & 0x20) {
+ if (p == q) return CS_BAD_TUPLE;
+ entry->mem = *p; p++;
+ } else
+ entry->mem = 0;
+
+ /* Misc features */
+ if (features & 0x80) {
+ if (p == q) return CS_BAD_TUPLE;
+ entry->flags |= (*p << 8);
+ if (*p & 0x80) {
+ if (++p == q) return CS_BAD_TUPLE;
+ entry->flags |= (*p << 16);
+ }
+ while (*p & 0x80)
+ if (++p == q) return CS_BAD_TUPLE;
+ p++;
+ }
+
+ entry->subtuples = q-p;
+
+ return CS_SUCCESS;
+}
+
+#endif
+
+/*====================================================================*/
+
+static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
+{
+ u_char *p, *q;
+ int n;
+
+ p = (u_char *)tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+
+ for (n = 0; n < CISTPL_MAX_DEVICES; n++) {
+ if (p > q-6) break;
+ geo->geo[n].buswidth = p[0];
+ geo->geo[n].erase_block = 1 << (p[1]-1);
+ geo->geo[n].read_block = 1 << (p[2]-1);
+ geo->geo[n].write_block = 1 << (p[3]-1);
+ geo->geo[n].partition = 1 << (p[4]-1);
+ geo->geo[n].interleave = 1 << (p[5]-1);
+ p += 6;
+ }
+ geo->ngeo = n;
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
+{
+ u_char *p, *q;
+
+ if (tuple->TupleDataLen < 10)
+ return CS_BAD_TUPLE;
+
+ p = tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+
+ v2->vers = p[0];
+ v2->comply = p[1];
+ v2->dindex = le16_to_cpu(*(u_short *)(p+2));
+ v2->vspec8 = p[6];
+ v2->vspec9 = p[7];
+ v2->nhdr = p[8];
+ p += 9;
+ return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);
+}
+
+/*====================================================================*/
+
+static int parse_org(tuple_t *tuple, cistpl_org_t *org)
+{
+ u_char *p, *q;
+ int i;
+
+ p = tuple->TupleData;
+ q = p + tuple->TupleDataLen;
+ if (p == q) return CS_BAD_TUPLE;
+ org->data_org = *p;
+ if (++p == q) return CS_BAD_TUPLE;
+ for (i = 0; i < 30; i++) {
+ org->desc[i] = *p;
+ if (*p == '\0') break;
+ if (++p == q) return CS_BAD_TUPLE;
+ }
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
+{
+ u_char *p;
+
+ if (tuple->TupleDataLen < 10)
+ return CS_BAD_TUPLE;
+
+ p = tuple->TupleData;
+
+ fmt->type = p[0];
+ fmt->edc = p[1];
+ fmt->offset = le32_to_cpu(*(u_int *)(p+2));
+ fmt->length = le32_to_cpu(*(u_int *)(p+6));
+
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+int parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+{
+ int ret = CS_SUCCESS;
+
+ if (tuple->TupleDataLen > tuple->TupleDataMax)
+ return CS_BAD_TUPLE;
+ switch (tuple->TupleCode) {
+ case CISTPL_DEVICE:
+ case CISTPL_DEVICE_A:
+ ret = parse_device(tuple, &parse->device);
+ break;
+#ifdef CONFIG_CARDBUS
+ case CISTPL_BAR:
+ ret = parse_bar(tuple, &parse->bar);
+ break;
+ case CISTPL_CONFIG_CB:
+ ret = parse_config_cb(tuple, &parse->config);
+ break;
+ case CISTPL_CFTABLE_ENTRY_CB:
+ ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
+ break;
+#endif
+ case CISTPL_CHECKSUM:
+ ret = parse_checksum(tuple, &parse->checksum);
+ break;
+ case CISTPL_LONGLINK_A:
+ case CISTPL_LONGLINK_C:
+ ret = parse_longlink(tuple, &parse->longlink);
+ break;
+ case CISTPL_LONGLINK_MFC:
+ ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
+ break;
+ case CISTPL_VERS_1:
+ ret = parse_vers_1(tuple, &parse->version_1);
+ break;
+ case CISTPL_ALTSTR:
+ ret = parse_altstr(tuple, &parse->altstr);
+ break;
+ case CISTPL_JEDEC_A:
+ case CISTPL_JEDEC_C:
+ ret = parse_jedec(tuple, &parse->jedec);
+ break;
+ case CISTPL_MANFID:
+ ret = parse_manfid(tuple, &parse->manfid);
+ break;
+ case CISTPL_FUNCID:
+ ret = parse_funcid(tuple, &parse->funcid);
+ break;
+ case CISTPL_FUNCE:
+ ret = parse_funce(tuple, &parse->funce);
+ break;
+ case CISTPL_CONFIG:
+ ret = parse_config(tuple, &parse->config);
+ break;
+ case CISTPL_CFTABLE_ENTRY:
+ ret = parse_cftable_entry(tuple, &parse->cftable_entry);
+ break;
+ case CISTPL_DEVICE_GEO:
+ case CISTPL_DEVICE_GEO_A:
+ ret = parse_device_geo(tuple, &parse->device_geo);
+ break;
+ case CISTPL_VERS_2:
+ ret = parse_vers_2(tuple, &parse->vers_2);
+ break;
+ case CISTPL_ORG:
+ ret = parse_org(tuple, &parse->org);
+ break;
+ case CISTPL_FORMAT:
+ case CISTPL_FORMAT_A:
+ ret = parse_format(tuple, &parse->format);
+ break;
+ case CISTPL_NO_LINK:
+ case CISTPL_LINKTARGET:
+ ret = CS_SUCCESS;
+ break;
+ default:
+ ret = CS_UNSUPPORTED_FUNCTION;
+ break;
+ }
+ return ret;
+}
+
+/*======================================================================
+
+ This is used internally by Card Services to look up CIS stuff.
+
+======================================================================*/
+
+int read_tuple(client_handle_t handle, cisdata_t code, void *parse)
+{
+ tuple_t tuple;
+ cisdata_t *buf;
+ int ret;
+
+ buf = kmalloc(255, GFP_KERNEL);
+ if (buf == NULL)
+ return CS_OUT_OF_RESOURCE;
+ tuple.DesiredTuple = code;
+ tuple.Attributes = TUPLE_RETURN_COMMON;
+ ret = CardServices(GetFirstTuple, handle, &tuple, NULL);
+ if (ret != CS_SUCCESS) goto done;
+ tuple.TupleData = buf;
+ tuple.TupleOffset = 0;
+ tuple.TupleDataMax = 255;
+ ret = CardServices(GetTupleData, handle, &tuple, NULL);
+ if (ret != CS_SUCCESS) goto done;
+ ret = CardServices(ParseTuple, handle, &tuple, parse);
+done:
+ kfree(buf);
+ return ret;
+}
+
+/*======================================================================
+
+ This tries to determine if a card has a sensible CIS. It returns
+ the number of tuples in the CIS, or 0 if the CIS looks bad. The
+ checks include making sure several critical tuples are present and
+ valid; seeing if the total number of tuples is reasonable; and
+ looking for tuples that use reserved codes.
+
+======================================================================*/
+
+int validate_cis(client_handle_t handle, cisinfo_t *info)
+{
+ tuple_t tuple;
+ cisparse_t *p;
+ int ret, reserved, dev_ok = 0, ident_ok = 0;
+
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL)
+ return CS_OUT_OF_RESOURCE;
+
+ info->Chains = reserved = 0;
+ tuple.DesiredTuple = RETURN_FIRST_TUPLE;
+ tuple.Attributes = TUPLE_RETURN_COMMON;
+ ret = get_first_tuple(handle, &tuple);
+ if (ret != CS_SUCCESS)
+ goto done;
+
+ /* First tuple should be DEVICE; we should really have either that
+ or a CFTABLE_ENTRY of some sort */
+ if ((tuple.TupleCode == CISTPL_DEVICE) ||
+ (read_tuple(handle, CISTPL_CFTABLE_ENTRY, p) == CS_SUCCESS) ||
+ (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, p) == CS_SUCCESS))
+ dev_ok++;
+
+ /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
+ tuple, for card identification. Certain old D-Link and Linksys
+ cards have only a broken VERS_2 tuple; hence the bogus test. */
+ if ((read_tuple(handle, CISTPL_MANFID, p) == CS_SUCCESS) ||
+ (read_tuple(handle, CISTPL_VERS_1, p) == CS_SUCCESS) ||
+ (read_tuple(handle, CISTPL_VERS_2, p) != CS_NO_MORE_ITEMS))
+ ident_ok++;
+
+ if (!dev_ok && !ident_ok)
+ goto done;
+
+ for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) {
+ ret = get_next_tuple(handle, &tuple);
+ if (ret != CS_SUCCESS) break;
+ if (((tuple.TupleCode > 0x23) && (tuple.TupleCode < 0x40)) ||
+ ((tuple.TupleCode > 0x47) && (tuple.TupleCode < 0x80)) ||
+ ((tuple.TupleCode > 0x90) && (tuple.TupleCode < 0xff)))
+ reserved++;
+ }
+ if ((info->Chains == MAX_TUPLES) || (reserved > 5) ||
+ ((!dev_ok || !ident_ok) && (info->Chains > 10)))
+ info->Chains = 0;
+
+done:
+ kfree(p);
+ return CS_SUCCESS;
+}
+
diff --git a/dump_cis.c b/dump_cis.c
new file mode 100644
index 0000000..aa5cd9f
--- /dev/null
+++ b/dump_cis.c
@@ -0,0 +1,1102 @@
+/*======================================================================
+
+ PC Card CIS dump utility
+
+ dump_cis.c 1.63 2001/11/30 23:10:17
+
+ The contents of this file are subject to the Mozilla Public
+ License Version 1.1 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS
+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ rights and limitations under the License.
+
+ 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.
+
+ Alternatively, the contents of this file may be used under the
+ terms of the GNU General Public License version 2 (the "GPL"), in
+ which case the provisions of the GPL are applicable instead of the
+ above. If you wish to allow the use of your version of this file
+ only under the terms of the GPL and not to allow others to use
+ your version of this file under the MPL, indicate your decision
+ by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL. If you do not delete
+ the provisions above, a recipient may use your version of this
+ file under either the MPL or the GPL.
+
+======================================================================*/
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+static int verbose = 0;
+static char indent[10] = " ";
+
+/*====================================================================*/
+
+static int major = 0;
+
+static int lookup_dev(char *name)
+{
+ FILE *f;
+ int n;
+ char s[32], t[32];
+
+ f = fopen("/proc/devices", "r");
+ if (f == NULL)
+ return -1;
+ while (fgets(s, 32, f) != NULL) {
+ if (sscanf(s, "%d %s", &n, t) == 2)
+ if (strcmp(name, t) == 0)
+ break;
+ }
+ fclose(f);
+ if (strcmp(name, t) == 0)
+ return n;
+ else
+ return -1;
+}
+
+/*====================================================================*/
+
+static int open_sock(int sock)
+{
+ static char *paths[] = {
+ "/var/lib/pcmcia", "/var/run", "/dev", "/tmp", NULL
+ };
+ int fd;
+ char **p, fn[64];
+ dev_t dev = (major<<8) + sock;
+
+ for (p = paths; *p; p++) {
+ sprintf(fn, "%s/dc%d", *p, getpid());
+ if (mknod(fn, (S_IFCHR|S_IREAD|S_IWRITE), dev) == 0) {
+ fd = open(fn, O_RDONLY);
+ unlink(fn);
+ if (fd >= 0)
+ return fd;
+ if (errno == ENODEV) break;
+ }
+ }
+ return -1;
+} /* open_sock */
+
+/*====================================================================*/
+
+static void print_tuple(tuple_parse_t *tup)
+{
+ int i;
+ printf("%soffset 0x%2.2x, tuple 0x%2.2x, link 0x%2.2x\n",
+ indent, tup->tuple.CISOffset, tup->tuple.TupleCode,
+ tup->tuple.TupleLink);
+ for (i = 0; i < tup->tuple.TupleDataLen; i++) {
+ if ((i % 16) == 0) printf("%s ", indent);
+ printf("%2.2x ", (u_char)tup->data[i]);
+ if ((i % 16) == 15) putchar('\n');
+ }
+ if ((i % 16) != 0) putchar('\n');
+}
+
+/*====================================================================*/
+
+static void print_funcid(cistpl_funcid_t *fn)
+{
+ printf("%sfuncid ", indent);
+ switch (fn->func) {
+ case CISTPL_FUNCID_MULTI:
+ printf("multi_function"); break;
+ case CISTPL_FUNCID_MEMORY:
+ printf("memory_card"); break;
+ case CISTPL_FUNCID_SERIAL:
+ printf("serial_port"); break;
+ case CISTPL_FUNCID_PARALLEL:
+ printf("parallel_port"); break;
+ case CISTPL_FUNCID_FIXED:
+ printf("fixed_disk"); break;
+ case CISTPL_FUNCID_VIDEO:
+ printf("video_adapter"); break;
+ case CISTPL_FUNCID_NETWORK:
+ printf("network_adapter"); break;
+ case CISTPL_FUNCID_AIMS:
+ printf("aims_card"); break;
+ case CISTPL_FUNCID_SCSI:
+ printf("scsi_adapter"); break;
+ default:
+ printf("unknown"); break;
+ }
+ if (fn->sysinit & CISTPL_SYSINIT_POST)
+ printf(" [post]");
+ if (fn->sysinit & CISTPL_SYSINIT_ROM)
+ printf(" [rom]");
+ putchar('\n');
+}
+
+/*====================================================================*/
+
+static void print_size(u_int size)
+{
+ if (size < 1024)
+ printf("%ub", size);
+ else if (size < 1024*1024)
+ printf("%ukb", size/1024);
+ else
+ printf("%umb", size/(1024*1024));
+}
+
+static void print_unit(u_int v, char *unit, char tag)
+{
+ int n;
+ for (n = 0; (v % 1000) == 0; n++) v /= 1000;
+ printf("%u", v);
+ if (n < strlen(unit)) putchar(unit[n]);
+ putchar(tag);
+}
+
+static void print_time(u_int tm, u_long scale)
+{
+ print_unit(tm * scale, "num", 's');
+}
+
+static void print_volt(u_int vi)
+{
+ print_unit(vi * 10, "um", 'V');
+}
+
+static void print_current(u_int ii)
+{
+ print_unit(ii / 10, "um", 'A');
+}
+
+static void print_speed(u_int b)
+{
+ if (b < 1000)
+ printf("%u bits/sec", b);
+ else if (b < 1000000)
+ printf("%u kb/sec", b/1000);
+ else
+ printf("%u mb/sec", b/1000000);
+}
+
+/*====================================================================*/
+
+static const char *dtype[] = {
+ "NULL", "ROM", "OTPROM", "EPROM", "EEPROM", "FLASH", "SRAM",
+ "DRAM", "rsvd", "rsvd", "rsvd", "rsvd", "rsvd", "fn_specific",
+ "extended", "rsvd"
+};
+
+static void print_device(cistpl_device_t *dev)
+{
+ int i;
+ for (i = 0; i < dev->ndev; i++) {
+ printf("%s %s ", indent, dtype[dev->dev[i].type]);
+ printf("%uns, ", dev->dev[i].speed);
+ print_size(dev->dev[i].size);
+ putchar('\n');
+ }
+ if (dev->ndev == 0)
+ printf("%s no_info\n", indent);
+}
+
+/*====================================================================*/
+
+static void print_power(char *tag, cistpl_power_t *power)
+{
+ int i, n;
+ for (i = n = 0; i < 8; i++)
+ if (power->present & (1<<i)) n++;
+ i = 0;
+ printf("%s %s", indent, tag);
+ if (power->present & (1<<CISTPL_POWER_VNOM)) {
+ printf(" Vnom "); i++;
+ print_volt(power->param[CISTPL_POWER_VNOM]);
+ }
+ if (power->present & (1<<CISTPL_POWER_VMIN)) {
+ printf(" Vmin "); i++;
+ print_volt(power->param[CISTPL_POWER_VMIN]);
+ }
+ if (power->present & (1<<CISTPL_POWER_VMAX)) {
+ printf(" Vmax "); i++;
+ print_volt(power->param[CISTPL_POWER_VMAX]);
+ }
+ if (power->present & (1<<CISTPL_POWER_ISTATIC)) {
+ printf(" Istatic "); i++;
+ print_current(power->param[CISTPL_POWER_ISTATIC]);
+ }
+ if (power->present & (1<<CISTPL_POWER_IAVG)) {
+ if (++i == 5) printf("\n%s ", indent);
+ printf(" Iavg ");
+ print_current(power->param[CISTPL_POWER_IAVG]);
+ }
+ if (power->present & (1<<CISTPL_POWER_IPEAK)) {
+ if (++i == 5) printf("\n%s ", indent);
+ printf(" Ipeak ");
+ print_current(power->param[CISTPL_POWER_IPEAK]);
+ }
+ if (power->present & (1<<CISTPL_POWER_IDOWN)) {
+ if (++i == 5) printf("\n%s ", indent);
+ printf(" Idown ");
+ print_current(power->param[CISTPL_POWER_IDOWN]);
+ }
+ if (power->flags & CISTPL_POWER_HIGHZ_OK) {
+ if (++i == 5) printf("\n%s ", indent);
+ printf(" [highz OK]");
+ }
+ if (power->flags & CISTPL_POWER_HIGHZ_REQ) {
+ printf(" [highz]");
+ }
+ putchar('\n');
+}
+
+/*====================================================================*/
+
+static void print_cftable_entry(cistpl_cftable_entry_t *entry)
+{
+ int i;
+
+ printf("%scftable_entry 0x%2.2x%s\n", indent, entry->index,
+ (entry->flags & CISTPL_CFTABLE_DEFAULT) ? " [default]" : "");
+
+ if (entry->flags & ~CISTPL_CFTABLE_DEFAULT) {
+ printf("%s ", indent);
+ if (entry->flags & CISTPL_CFTABLE_BVDS)
+ printf(" [bvd]");
+ if (entry->flags & CISTPL_CFTABLE_WP)
+ printf(" [wp]");
+ if (entry->flags & CISTPL_CFTABLE_RDYBSY)
+ printf(" [rdybsy]");
+ if (entry->flags & CISTPL_CFTABLE_MWAIT)
+ printf(" [mwait]");
+ if (entry->flags & CISTPL_CFTABLE_AUDIO)
+ printf(" [audio]");
+ if (entry->flags & CISTPL_CFTABLE_READONLY)
+ printf(" [readonly]");
+ if (entry->flags & CISTPL_CFTABLE_PWRDOWN)
+ printf(" [pwrdown]");
+ putchar('\n');
+ }
+
+ if (entry->vcc.present)
+ print_power("Vcc", &entry->vcc);
+ if (entry->vpp1.present)
+ print_power("Vpp1", &entry->vpp1);
+ if (entry->vpp2.present)
+ print_power("Vpp2", &entry->vpp2);
+
+ if ((entry->timing.wait != 0) || (entry->timing.ready != 0) ||
+ (entry->timing.reserved != 0)) {
+ printf("%s timing", indent);
+ if (entry->timing.wait != 0) {
+ printf(" wait ");
+ print_time(entry->timing.wait, entry->timing.waitscale);
+ }
+ if (entry->timing.ready != 0) {
+ printf(" ready ");
+ print_time(entry->timing.ready, entry->timing.rdyscale);
+ }
+ if (entry->timing.reserved != 0) {
+ printf(" reserved ");
+ print_time(entry->timing.reserved, entry->timing.rsvscale);
+ }
+ putchar('\n');
+ }
+
+ if (entry->io.nwin) {
+ cistpl_io_t *io = &entry->io;
+ printf("%s io", indent);
+ for (i = 0; i < io->nwin; i++) {
+ if (i) putchar(',');
+ printf(" 0x%4.4x-0x%4.4x", io->win[i].base,
+ io->win[i].base+io->win[i].len-1);
+ }
+ printf(" [lines=%d]", io->flags & CISTPL_IO_LINES_MASK);
+ if (io->flags & CISTPL_IO_8BIT) printf(" [8bit]");
+ if (io->flags & CISTPL_IO_16BIT) printf(" [16bit]");
+ if (io->flags & CISTPL_IO_RANGE) printf(" [range]");
+ putchar('\n');
+ }
+
+ if (entry->irq.IRQInfo1) {
+ printf("%s irq ", indent);
+ if (entry->irq.IRQInfo1 & IRQ_INFO2_VALID)
+ printf("mask 0x%04x", entry->irq.IRQInfo2);
+ else
+ printf("%u", entry->irq.IRQInfo1 & IRQ_MASK);
+ if (entry->irq.IRQInfo1 & IRQ_LEVEL_ID) printf(" [level]");
+ if (entry->irq.IRQInfo1 & IRQ_PULSE_ID) printf(" [pulse]");
+ if (entry->irq.IRQInfo1 & IRQ_SHARE_ID) printf(" [shared]");
+ putchar('\n');
+ }
+
+ if (entry->mem.nwin) {
+ cistpl_mem_t *mem = &entry->mem;
+ printf("%s memory", indent);
+ for (i = 0; i < mem->nwin; i++) {
+ if (i) putchar(',');
+ printf(" 0x%4.4x-0x%4.4x @ 0x%4.4x", mem->win[i].card_addr,
+ mem->win[i].card_addr + mem->win[i].len-1,
+ mem->win[i].host_addr);
+ }
+ putchar('\n');
+ }
+
+ if (verbose && entry->subtuples)
+ printf("%s %d bytes in subtuples\n", indent, entry->subtuples);
+
+}
+
+/*====================================================================*/
+
+static void print_cftable_entry_cb(cistpl_cftable_entry_cb_t *entry)
+{
+ int i;
+
+ printf("%scftable_entry_cb 0x%2.2x%s\n", indent, entry->index,
+ (entry->flags & CISTPL_CFTABLE_DEFAULT) ? " [default]" : "");
+
+ if (entry->flags & ~CISTPL_CFTABLE_DEFAULT) {
+ printf("%s ", indent);
+ if (entry->flags & CISTPL_CFTABLE_MASTER)
+ printf(" [master]");
+ if (entry->flags & CISTPL_CFTABLE_INVALIDATE)
+ printf(" [invalidate]");
+ if (entry->flags & CISTPL_CFTABLE_VGA_PALETTE)
+ printf(" [vga palette]");
+ if (entry->flags & CISTPL_CFTABLE_PARITY)
+ printf(" [parity]");
+ if (entry->flags & CISTPL_CFTABLE_WAIT)
+ printf(" [wait]");
+ if (entry->flags & CISTPL_CFTABLE_SERR)
+ printf(" [serr]");
+ if (entry->flags & CISTPL_CFTABLE_FAST_BACK)
+ printf(" [fast back]");
+ if (entry->flags & CISTPL_CFTABLE_BINARY_AUDIO)
+ printf(" [binary audio]");
+ if (entry->flags & CISTPL_CFTABLE_PWM_AUDIO)
+ printf(" [pwm audio]");
+ putchar('\n');
+ }
+
+ if (entry->vcc.present)
+ print_power("Vcc", &entry->vcc);
+ if (entry->vpp1.present)
+ print_power("Vpp1", &entry->vpp1);
+ if (entry->vpp2.present)
+ print_power("Vpp2", &entry->vpp2);
+
+ if (entry->io) {
+ printf("%s io_base", indent);
+ for (i = 0; i < 8; i++)
+ if (entry->io & (1<<i)) printf(" %d", i);
+ putchar('\n');
+ }
+
+ if (entry->irq.IRQInfo1) {
+ printf("%s irq ", indent);
+ if (entry->irq.IRQInfo1 & IRQ_INFO2_VALID)
+ printf("mask 0x%4.4x", entry->irq.IRQInfo2);
+ else
+ printf("%u", entry->irq.IRQInfo1 & IRQ_MASK);
+ if (entry->irq.IRQInfo1 & IRQ_LEVEL_ID) printf(" [level]");
+ if (entry->irq.IRQInfo1 & IRQ_PULSE_ID) printf(" [pulse]");
+ if (entry->irq.IRQInfo1 & IRQ_SHARE_ID) printf(" [shared]");
+ putchar('\n');
+ }
+
+ if (entry->mem) {
+ printf("%s mem_base", indent);
+ for (i = 0; i < 8; i++)
+ if (entry->mem & (1<<i)) printf(" %d", i);
+ putchar('\n');
+ }
+
+ if (verbose && entry->subtuples)
+ printf("%s %d bytes in subtuples\n", indent, entry->subtuples);
+
+}
+
+/*====================================================================*/
+
+static void print_jedec(cistpl_jedec_t *j)
+{
+ int i;
+ for (i = 0; i < j->nid; i++) {
+ if (i != 0) putchar(',');
+ printf(" 0x%02x 0x%02x", j->id[i].mfr, j->id[i].info);
+ }
+ putchar('\n');
+}
+
+/*====================================================================*/
+
+static void print_device_geo(cistpl_device_geo_t *geo)
+{
+ int i;
+ for (i = 0; i < geo->ngeo; i++) {
+ printf("%s width %d erase 0x%x read 0x%x write 0x%x "
+ "partition 0x%x interleave 0x%x\n", indent,
+ geo->geo[i].buswidth, geo->geo[i].erase_block,
+ geo->geo[i].read_block, geo->geo[i].write_block,
+ geo->geo[i].partition, geo->geo[i].interleave);
+ }
+}
+
+/*====================================================================*/
+
+static void print_org(cistpl_org_t *org)
+{
+ printf("%sdata_org ", indent);
+ switch (org->data_org) {
+ case CISTPL_ORG_FS:
+ printf("[filesystem]"); break;
+ case CISTPL_ORG_APPSPEC:
+ printf("[app_specific]"); break;
+ case CISTPL_ORG_XIP:
+ printf("[code]"); break;
+ default:
+ if (org->data_org < 0x80)
+ printf("[reserved]");
+ else
+ printf("[vendor_specific]");
+ }
+ printf(", \"%s\"\n", org->desc);
+}
+
+/*====================================================================*/
+
+static char *data_mod[] = {
+ "Bell103", "V.21", "V.23", "V.22", "Bell212A", "V.22bis",
+ "V.26", "V.26bis", "V.27bis", "V.29", "V.32", "V.32bis",
+ "V.34", "rfu", "rfu", "rfu"
+};
+static char *fax_mod[] = {
+ "V.21-C2", "V.27ter", "V.29", "V.17", "V.33", "rfu", "rfu", "rfu"
+};
+static char *fax_features[] = {
+ "T.3", "T.4", "T.6", "error", "voice", "poll", "file", "passwd"
+};
+static char *cmd_protocol[] = {
+ "AT1", "AT2", "AT3", "MNP_AT", "V.25bis", "V.25A", "DMCL"
+};
+static char *uart[] = {
+ "8250", "16450", "16550", "8251", "8530", "85230"
+};
+static char *parity[] = { "space", "mark", "odd", "even" };
+static char *stop[] = { "1", "1.5", "2" };
+static char *flow[] = {
+ "XON/XOFF xmit", "XON/XOFF rcv", "hw xmit", "hw rcv", "transparent"
+};
+static void print_serial(cistpl_funce_t *funce)
+{
+ cistpl_serial_t *s;
+ cistpl_data_serv_t *ds;
+ cistpl_fax_serv_t *fs;
+ cistpl_modem_cap_t *cp;
+ int i, j;
+
+ switch (funce->type & 0x0f) {
+ case CISTPL_FUNCE_SERIAL_IF:
+ case CISTPL_FUNCE_SERIAL_IF_DATA:
+ case CISTPL_FUNCE_SERIAL_IF_FAX:
+ case CISTPL_FUNCE_SERIAL_IF_VOICE:
+ s = (cistpl_serial_t *)(funce->data);
+ printf("%sserial_interface", indent);
+ if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_IF_DATA)
+ printf("_data");
+ else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_IF_FAX)
+ printf("_fax");
+ else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_IF_VOICE)
+ printf("_voice");
+ printf("\n%s uart %s", indent,
+ (s->uart_type < 6) ? uart[s->uart_type] : "reserved");
+ if (s->uart_cap_0) {
+ printf(" [");
+ for (i = 0; i < 4; i++)
+ if (s->uart_cap_0 & (1<<i))
+ printf("%s%s", parity[i],
+ (s->uart_cap_0 >= (2<<i)) ? "/" : "]");
+ }
+ if (s->uart_cap_1) {
+ int m = s->uart_cap_1 & 0x0f;
+ int n = s->uart_cap_1 >> 4;
+ printf(" [");
+ for (i = 0; i < 4; i++)
+ if (m & (1<<i))
+ printf("%d%s", i+5, (m >= (2<<i)) ? "/" : "");
+ printf("] [");
+ for (i = 0; i < 3; i++)
+ if (n & (1<<i))
+ printf("%s%s", stop[i], (n >= (2<<i)) ? "/" : "]");
+ }
+ printf("\n");
+ break;
+ case CISTPL_FUNCE_SERIAL_CAP:
+ case CISTPL_FUNCE_SERIAL_CAP_DATA:
+ case CISTPL_FUNCE_SERIAL_CAP_FAX:
+ case CISTPL_FUNCE_SERIAL_CAP_VOICE:
+ cp = (cistpl_modem_cap_t *)(funce->data);
+ printf("%sserial_modem_cap", indent);
+ if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_CAP_DATA)
+ printf("_data");
+ else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_CAP_FAX)
+ printf("_fax");
+ else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_CAP_VOICE)
+ printf("_voice");
+ if (cp->flow) {
+ printf("\n%s flow", indent);
+ for (i = 0; i < 5; i++)
+ if (cp->flow & (1<<i))
+ printf(" [%s]", flow[i]);
+ }
+ printf("\n%s cmd_buf %d rcv_buf %d xmit_buf %d\n",
+ indent, 4*(cp->cmd_buf+1),
+ cp->rcv_buf_0+(cp->rcv_buf_1<<8)+(cp->rcv_buf_2<<16),
+ cp->xmit_buf_0+(cp->xmit_buf_1<<8)+(cp->xmit_buf_2<<16));
+ break;
+ case CISTPL_FUNCE_SERIAL_SERV_DATA:
+ ds = (cistpl_data_serv_t *)(funce->data);
+ printf("%sserial_data_services\n", indent);
+ printf("%s data_rate %d\n", indent,
+ 75*((ds->max_data_0<<8) + ds->max_data_1));
+ printf("%s modulation", indent);
+ for (i = j = 0; i < 16; i++)
+ if (((ds->modulation_1<<8) + ds->modulation_0) & (1<<i)) {
+ if (++j % 6 == 0)
+ printf("\n%s ", indent);
+ printf(" [%s]", data_mod[i]);
+ }
+ printf("\n");
+ if (ds->error_control) {
+ printf("%s error_control", indent);
+ if (ds->error_control & CISTPL_SERIAL_ERR_MNP2_4)
+ printf(" [MNP2-4]");
+ if (ds->error_control & CISTPL_SERIAL_ERR_V42_LAPM)
+ printf(" [V.42/LAPM]");
+ printf("\n");
+ }
+ if (ds->compression) {
+ printf("%s compression", indent);
+ if (ds->compression & CISTPL_SERIAL_CMPR_V42BIS)
+ printf(" [V.42bis]");
+ if (ds->compression & CISTPL_SERIAL_CMPR_MNP5)
+ printf(" [MNP5]");
+ printf("\n");
+ }
+ if (ds->cmd_protocol) {
+ printf("%s cmd_protocol", indent);
+ for (i = 0; i < 7; i++)
+ if (ds->cmd_protocol & (1<<i))
+ printf(" [%s]", cmd_protocol[i]);
+ printf("\n");
+ }
+ break;
+
+ case CISTPL_FUNCE_SERIAL_SERV_FAX:
+ fs = (cistpl_fax_serv_t *)(funce->data);
+ printf("%sserial_fax_services [class=%d]\n",
+ indent, funce->type>>4);
+ printf("%s data_rate %d\n", indent,
+ 75*((fs->max_data_0<<8) + fs->max_data_1));
+ printf("%s modulation", indent);
+ for (i = 0; i < 8; i++)
+ if (fs->modulation & (1<<i))
+ printf(" [%s]", fax_mod[i]);
+ printf("\n");
+ if (fs->features_0) {
+ printf("%s features", indent);
+ for (i = 0; i < 8; i++)
+ if (fs->features_0 & (1<<i))
+ printf(" [%s]", fax_features[i]);
+ printf("\n");
+ }
+ break;
+ }
+}
+
+/*====================================================================*/
+
+static void print_fixed(cistpl_funce_t *funce)
+{
+ cistpl_ide_interface_t *i;
+ cistpl_ide_feature_t *f;
+
+ switch (funce->type) {
+ case CISTPL_FUNCE_IDE_IFACE:
+ i = (cistpl_ide_interface_t *)(funce->data);
+ printf("%sdisk_interface ", indent);
+ if (i->interface == CISTPL_IDE_INTERFACE)
+ printf("[ide]\n");
+ else
+ printf("[undefined]\n");
+ break;
+ case CISTPL_FUNCE_IDE_MASTER:
+ case CISTPL_FUNCE_IDE_SLAVE:
+ f = (cistpl_ide_feature_t *)(funce->data);
+ printf("%sdisk_features", indent);
+ if (f->feature1 & CISTPL_IDE_SILICON)
+ printf(" [silicon]");
+ else
+ printf(" [rotating]");
+ if (f->feature1 & CISTPL_IDE_UNIQUE)
+ printf(" [unique]");
+ if (f->feature1 & CISTPL_IDE_DUAL)
+ printf(" [dual]");
+ else
+ printf(" [single]");
+ if (f->feature1 && f->feature2)
+ printf("\n%s ", indent);
+ if (f->feature2 & CISTPL_IDE_HAS_SLEEP)
+ printf(" [sleep]");
+ if (f->feature2 & CISTPL_IDE_HAS_STANDBY)
+ printf(" [standby]");
+ if (f->feature2 & CISTPL_IDE_HAS_IDLE)
+ printf(" [idle]");
+ if (f->feature2 & CISTPL_IDE_LOW_POWER)
+ printf(" [low power]");
+ if (f->feature2 & CISTPL_IDE_REG_INHIBIT)
+ printf(" [reg inhibit]");
+ if (f->feature2 & CISTPL_IDE_HAS_INDEX)
+ printf(" [index]");
+ if (f->feature2 & CISTPL_IDE_IOIS16)
+ printf(" [iois16]");
+ putchar('\n');
+ break;
+ }
+}
+
+/*====================================================================*/
+
+static const char *tech[] = {
+ "undefined", "ARCnet", "ethernet", "token_ring", "localtalk",
+ "FDDI/CDDI", "ATM", "wireless"
+};
+
+static const char *media[] = {
+ "undefined", "unshielded_twisted_pair", "shielded_twisted_pair",
+ "thin_coax", "thick_coax", "fiber", "900_MHz", "2.4_GHz",
+ "5.4_GHz", "diffuse_infrared", "point_to_point_infrared"
+};
+
+static void print_network(cistpl_funce_t *funce)
+{
+ cistpl_lan_tech_t *t;
+ cistpl_lan_speed_t *s;
+ cistpl_lan_media_t *m;
+ cistpl_lan_node_id_t *n;
+ cistpl_lan_connector_t *c;
+ int i;
+
+ switch (funce->type) {
+ case CISTPL_FUNCE_LAN_TECH:
+ t = (cistpl_lan_tech_t *)(funce->data);
+ printf("%slan_technology %s\n", indent, tech[t->tech]);
+ break;
+ case CISTPL_FUNCE_LAN_SPEED:
+ s = (cistpl_lan_speed_t *)(funce->data);
+ printf("%slan_speed ", indent);
+ print_speed(s->speed);
+ putchar('\n');
+ break;
+ case CISTPL_FUNCE_LAN_MEDIA:
+ m = (cistpl_lan_media_t *)(funce->data);
+ printf("%slan_media %s\n", indent, media[m->media]);
+ break;
+ case CISTPL_FUNCE_LAN_NODE_ID:
+ n = (cistpl_lan_node_id_t *)(funce->data);
+ printf("%slan_node_id", indent);
+ for (i = 0; i < n->nb; i++)
+ printf(" %02x", n->id[i]);
+ putchar('\n');
+ break;
+ case CISTPL_FUNCE_LAN_CONNECTOR:
+ c = (cistpl_lan_connector_t *)(funce->data);
+ printf("%slan_connector ", indent);
+ if (c->code == 0)
+ printf("Open connector standard\n");
+ else
+ printf("Closed connector standard\n");
+ break;
+ }
+}
+
+/*====================================================================*/
+
+static void print_vers_1(cistpl_vers_1_t *v1)
+{
+ int i, n;
+ char s[32];
+ sprintf(s, "%svers_1 %d.%d", indent, v1->major, v1->minor);
+ printf("%s", s);
+ n = strlen(s);
+ for (i = 0; i < v1->ns; i++) {
+ if (n + strlen(v1->str + v1->ofs[i]) + 4 > 72) {
+ n = strlen(indent) + 2;
+ printf(",\n%s ", indent);
+ } else {
+ printf(", ");
+ n += 2;
+ }
+ printf("\"%s\"", v1->str + v1->ofs[i]);
+ n += strlen(v1->str + v1->ofs[i]) + 2;
+ }
+ putchar('\n');
+}
+
+/*====================================================================*/
+
+static void print_vers_2(cistpl_vers_2_t *v2)
+{
+ printf("%sversion 0x%2.2x, compliance 0x%2.2x, dindex 0x%4.4x\n",
+ indent, v2->vers, v2->comply, v2->dindex);
+ printf("%s vspec8 0x%2.2x, vspec9 0x%2.2x, nhdr %d\n",
+ indent, v2->vspec8, v2->vspec9, v2->nhdr);
+ printf("%s vendor \"%s\"\n", indent, v2->str+v2->vendor);
+ printf("%s info \"%s\"\n", indent, v2->str+v2->info);
+}
+
+/*====================================================================*/
+
+#ifdef CISTPL_FORMAT_DISK
+static void print_format(cistpl_format_t *fmt)
+{
+ if (fmt->type == CISTPL_FORMAT_DISK)
+ printf("%s [disk]", indent);
+ else if (fmt->type == CISTPL_FORMAT_MEM)
+ printf("%s [memory]", indent);
+ else
+ printf("%s [type 0x%02x]\n", indent, fmt->type);
+ if (fmt->edc == CISTPL_EDC_NONE)
+ printf(" [no edc]");
+ else if (fmt->edc == CISTPL_EDC_CKSUM)
+ printf(" [cksum]");
+ else if (fmt->edc == CISTPL_EDC_CRC)
+ printf(" [crc]");
+ else if (fmt->edc == CISTPL_EDC_PCC)
+ printf(" [pcc]");
+ else
+ printf(" [edc 0x%02x]", fmt->edc);
+ printf(" offset 0x%04x length ", fmt->offset);
+ print_size(fmt->length);
+ putchar('\n');
+}
+#endif
+
+/*====================================================================*/
+
+static void print_config(int code, cistpl_config_t *cfg)
+{
+ printf("%sconfig%s base 0x%4.4x", indent,
+ (code == CISTPL_CONFIG_CB) ? "_cb" : "",
+ cfg->base);
+ if (code == CISTPL_CONFIG)
+ printf(" mask 0x%4.4x", cfg->rmask[0]);
+ printf(" last_index 0x%2.2x\n", cfg->last_idx);
+ if (verbose && cfg->subtuples)
+ printf("%s %d bytes in subtuples\n", indent, cfg->subtuples);
+}
+
+/*====================================================================*/
+
+static int nfn = 0, cur = 0;
+
+static void print_parse(tuple_parse_t *tup)
+{
+ static int func = 0;
+ int i;
+
+ switch (tup->tuple.TupleCode) {
+ case CISTPL_DEVICE:
+ case CISTPL_DEVICE_A:
+ if (tup->tuple.TupleCode == CISTPL_DEVICE)
+ printf("%sdev_info\n", indent);
+ else
+ printf("%sattr_dev_info\n", indent);
+ print_device(&tup->parse.device);
+ break;
+ case CISTPL_CHECKSUM:
+ printf("%schecksum 0x%04x-0x%04x = 0x%02x\n",
+ indent, tup->parse.checksum.addr,
+ tup->parse.checksum.addr+tup->parse.checksum.len-1,
+ tup->parse.checksum.sum);
+ break;
+ case CISTPL_LONGLINK_A:
+ if (verbose)
+ printf("%slong_link_attr 0x%04x\n", indent,
+ tup->parse.longlink.addr);
+ break;
+ case CISTPL_LONGLINK_C:
+ if (verbose)
+ printf("%slong_link 0x%04x\n", indent,
+ tup->parse.longlink.addr);
+ break;
+ case CISTPL_LONGLINK_MFC:
+ if (verbose) {
+ printf("%smfc_long_link\n", indent);
+ for (i = 0; i < tup->parse.longlink_mfc.nfn; i++)
+ printf("%s function %d: %s 0x%04x\n", indent, i,
+ tup->parse.longlink_mfc.fn[i].space ? "common" : "attr",
+ tup->parse.longlink_mfc.fn[i].addr);
+ } else {
+ printf("%smfc {\n", indent);
+ nfn = tup->parse.longlink_mfc.nfn;
+ cur = 0;
+ strcat(indent, " ");
+ }
+ break;
+ case CISTPL_NO_LINK:
+ if (verbose)
+ printf("%sno_long_link\n", indent);
+ break;
+#ifdef CISTPL_INDIRECT
+ case CISTPL_INDIRECT:
+ if (verbose)
+ printf("%sindirect_access\n", indent);
+ break;
+#endif
+ case CISTPL_LINKTARGET:
+ if (verbose)
+ printf("%slink_target\n", indent);
+ else {
+ if (cur++) printf("%s}, {\n", indent+2);
+ }
+ break;
+ case CISTPL_VERS_1:
+ print_vers_1(&tup->parse.version_1);
+ break;
+ case CISTPL_ALTSTR:
+ break;
+ case CISTPL_JEDEC_A:
+ case CISTPL_JEDEC_C:
+ if (tup->tuple.TupleCode == CISTPL_JEDEC_C)
+ printf("%scommon_jedec", indent);
+ else
+ printf("%sattr_jedec", indent);
+ print_jedec(&tup->parse.jedec);
+ break;
+ case CISTPL_DEVICE_GEO:
+ case CISTPL_DEVICE_GEO_A:
+ if (tup->tuple.TupleCode == CISTPL_DEVICE_GEO)
+ printf("%scommon_geometry\n", indent);
+ else
+ printf("%sattr_geometry\n", indent);
+ print_device_geo(&tup->parse.device_geo);
+ break;
+ case CISTPL_MANFID:
+ printf("%smanfid 0x%4.4x, 0x%4.4x\n", indent,
+ tup->parse.manfid.manf, tup->parse.manfid.card);
+ break;
+ case CISTPL_FUNCID:
+ print_funcid(&tup->parse.funcid);
+ func = tup->parse.funcid.func;
+ break;
+ case CISTPL_FUNCE:
+ switch (func) {
+ case CISTPL_FUNCID_SERIAL:
+ print_serial(&tup->parse.funce);
+ break;
+ case CISTPL_FUNCID_FIXED:
+ print_fixed(&tup->parse.funce);
+ break;
+ case CISTPL_FUNCID_NETWORK:
+ print_network(&tup->parse.funce);
+ break;
+ }
+ break;
+ case CISTPL_BAR:
+ printf("%sBAR %d size ", indent,
+ tup->parse.bar.attr & CISTPL_BAR_SPACE);
+ print_size(tup->parse.bar.size);
+ if (tup->parse.bar.attr & CISTPL_BAR_SPACE_IO)
+ printf(" [io]");
+ else
+ printf(" [mem]");
+ if (tup->parse.bar.attr & CISTPL_BAR_PREFETCH)
+ printf(" [prefetch]");
+ if (tup->parse.bar.attr & CISTPL_BAR_CACHEABLE)
+ printf(" [cacheable]");
+ if (tup->parse.bar.attr & CISTPL_BAR_1MEG_MAP)
+ printf(" [<1mb]");
+ putchar('\n');
+ break;
+ case CISTPL_CONFIG:
+ case CISTPL_CONFIG_CB:
+ print_config(tup->tuple.TupleCode, &tup->parse.config);
+ break;
+ case CISTPL_CFTABLE_ENTRY:
+ print_cftable_entry(&tup->parse.cftable_entry);
+ break;
+ case CISTPL_CFTABLE_ENTRY_CB:
+ print_cftable_entry_cb(&tup->parse.cftable_entry_cb);
+ break;
+ case CISTPL_VERS_2:
+ print_vers_2(&tup->parse.vers_2);
+ break;
+ case CISTPL_ORG:
+ print_org(&tup->parse.org);
+ break;
+#ifdef CISTPL_FORMAT_DISK
+ case CISTPL_FORMAT:
+ case CISTPL_FORMAT_A:
+ if (tup->tuple.TupleCode == CISTPL_FORMAT)
+ printf("%scommon_format\n", indent);
+ else
+ printf("%sattr_format\n", indent);
+ print_format(&tup->parse.format);
+#endif
+ }
+}
+
+/*====================================================================*/
+
+static int get_tuple_buf(int fd, ds_ioctl_arg_t *arg, int first)
+{
+ u_int ofs;
+ static int nb = 0;
+ static u_char buf[1024];
+
+ if (first) {
+ nb = read(fd, buf, sizeof(buf));
+ arg->tuple.TupleLink = arg->tuple.CISOffset = 0;
+ }
+ ofs = arg->tuple.CISOffset + arg->tuple.TupleLink;
+ if (ofs >= nb) return -1;
+ arg->tuple.TupleCode = buf[ofs++];
+ arg->tuple.TupleDataLen = arg->tuple.TupleLink = buf[ofs++];
+ arg->tuple.CISOffset = ofs;
+ memcpy(arg->tuple_parse.data, buf+ofs, arg->tuple.TupleLink);
+ return 0;
+}
+
+static int get_tuple(int fd, ds_ioctl_arg_t *arg, int first)
+{
+ int cmd = (first) ? DS_GET_FIRST_TUPLE : DS_GET_NEXT_TUPLE;
+ if (ioctl(fd, cmd, arg) != 0) {
+ if (errno == ENODEV)
+ printf("%sno card\n", indent);
+ else if (errno != ENODATA)
+ printf("%sget tuple: %s\n", indent, strerror(errno));
+ return -1;
+ }
+ if (ioctl(fd, DS_GET_TUPLE_DATA, arg) != 0) {
+ printf("%sget tuple data: %s\n", indent, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+/*====================================================================*/
+
+#define MAX_SOCKS 8
+
+int main(int argc, char *argv[])
+{
+ int i, fd, pfd = -1;
+ ds_ioctl_arg_t arg;
+ int optch, errflg, first;
+ int force = 0;
+ char *infile = NULL;
+
+ errflg = 0;
+ while ((optch = getopt(argc, argv, "fvi:")) != -1) {
+ switch (optch) {
+ case 'f':
+ force = 1; break;
+ case 'v':
+ verbose = 1; break;
+ case 'i':
+ infile = strdup(optarg); break;
+ default:
+ errflg = 1; break;
+ }
+ }
+ if (errflg || (optind < argc)) {
+ fprintf(stderr, "usage: %s [-v] [-f] [-i infile]\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ major = lookup_dev("pcmcia");
+ if (major < 0) {
+ fprintf(stderr, "no pcmcia driver in /proc/devices\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; (i < MAX_SOCKS) && !(i && infile); i++) {
+ nfn = cur = 0;
+ if (infile) {
+ indent[0] = '\0';
+ fd = open(infile, O_RDONLY);
+ if (fd < 0) {
+ perror("open()");
+ return -1;
+ }
+ pfd = open_sock(0);
+ } else {
+ strcpy(indent, " ");
+ fd = pfd = open_sock(i);
+ }
+ if (pfd < 0)
+ break;
+ if (!verbose && (i > 0)) putchar('\n');
+ if (!infile) printf("Socket %d:\n", i);
+
+ if (!force && !infile) {
+ if (ioctl(fd, DS_VALIDATE_CIS, &arg) != 0) {
+ printf("%svalidate CIS: %s\n", indent, strerror(errno));
+ continue;
+ }
+ if (arg.cisinfo.Chains == 0) {
+ printf("%sno CIS present\n", indent);
+ continue;
+ }
+ }
+
+ arg.tuple.TupleDataMax = sizeof(arg.tuple_parse.data);
+ arg.tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON;
+ arg.tuple.DesiredTuple = RETURN_FIRST_TUPLE;
+ arg.tuple.TupleOffset = 0;
+
+ for (first = 1; ; first = 0) {
+ if (infile) {
+ if (get_tuple_buf(fd, &arg, first) != 0) break;
+ } else {
+ if (get_tuple(fd, &arg, first) != 0) break;
+ }
+ if (verbose) print_tuple(&arg.tuple_parse);
+ if (ioctl(pfd, DS_PARSE_TUPLE, &arg) == 0)
+ print_parse(&arg.tuple_parse);
+ else if (errno != ENOSYS)
+ printf("%sparse error: %s\n", indent,
+ strerror(errno));
+ if (verbose) putchar('\n');
+ if (arg.tuple.TupleCode == CISTPL_END)
+ break;
+ }
+
+ if (!verbose && (nfn > 0))
+ printf("%s}\n", indent+2);
+ }
+ if ((i == 0) && (pfd < 0)) {
+ perror("open()");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/lex_cis.l b/lex_cis.l
new file mode 100644
index 0000000..92316aa
--- /dev/null
+++ b/lex_cis.l
@@ -0,0 +1,234 @@
+/* Special state for handling include files */
+%x src
+
+%{
+/*
+ * lex_cis.l 1.15 2001/08/24 12:21:41
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * 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.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#undef src
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <syslog.h>
+#define src 1
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cistpl.h>
+
+#include "pack_cis.h"
+#include "yacc_cis.h"
+
+/* For assembling nice error messages */
+int current_lineno;
+
+static int lex_number(char *);
+static int lex_units(char *, int, int);
+static int lex_float(char *);
+static int lex_string(char *);
+
+%}
+
+int [0-9]+
+hex 0x[0-9a-fA-F]+
+flt [0-9]+\.[0-9]*
+str \"([^"]|\\.)*\"
+
+%%
+
+\n current_lineno++;
+[ \t]* /* skip */ ;
+[ ]*[#;].* /* skip */ ;
+
+funcid return FUNCID;
+mfc return MFC;
+manfid return MANFID;
+vers_1 return VERS_1;
+checksum return CHECKSUM;
+
+common_jedec return CJEDEC;
+attr_jedec return AJEDEC;
+
+dev_info return DEV_INFO;
+attr_dev_info return ATTR_DEV_INFO;
+no_info return NO_INFO;
+NULL return lex_number("0");
+ROM return lex_number("1");
+EPROM return lex_number("3");
+EEPROM return lex_number("4");
+FLASH return lex_number("5");
+SRAM return lex_number("6");
+DRAM return lex_number("7");
+fn_specific return lex_number("13");
+
+config return CONFIG;
+base return BASE;
+mask return MASK;
+last_index return LAST_INDEX;
+\[post\] return POST;
+\[rom\] return ROM;
+
+cftable_entry return CFTABLE;
+\[default\] return DEFAULT;
+\[bvd\] return BVD;
+\[wp\] return WP;
+\[rdybsy\] return RDYBSY;
+\[mwait\] return MWAIT;
+\[audio\] return AUDIO;
+\[readonly\] return READONLY;
+\[pwrdown\] return PWRDOWN;
+
+Vcc return VCC;
+Vpp1 return VPP1;
+Vpp2 return VPP2;
+Vnom return VNOM;
+Vmin return VMIN;
+Vmax return VMAX;
+Istatic return ISTATIC;
+Iavg return IAVG;
+Ipeak return IPEAK;
+Idown return IDOWN;
+
+io return IO;
+memory return MEM;
+\[8bit\] return BIT8;
+\[16bit\] return BIT16;
+\[lines return LINES;
+\[range\] return RANGE;
+
+irq return IRQ_NO;
+\[level\] return LEVEL;
+\[pulse\] return PULSE;
+\[shared\] return SHARED;
+
+timing return TIMING;
+wait return WAIT;
+ready return READY;
+reserved return RESERVED;
+
+multi_function return lex_number("0");
+memory_card return lex_number("1");
+serial_port return lex_number("2");
+parallel_port return lex_number("3");
+fixed_disk return lex_number("4");
+video_adapter return lex_number("5");
+network_adapter return lex_number("6");
+aims_card return lex_number("7");
+scsi_adapter return lex_number("8");
+
+{int} return lex_number(yytext);
+{hex} return lex_number(yytext);
+
+{int}b return lex_units(yytext, 1, SIZE);
+{int}kb return lex_units(yytext, 1024, SIZE);
+{int}mb return lex_units(yytext, 1024*1024, SIZE);
+
+{flt}s return lex_units(yytext, 1000000000, TIME);
+{flt}ms return lex_units(yytext, 1000000, TIME);
+{flt}us return lex_units(yytext, 1000, TIME);
+{flt}ns return lex_units(yytext, 1, TIME);
+{int}s return lex_units(yytext, 1000000000, TIME);
+{int}ms return lex_units(yytext, 1000000, TIME);
+{int}us return lex_units(yytext, 1000, TIME);
+{int}ns return lex_units(yytext, 1, TIME);
+
+{flt}V return lex_units(yytext, 100000, VOLTAGE);
+{flt}mV return lex_units(yytext, 100, VOLTAGE);
+{flt}uV return lex_units(yytext, 0.1, VOLTAGE);
+{int}V return lex_units(yytext, 100000, VOLTAGE);
+{int}mV return lex_units(yytext, 100, VOLTAGE);
+{int}uV return lex_units(yytext, 0.1, VOLTAGE);
+
+{flt}A return lex_units(yytext, 10000000, CURRENT);
+{flt}mA return lex_units(yytext, 10000, CURRENT);
+{flt}uA return lex_units(yytext, 10, CURRENT);
+{int}A return lex_units(yytext, 10000000, CURRENT);
+{int}mA return lex_units(yytext, 10000, CURRENT);
+{int}uA return lex_units(yytext, 10, CURRENT);
+
+{flt} return lex_float(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_float(char *s)
+{
+ yylval.flt = strtod(s, NULL);
+ return FLOAT;
+}
+
+static int lex_units(char *s, int scale, int token)
+{
+ float f;
+ sscanf(s, "%f", &f);
+ yylval.num = scale*f + 0.5;
+ return token;
+}
+
+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;
+}
+
+/*======================================================================
+
+ The main parser entry point
+
+======================================================================*/
+
+void parse_cis(FILE *f)
+{
+ current_lineno = 1;
+ yyrestart(f);
+ yyparse();
+ fclose(f);
+}
+
diff --git a/pack_cis.c b/pack_cis.c
new file mode 100644
index 0000000..67ebbba
--- /dev/null
+++ b/pack_cis.c
@@ -0,0 +1,447 @@
+/*======================================================================
+
+ A utility to convert a plain text description of a Card
+ Information Structure into its packed binary representation.
+
+ pack_cis.c 1.20 2002/10/16 16:38:18
+
+ The contents of this file are subject to the Mozilla Public
+ License Version 1.1 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS
+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ rights and limitations under the License.
+
+ 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.
+
+ Alternatively, the contents of this file may be used under the
+ terms of the GNU General Public License version 2 (the "GPL"), in
+ which case the provisions of the GPL are applicable instead of the
+ above. If you wish to allow the use of your version of this file
+ only under the terms of the GPL and not to allow others to use
+ your version of this file under the MPL, indicate your decision
+ by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL. If you do not delete
+ the provisions above, a recipient may use your version of this
+ file under either the MPL or the GPL.
+
+ Usage:
+
+ pack_cis [-o outfile] [infile]
+
+ [infile] defaults to stdin, and [outfile] defaults to stdout.
+
+======================================================================*/
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+
+#include "pack_cis.h"
+
+tuple_info_t *cis_root = NULL, *mfc[8] = { NULL };
+int nf = 0;
+
+/*======================================================================
+
+ Support routines for packing parts of configuration table entries
+
+======================================================================*/
+
+static u_int mantissa[] = {
+ 10, 12, 13, 15, 20, 25, 30, 35,
+ 40, 45, 50, 55, 60, 70, 80, 90
+};
+static int pack_power(cistpl_power_t *pwr, u_char *b)
+{
+ u_int tmp, i;
+ u_char m, e, x, *c = b;
+ *c = pwr->present; c++;
+ for (i = 0; i < 7; i++) {
+ if (!(pwr->present & (1<<i)))
+ continue;
+ tmp = pwr->param[i];
+ for (e = 1; ((tmp % 10) == 0) || (tmp > 999); e++)
+ tmp /= 10;
+ x = m = 0;
+ if (tmp < 100) {
+ if (tmp < 10) { tmp *= 10; e--; }
+ for (m = 0; m < 16; m++)
+ if (mantissa[m] == tmp) break;
+ if (m == 16) { tmp *= 10; e--; }
+ }
+ if (tmp >= 100) {
+ e++;
+ x = (tmp/10) - ((tmp/10) % 10);
+ for (m = 0; m < 16; m++)
+ if (mantissa[m] == x) break;
+ x = (u_char)(tmp - 10*(u_int)x);
+ }
+ *c = (m<<3) | e | (x ? 0x80 : 0); c++;
+ if (x) { *c = x; c++; }
+ }
+ return c-b;
+}
+
+static int pack_io(cistpl_io_t *p, u_char *b)
+{
+ u_char *c = b;
+ u_int i, j, ml, ma;
+ *c = p->flags & (CISTPL_IO_8BIT|CISTPL_IO_16BIT);
+ if ((p->nwin == 1) && (p->win[0].base == 0)) {
+ for (i = 1, j = 0; i < p->win[0].len; i *= 2, j++) ;
+ *c |= j; c++;
+ } else {
+ for (i = ma = ml = 0; i < p->nwin; i++) {
+ ma |= p->win[i].base;
+ ml |= p->win[i].len-1;
+ }
+ ma = (ma > 0xffff) ? 3 : ((ma > 0xff) ? 2 : 1);
+ ml = (ml > 0xffff) ? 3 : ((ml > 0xff) ? 2 : 1);
+ *c |= 0x80 | (p->flags & CISTPL_IO_LINES_MASK); c++;
+ *c = (p->nwin-1) | (ma<<4) | (ml<<6); c++;
+ if (ma == 3) ma++; if (ml == 3) ml++;
+ for (i = 0; i < p->nwin; i++) {
+ for (j = 0; j < ma; j++) {
+ *c = (p->win[i].base >> (8*j)) & 0xff; c++;
+ }
+ for (j = 0; j < ml; j++) {
+ *c = ((p->win[i].len-1) >> (8*j)) & 0xff; c++;
+ }
+ }
+ }
+ return c-b;
+}
+
+static int pack_mem(cistpl_mem_t *p, u_char *b)
+{
+ u_char *c = b;
+ u_int i, j, ml, ma, ha;
+ for (i = ma = ml = ha = 0; i < p->nwin; i++) {
+ ma |= p->win[i].card_addr;
+ ml |= p->win[i].len;
+ ha |= p->win[i].host_addr;
+ }
+ ma = (ma|ha) >> 8; ml >>= 8;
+ ma = (ma > 0xffff) ? 3 : ((ma > 0xff) ? 2 : 1);
+ ml = (ml > 0xffff) ? 3 : ((ml > 0xff) ? 2 : 1);
+ *c = (p->nwin-1) | (ma<<5) | (ml<<3) | (ha ? 0x80 : 0); c++;
+ for (i = 0; i < p->nwin; i++) {
+ for (j = 1; j <= ml; j++) {
+ *c = (p->win[i].len >> (8*j)) & 0xff; c++;
+ }
+ for (j = 1; j <= ma; j++) {
+ *c = (p->win[i].card_addr >> (8*j)) & 0xff; c++;
+ }
+ if (ha)
+ for (j = 1; j <= ma; j++) {
+ *c = (p->win[i].host_addr >> (8*j)) & 0xff; c++;
+ }
+ }
+ return c-b;
+}
+
+static int pack_irq(cistpl_irq_t *p, u_char *b)
+{
+ b[0] = p->IRQInfo1;
+ if (p->IRQInfo1 & IRQ_INFO2_VALID) {
+ b[1] = p->IRQInfo2 & 0xff;
+ b[2] = (p->IRQInfo2 >> 8) & 0xff;
+ return 3;
+ }
+ return 1;
+}
+
+static void pack_cftable(cistpl_cftable_entry_t *p, u_char *b)
+{
+ u_char *c;
+ b[2] = p->index | 0x80;
+ if (p->flags & CISTPL_CFTABLE_DEFAULT)
+ b[2] |= 0x40;
+ b[3] = 0x01;
+ b[3] |= (p->flags & CISTPL_CFTABLE_BVDS) ? 0x10 : 0;
+ b[3] |= (p->flags & CISTPL_CFTABLE_WP) ? 0x20 : 0;
+ b[3] |= (p->flags & CISTPL_CFTABLE_RDYBSY) ? 0x40 : 0;
+ b[3] |= (p->flags & CISTPL_CFTABLE_MWAIT) ? 0x80 : 0;
+ b[4] = 0;
+ c = b+5;
+ if (p->vcc.present) {
+ b[4]++; c += pack_power(&p->vcc, c);
+ if (p->vpp1.present) {
+ b[4]++; c += pack_power(&p->vpp1, c);
+ if (p->vpp2.present) {
+ b[4]++; c += pack_power(&p->vpp2, c);
+ }
+ }
+ }
+ if (p->io.nwin > 0) {
+ b[4] |= 0x08;
+ c += pack_io(&p->io, c);
+ }
+ if (p->irq.IRQInfo1 > 0) {
+ b[4] |= 0x10;
+ c += pack_irq(&p->irq, c);
+ }
+ if (p->mem.nwin > 0) {
+ b[4] |= 0x60;
+ c += pack_mem(&p->mem, c);
+ }
+ if (p->flags >> 8) {
+ b[4] |= 0x80;
+ *c++ = p->flags >> 8;
+ }
+ b[1] = c-b-2;
+}
+
+/*======================================================================
+
+ Routines for packing device info tuples
+
+======================================================================*/
+
+static int pack_speed(u_int speed, u_char *b)
+{
+ u_char e, m, *c = b;
+ switch (speed) {
+ case 0: *c |= 0; c++; break;
+ case 250: *c |= 1; c++; break;
+ case 200: *c |= 2; c++; break;
+ case 150: *c |= 3; c++; break;
+ case 100: *c |= 4; c++; break;
+ default:
+ *c |= 7; c++;
+ for (e = 1; speed > 80; e++)
+ speed /= 10;
+ for (m = 0; m < 15; m++)
+ if (mantissa[m] >= speed) break;
+ *c = ((m+1)<<3) | e; c++;
+ }
+ return c-b;
+}
+
+static void pack_device(cistpl_device_t *d, u_char *b)
+{
+ u_int i, sz;
+ u_char e, *c = b+2;
+ for (i = 0; i < d->ndev; i++) {
+ *c = (d->dev[i].type<<4);
+ c += pack_speed(d->dev[i].speed, c);
+ sz = d->dev[i].size/512;
+ for (e = 0; sz > 32; e++)
+ sz /= 4;
+ *c = (e & 7) | ((sz-1) << 3); c++;
+ }
+ *c = 0xff; c++;
+ b[1] = c-b-2;
+}
+
+/*======================================================================
+
+ For now, I only implement a subset of tuples types, intended to be
+ enough to handle most IO-oriented cards.
+
+======================================================================*/
+
+static int pack_tuple(tuple_info_t *t, u_char *b)
+{
+ cisparse_t *p = t->parse;
+ u_int i, m;
+ u_char *c;
+
+ *b = t->type;
+ switch (t->type) {
+ case CISTPL_DEVICE:
+ case CISTPL_DEVICE_A:
+ if (p) {
+ pack_device(&p->device, b);
+ } else {
+ /* Fake null device tuple */
+ b[1] = 3; b[2] = 0; b[3] = 0; b[4] = 0xff;
+ }
+ break;
+ case CISTPL_MANFID:
+ b[1] = 4;
+ b[2] = p->manfid.manf & 0xff;
+ b[3] = p->manfid.manf >> 8;
+ b[4] = p->manfid.card & 0xff;
+ b[5] = p->manfid.card >> 8;
+ break;
+ case CISTPL_FUNCID:
+ b[1] = 2;
+ b[2] = p->funcid.func;
+ b[3] = p->funcid.sysinit;
+ break;
+ case CISTPL_JEDEC_C:
+ case CISTPL_JEDEC_A:
+ b[1] = 2*p->jedec.nid;
+ for (i = 0; i < p->jedec.nid; i++) {
+ b[2*i+1] = p->jedec.id[i].mfr;
+ b[2*i+2] = p->jedec.id[i].info;
+ }
+ break;
+ case CISTPL_CONFIG:
+ b[3] = p->config.last_idx;
+ i = p->config.base;
+ for (c = b+4, m = 0; (i > 0) || !m; i >>= 8, m++) {
+ c[m] = i & 0xff;
+ }
+ b[2] = m-1;
+ i = p->config.rmask[0];
+ for (c = c+m, m = 0; (i > 0) || !m; i >>= 8, m++) {
+ c[m] = i & 0xff;
+ }
+ b[2] |= ((m-1) << 2);
+ b[1] = c+m-b-2;
+ break;
+ case CISTPL_VERS_1:
+ b[2] = p->version_1.major;
+ b[3] = p->version_1.minor;
+ c = b+4;
+ for (i = 0; i < p->version_1.ns; i++) {
+ strcpy((char *)c, p->version_1.str+p->version_1.ofs[i]);
+ c += strlen((char *)c) + 1;
+ }
+ for (; i < 4; i++) { *c = 0; c++; }
+ *c = 0xff; c++;
+ b[1] = c-b-2;
+ break;
+ case CISTPL_CFTABLE_ENTRY:
+ pack_cftable(&p->cftable_entry, b);
+ break;
+ case CISTPL_LINKTARGET:
+ b[1] = 3; b[2] = 'C'; b[3] = 'I'; b[4] = 'S';
+ break;
+ case CISTPL_NO_LINK:
+ case CISTPL_END:
+ b[1] = 0;
+ break;
+ }
+ return b[1]+2;
+}
+
+/*======================================================================
+
+ The following routines handle parsing of aggregates of tuples.
+ pack_chain() is the simplest: just return a string of tuples and
+ terminate with an END tuple. pack_mfc() is used to tie the
+ function-specific tuple chains for a multifunction card together
+ using a LONGLINK_MFC tuple. And pack_cis() handles a complete
+ CIS, whether it is multifunction or not.
+
+======================================================================*/
+
+static int pack_chain(tuple_info_t *t, u_char *b)
+{
+ int n = 0;
+ tuple_info_t end = { CISTPL_END, NULL, NULL };
+ while (t) {
+ n += pack_tuple(t, b+n);
+ t = t->next;
+ }
+ n += pack_tuple(&end, b+n);
+ return n;
+}
+
+static int pack_mfc(u_int ofs, u_char *b)
+{
+ u_int i, j, pos;
+ tuple_info_t target = { CISTPL_LINKTARGET, NULL, NULL };
+
+ b[0] = CISTPL_LONGLINK_MFC;
+ b[1] = 5*nf + 1;
+ b[2] = nf;
+ b[5*nf+3] = CISTPL_END;
+ b[5*nf+4] = 0;
+ /* Leave space for this tuple and the CISTPL_END tuple */
+ pos = 5*nf+5;
+ for (i = 0; i < nf; i++) {
+ b[3+i*5] = 0;
+ for (j = 0; j < 4; j++)
+ b[4+i*5+j] = ((ofs+pos) >> (8*j)) & 0xff;
+ pos += pack_tuple(&target, b+pos);
+ pos += pack_chain(mfc[i], b+pos);
+ }
+ return ofs+pos;
+}
+
+static int pack_cis(tuple_info_t *t, u_char *b)
+{
+ int n = 0;
+ tuple_info_t device = { CISTPL_DEVICE, NULL, NULL };
+ tuple_info_t nolink = { CISTPL_NO_LINK, NULL, NULL };
+ tuple_info_t end = { CISTPL_END, NULL, NULL };
+ if (t->type != CISTPL_DEVICE)
+ n = pack_tuple(&device, b);
+ while (t) {
+ n += pack_tuple(t, b+n);
+ t = t->next;
+ }
+ if (nf > 0) {
+ n = pack_mfc(n, b+n);
+ } else {
+ n += pack_tuple(&nolink, b+n);
+ n += pack_tuple(&end, b+n);
+ }
+ return n;
+}
+
+/*====================================================================*/
+
+int main(int argc, char *argv[])
+{
+ int optch, errflg = 0;
+ char *out = NULL;
+ u_char buf[1024];
+ int n;
+ FILE *f;
+
+ while ((optch = getopt(argc, argv, "o:")) != -1) {
+ switch (optch) {
+ case 'o':
+ out = strdup(optarg); break;
+ default:
+ errflg = 1; break;
+ }
+ }
+ if (errflg || (optind < argc-1)) {
+ fprintf(stderr, "usage: %s [-o outfile] [infile]\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ if (optind < argc) {
+ f = fopen(argv[optind], "r");
+ if (!f) {
+ fprintf(stderr, "could not open '%s': %s\n", argv[optind],
+ strerror(errno));
+ return -1;
+ }
+ } else
+ f = stdin;
+ parse_cis(f);
+ fclose(f);
+ n = pack_cis(cis_root, buf);
+ if (out) {
+ f = fopen(out, "w");
+ if (!f) {
+ fprintf(stderr, "could not open '%s': %s\n", out,
+ strerror(errno));
+ return -1;
+ }
+ } else f = stdout;
+ fwrite(buf, n, 1, f);
+ fclose(f);
+
+ return 0;
+}
diff --git a/pack_cis.h b/pack_cis.h
new file mode 100644
index 0000000..c212444
--- /dev/null
+++ b/pack_cis.h
@@ -0,0 +1,38 @@
+/*
+ * pack_cis.h 1.7 2001/08/24 12:16:45
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * 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.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+typedef struct tuple_info_t {
+ u_char type;
+ cisparse_t *parse;
+ struct tuple_info_t *next;
+} tuple_info_t;
+
+extern tuple_info_t *cis_root, *mfc[8];
+extern int nf;
+
+void parse_cis(FILE *f);
diff --git a/pcmcia/bulkmem.h b/pcmcia/bulkmem.h
new file mode 100644
index 0000000..7748d44
--- /dev/null
+++ b/pcmcia/bulkmem.h
@@ -0,0 +1,195 @@
+/*
+ * Definitions for bulk memory services
+ *
+ * bulkmem.h 1.13 2001/08/24 12:16:12
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * 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.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ * bulkmem.h 1.3 1995/05/27 04:49:49
+ */
+
+#ifndef _LINUX_BULKMEM_H
+#define _LINUX_BULKMEM_H
+
+/* For GetFirstRegion and GetNextRegion */
+typedef struct region_info_t {
+ u_int Attributes;
+ u_int CardOffset;
+ u_int RegionSize;
+ u_int AccessSpeed;
+ u_int BlockSize;
+ u_int PartMultiple;
+ u_char JedecMfr, JedecInfo;
+ memory_handle_t next;
+} region_info_t;
+
+#define REGION_TYPE 0x0001
+#define REGION_TYPE_CM 0x0000
+#define REGION_TYPE_AM 0x0001
+#define REGION_PREFETCH 0x0008
+#define REGION_CACHEABLE 0x0010
+#define REGION_BAR_MASK 0xe000
+#define REGION_BAR_SHIFT 13
+
+/* For OpenMemory */
+typedef struct open_mem_t {
+ u_int Attributes;
+ u_int Offset;
+} open_mem_t;
+
+/* Attributes for OpenMemory */
+#define MEMORY_TYPE 0x0001
+#define MEMORY_TYPE_CM 0x0000
+#define MEMORY_TYPE_AM 0x0001
+#define MEMORY_EXCLUSIVE 0x0002
+#define MEMORY_PREFETCH 0x0008
+#define MEMORY_CACHEABLE 0x0010
+#define MEMORY_BAR_MASK 0xe000
+#define MEMORY_BAR_SHIFT 13
+
+typedef struct eraseq_entry_t {
+ memory_handle_t Handle;
+ u_char State;
+ u_int Size;
+ u_int Offset;
+ void *Optional;
+} eraseq_entry_t;
+
+typedef struct eraseq_hdr_t {
+ int QueueEntryCnt;
+ eraseq_entry_t *QueueEntryArray;
+} eraseq_hdr_t;
+
+#define ERASE_QUEUED 0x00
+#define ERASE_IN_PROGRESS(n) (((n) > 0) && ((n) < 0x80))
+#define ERASE_IDLE 0xff
+#define ERASE_PASSED 0xe0
+#define ERASE_FAILED 0xe1
+
+#define ERASE_MISSING 0x80
+#define ERASE_MEDIA_WRPROT 0x84
+#define ERASE_NOT_ERASABLE 0x85
+#define ERASE_BAD_OFFSET 0xc1
+#define ERASE_BAD_TECH 0xc2
+#define ERASE_BAD_SOCKET 0xc3
+#define ERASE_BAD_VCC 0xc4
+#define ERASE_BAD_VPP 0xc5
+#define ERASE_BAD_SIZE 0xc6
+
+/* For CopyMemory */
+typedef struct copy_op_t {
+ u_int Attributes;
+ u_int SourceOffset;
+ u_int DestOffset;
+ u_int Count;
+} copy_op_t;
+
+/* For ReadMemory and WriteMemory */
+typedef struct mem_op_t {
+ u_int Attributes;
+ u_int Offset;
+ u_int Count;
+} mem_op_t;
+
+#define MEM_OP_BUFFER 0x01
+#define MEM_OP_BUFFER_USER 0x00
+#define MEM_OP_BUFFER_KERNEL 0x01
+#define MEM_OP_DISABLE_ERASE 0x02
+#define MEM_OP_VERIFY 0x04
+
+/* For RegisterMTD */
+typedef struct mtd_reg_t {
+ u_int Attributes;
+ u_int Offset;
+ u_long MediaID;
+} mtd_reg_t;
+
+/*
+ * Definitions for MTD requests
+ */
+
+typedef struct mtd_request_t {
+ u_int SrcCardOffset;
+ u_int DestCardOffset;
+ u_int TransferLength;
+ u_int Function;
+ u_long MediaID;
+ u_int Status;
+ u_int Timeout;
+} mtd_request_t;
+
+/* Fields in MTD Function */
+#define MTD_REQ_ACTION 0x003
+#define MTD_REQ_ERASE 0x000
+#define MTD_REQ_READ 0x001
+#define MTD_REQ_WRITE 0x002
+#define MTD_REQ_COPY 0x003
+#define MTD_REQ_NOERASE 0x004
+#define MTD_REQ_VERIFY 0x008
+#define MTD_REQ_READY 0x010
+#define MTD_REQ_TIMEOUT 0x020
+#define MTD_REQ_LAST 0x040
+#define MTD_REQ_FIRST 0x080
+#define MTD_REQ_KERNEL 0x100
+
+/* Status codes */
+#define MTD_WAITREQ 0x00
+#define MTD_WAITTIMER 0x01
+#define MTD_WAITRDY 0x02
+#define MTD_WAITPOWER 0x03
+
+/*
+ * Definitions for MTD helper functions
+ */
+
+/* For MTDModifyWindow */
+typedef struct mtd_mod_win_t {
+ u_int Attributes;
+ u_int AccessSpeed;
+ u_int CardOffset;
+} mtd_mod_win_t;
+
+/* For MTDSetVpp */
+typedef struct mtd_vpp_req_t {
+ u_char Vpp1, Vpp2;
+} mtd_vpp_req_t;
+
+/* For MTDRDYMask */
+typedef struct mtd_rdy_req_t {
+ u_int Mask;
+} mtd_rdy_req_t;
+
+enum mtd_helper {
+ MTDRequestWindow, MTDModifyWindow, MTDReleaseWindow,
+ MTDSetVpp, MTDRDYMask
+};
+
+#ifdef IN_CARD_SERVICES
+extern int MTDHelperEntry(int func, void *a1, void *a2);
+#else
+extern int MTDHelperEntry(int func, ...);
+#endif
+
+#endif /* _LINUX_BULKMEM_H */
diff --git a/pcmcia/cistpl.h b/pcmcia/cistpl.h
new file mode 100644
index 0000000..1d4cac2
--- /dev/null
+++ b/pcmcia/cistpl.h
@@ -0,0 +1,604 @@
+/*
+ * cistpl.h 1.35 2001/08/24 12:16:12
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * 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.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#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 {
+ u_int addr;
+} cistpl_longlink_t;
+
+typedef struct cistpl_checksum_t {
+ u_short addr;
+ u_short len;
+ u_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 {
+ u_char nfn;
+ struct {
+ u_char space;
+ u_int addr;
+ } fn[CISTPL_MAX_FUNCTIONS];
+} cistpl_longlink_mfc_t;
+
+#define CISTPL_MAX_ALTSTR_STRINGS 4
+
+typedef struct cistpl_altstr_t {
+ u_char ns;
+ u_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 {
+ u_char ndev;
+ struct {
+ u_char type;
+ u_char wp;
+ u_int speed;
+ u_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 {
+ u_char flags;
+ cistpl_device_t device;
+} cistpl_device_o_t;
+
+#define CISTPL_VERS_1_MAX_PROD_STRINGS 4
+
+typedef struct cistpl_vers_1_t {
+ u_char major;
+ u_char minor;
+ u_char ns;
+ u_char ofs[CISTPL_VERS_1_MAX_PROD_STRINGS];
+ char str[254];
+} cistpl_vers_1_t;
+
+typedef struct cistpl_jedec_t {
+ u_char nid;
+ struct {
+ u_char mfr;
+ u_char info;
+ } id[CISTPL_MAX_DEVICES];
+} cistpl_jedec_t;
+
+typedef struct cistpl_manfid_t {
+ u_short manf;
+ u_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 {
+ u_char func;
+ u_char sysinit;
+} cistpl_funcid_t;
+
+typedef struct cistpl_funce_t {
+ u_char type;
+ u_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 {
+ u_char uart_type;
+ u_char uart_cap_0;
+ u_char uart_cap_1;
+} cistpl_serial_t;
+
+typedef struct cistpl_modem_cap_t {
+ u_char flow;
+ u_char cmd_buf;
+ u_char rcv_buf_0, rcv_buf_1, rcv_buf_2;
+ u_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 {
+ u_char max_data_0;
+ u_char max_data_1;
+ u_char modulation_0;
+ u_char modulation_1;
+ u_char error_control;
+ u_char compression;
+ u_char cmd_protocol;
+ u_char escape;
+ u_char encrypt;
+ u_char misc_features;
+ u_char ccitt_code[0];
+} cistpl_data_serv_t;
+
+typedef struct cistpl_fax_serv_t {
+ u_char max_data_0;
+ u_char max_data_1;
+ u_char modulation;
+ u_char encrypt;
+ u_char features_0;
+ u_char features_1;
+ u_char ccitt_code[0];
+} cistpl_fax_serv_t;
+
+typedef struct cistpl_voice_serv_t {
+ u_char max_data_0;
+ u_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 {
+ u_char tech;
+} cistpl_lan_tech_t;
+
+typedef struct cistpl_lan_speed_t {
+ u_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 {
+ u_char media;
+} cistpl_lan_media_t;
+
+typedef struct cistpl_lan_node_id_t {
+ u_char nb;
+ u_char id[16];
+} cistpl_lan_node_id_t;
+
+typedef struct cistpl_lan_connector_t {
+ u_char code;
+} cistpl_lan_connector_t;
+
+/*======================================================================
+
+ IDE Function Extension Tuples
+
+======================================================================*/
+
+#define CISTPL_IDE_INTERFACE 0x01
+
+typedef struct cistpl_ide_interface_t {
+ u_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 {
+ u_char feature1;
+ u_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 {
+ u_char attr;
+ u_int size;
+} cistpl_bar_t;
+
+typedef struct cistpl_config_t {
+ u_char last_idx;
+ u_int base;
+ u_int rmask[4];
+ u_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 {
+ u_char present;
+ u_char flags;
+ u_int param[7];
+} cistpl_power_t;
+
+typedef struct cistpl_timing_t {
+ u_int wait, waitscale;
+ u_int ready, rdyscale;
+ u_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 {
+ u_char flags;
+ u_char nwin;
+ struct {
+ u_int base;
+ u_int len;
+ } win[CISTPL_IO_MAX_WIN];
+} cistpl_io_t;
+
+typedef struct cistpl_irq_t {
+ u_int IRQInfo1;
+ u_int IRQInfo2;
+} cistpl_irq_t;
+
+#define CISTPL_MEM_MAX_WIN 8
+
+typedef struct cistpl_mem_t {
+ u_char flags;
+ u_char nwin;
+ struct {
+ u_int len;
+ u_int card_addr;
+ u_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 {
+ u_char index;
+ u_short flags;
+ u_char interface;
+ cistpl_power_t vcc, vpp1, vpp2;
+ cistpl_timing_t timing;
+ cistpl_io_t io;
+ cistpl_irq_t irq;
+ cistpl_mem_t mem;
+ u_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 {
+ u_char index;
+ u_int flags;
+ cistpl_power_t vcc, vpp1, vpp2;
+ u_char io;
+ cistpl_irq_t irq;
+ u_char mem;
+ u_char subtuples;
+} cistpl_cftable_entry_cb_t;
+
+typedef struct cistpl_device_geo_t {
+ u_char ngeo;
+ struct {
+ u_char buswidth;
+ u_int erase_block;
+ u_int read_block;
+ u_int write_block;
+ u_int partition;
+ u_int interleave;
+ } geo[CISTPL_MAX_DEVICES];
+} cistpl_device_geo_t;
+
+typedef struct cistpl_vers_2_t {
+ u_char vers;
+ u_char comply;
+ u_short dindex;
+ u_char vspec8, vspec9;
+ u_char nhdr;
+ u_char vendor, info;
+ char str[244];
+} cistpl_vers_2_t;
+
+typedef struct cistpl_org_t {
+ u_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 {
+ u_char type;
+ u_char edc;
+ u_int offset;
+ u_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 {
+ u_int Attributes;
+ cisdata_t DesiredTuple;
+ u_int Flags; /* internal use */
+ u_int LinkOffset; /* internal use */
+ u_int CISOffset; /* internal use */
+ cisdata_t TupleCode;
+ cisdata_t TupleLink;
+ cisdata_t TupleOffset;
+ cisdata_t TupleDataMax;
+ cisdata_t TupleDataLen;
+ cisdata_t *TupleData;
+} tuple_t;
+
+/* Special cisdata_t 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 {
+ u_int Chains;
+} cisinfo_t;
+
+#define CISTPL_MAX_CIS_SIZE 0x200
+
+/* For ReplaceCIS */
+typedef struct cisdump_t {
+ u_int Length;
+ cisdata_t Data[CISTPL_MAX_CIS_SIZE];
+} cisdump_t;
+
+#endif /* LINUX_CISTPL_H */
diff --git a/pcmcia/cs.h b/pcmcia/cs.h
new file mode 100644
index 0000000..8e202c6
--- /dev/null
+++ b/pcmcia/cs.h
@@ -0,0 +1,441 @@
+/*
+ * cs.h 1.74 2001/10/04 03:15:22
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * 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.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#ifndef _LINUX_CS_H
+#define _LINUX_CS_H
+
+/* For AccessConfigurationRegister */
+typedef struct conf_reg_t {
+ u_char Function;
+ u_int Action;
+ off_t Offset;
+ u_int Value;
+} conf_reg_t;
+
+/* Actions */
+#define CS_READ 1
+#define CS_WRITE 2
+
+/* for AdjustResourceInfo */
+typedef struct adjust_t {
+ u_int Action;
+ u_int Resource;
+ u_int Attributes;
+ union {
+ struct memory {
+ u_long Base;
+ u_long Size;
+ } memory;
+ struct io {
+ ioaddr_t BasePort;
+ ioaddr_t NumPorts;
+ u_int IOAddrLines;
+ } io;
+ struct irq {
+ u_int IRQ;
+ } irq;
+ } resource;
+} adjust_t;
+
+/* Action field */
+#define REMOVE_MANAGED_RESOURCE 1
+#define ADD_MANAGED_RESOURCE 2
+#define GET_FIRST_MANAGED_RESOURCE 3
+#define GET_NEXT_MANAGED_RESOURCE 4
+/* Resource field */
+#define RES_MEMORY_RANGE 1
+#define RES_IO_RANGE 2
+#define RES_IRQ 3
+/* Attribute field */
+#define RES_IRQ_TYPE 0x03
+#define RES_IRQ_TYPE_EXCLUSIVE 0
+#define RES_IRQ_TYPE_TIME 1
+#define RES_IRQ_TYPE_DYNAMIC 2
+#define RES_IRQ_CSC 0x04
+#define RES_SHARED 0x08
+#define RES_RESERVED 0x10
+#define RES_ALLOCATED 0x20
+#define RES_REMOVED 0x40
+
+typedef struct servinfo_t {
+ char Signature[2];
+ u_int Count;
+ u_int Revision;
+ u_int CSLevel;
+ char *VendorString;
+} servinfo_t;
+
+typedef struct event_callback_args_t {
+ client_handle_t client_handle;
+ void *info;
+ void *mtdrequest;
+ void *buffer;
+ void *misc;
+ void *client_data;
+ struct bus_operations *bus;
+} event_callback_args_t;
+
+/* for GetConfigurationInfo */
+typedef struct config_info_t {
+ u_char Function;
+ u_int Attributes;
+ u_int Vcc, Vpp1, Vpp2;
+ u_int IntType;
+ u_int ConfigBase;
+ u_char Status, Pin, Copy, Option, ExtStatus;
+ u_int Present;
+ u_int CardValues;
+ u_int AssignedIRQ;
+ u_int IRQAttributes;
+ ioaddr_t BasePort1;
+ ioaddr_t NumPorts1;
+ u_int Attributes1;
+ ioaddr_t BasePort2;
+ ioaddr_t NumPorts2;
+ u_int Attributes2;
+ u_int IOAddrLines;
+} config_info_t;
+
+/* For CardValues field */
+#define CV_OPTION_VALUE 0x01
+#define CV_STATUS_VALUE 0x02
+#define CV_PIN_REPLACEMENT 0x04
+#define CV_COPY_VALUE 0x08
+#define CV_EXT_STATUS 0x10
+
+/* For GetFirst/NextClient */
+typedef struct client_req_t {
+ socket_t Socket;
+ u_int Attributes;
+} client_req_t;
+
+#define CLIENT_THIS_SOCKET 0x01
+
+/* For RegisterClient */
+typedef struct client_reg_t {
+ dev_info_t *dev_info;
+ u_int Attributes;
+ u_int EventMask;
+ int (*event_handler)(event_t event, int priority,
+ event_callback_args_t *);
+ event_callback_args_t event_callback_args;
+ u_int Version;
+} client_reg_t;
+
+/* ModifyConfiguration */
+typedef struct modconf_t {
+ u_int Attributes;
+ u_int Vcc, Vpp1, Vpp2;
+} modconf_t;
+
+/* Attributes for ModifyConfiguration */
+#define CONF_IRQ_CHANGE_VALID 0x100
+#define CONF_VCC_CHANGE_VALID 0x200
+#define CONF_VPP1_CHANGE_VALID 0x400
+#define CONF_VPP2_CHANGE_VALID 0x800
+
+/* For RequestConfiguration */
+typedef struct config_req_t {
+ u_int Attributes;
+ u_int Vcc, Vpp1, Vpp2;
+ u_int IntType;
+ u_int ConfigBase;
+ u_char Status, Pin, Copy, ExtStatus;
+ u_char ConfigIndex;
+ u_int Present;
+} config_req_t;
+
+/* Attributes for RequestConfiguration */
+#define CONF_ENABLE_IRQ 0x01
+#define CONF_ENABLE_DMA 0x02
+#define CONF_ENABLE_SPKR 0x04
+#define CONF_VALID_CLIENT 0x100
+
+/* IntType field */
+#define INT_MEMORY 0x01
+#define INT_MEMORY_AND_IO 0x02
+#define INT_CARDBUS 0x04
+#define INT_ZOOMED_VIDEO 0x08
+
+/* For RequestIO and ReleaseIO */
+typedef struct io_req_t {
+ ioaddr_t BasePort1;
+ ioaddr_t NumPorts1;
+ u_int Attributes1;
+ ioaddr_t BasePort2;
+ ioaddr_t NumPorts2;
+ u_int Attributes2;
+ u_int IOAddrLines;
+} io_req_t;
+
+/* Attributes for RequestIO and ReleaseIO */
+#define IO_SHARED 0x01
+#define IO_FIRST_SHARED 0x02
+#define IO_FORCE_ALIAS_ACCESS 0x04
+#define IO_DATA_PATH_WIDTH 0x18
+#define IO_DATA_PATH_WIDTH_8 0x00
+#define IO_DATA_PATH_WIDTH_16 0x08
+#define IO_DATA_PATH_WIDTH_AUTO 0x10
+
+/* For RequestIRQ and ReleaseIRQ */
+typedef struct irq_req_t {
+ u_int Attributes;
+ u_int AssignedIRQ;
+ u_int IRQInfo1, IRQInfo2;
+ void *Handler;
+ void *Instance;
+} irq_req_t;
+
+/* Attributes for RequestIRQ and ReleaseIRQ */
+#define IRQ_TYPE 0x03
+#define IRQ_TYPE_EXCLUSIVE 0x00
+#define IRQ_TYPE_TIME 0x01
+#define IRQ_TYPE_DYNAMIC_SHARING 0x02
+#define IRQ_FORCED_PULSE 0x04
+#define IRQ_FIRST_SHARED 0x08
+#define IRQ_HANDLE_PRESENT 0x10
+#define IRQ_PULSE_ALLOCATED 0x100
+
+/* Bits in IRQInfo1 field */
+#define IRQ_MASK 0x0f
+#define IRQ_NMI_ID 0x01
+#define IRQ_IOCK_ID 0x02
+#define IRQ_BERR_ID 0x04
+#define IRQ_VEND_ID 0x08
+#define IRQ_INFO2_VALID 0x10
+#define IRQ_LEVEL_ID 0x20
+#define IRQ_PULSE_ID 0x40
+#define IRQ_SHARE_ID 0x80
+
+typedef struct eventmask_t {
+ u_int Attributes;
+ u_int EventMask;
+} eventmask_t;
+
+#define CONF_EVENT_MASK_VALID 0x01
+
+/* Configuration registers present */
+#define PRESENT_OPTION 0x001
+#define PRESENT_STATUS 0x002
+#define PRESENT_PIN_REPLACE 0x004
+#define PRESENT_COPY 0x008
+#define PRESENT_EXT_STATUS 0x010
+#define PRESENT_IOBASE_0 0x020
+#define PRESENT_IOBASE_1 0x040
+#define PRESENT_IOBASE_2 0x080
+#define PRESENT_IOBASE_3 0x100
+#define PRESENT_IOSIZE 0x200
+
+/* For GetMemPage, MapMemPage */
+typedef struct memreq_t {
+ u_int CardOffset;
+ page_t Page;
+} memreq_t;
+
+/* For ModifyWindow */
+typedef struct modwin_t {
+ u_int Attributes;
+ u_int AccessSpeed;
+} modwin_t;
+
+/* For RequestWindow */
+typedef struct win_req_t {
+ u_int Attributes;
+ u_long Base;
+ u_int Size;
+ u_int AccessSpeed;
+} win_req_t;
+
+/* Attributes for RequestWindow */
+#define WIN_ADDR_SPACE 0x0001
+#define WIN_ADDR_SPACE_MEM 0x0000
+#define WIN_ADDR_SPACE_IO 0x0001
+#define WIN_MEMORY_TYPE 0x0002
+#define WIN_MEMORY_TYPE_CM 0x0000
+#define WIN_MEMORY_TYPE_AM 0x0002
+#define WIN_ENABLE 0x0004
+#define WIN_DATA_WIDTH 0x0018
+#define WIN_DATA_WIDTH_8 0x0000
+#define WIN_DATA_WIDTH_16 0x0008
+#define WIN_DATA_WIDTH_32 0x0010
+#define WIN_PAGED 0x0020
+#define WIN_SHARED 0x0040
+#define WIN_FIRST_SHARED 0x0080
+#define WIN_USE_WAIT 0x0100
+#define WIN_STRICT_ALIGN 0x0200
+#define WIN_MAP_BELOW_1MB 0x0400
+#define WIN_PREFETCH 0x0800
+#define WIN_CACHEABLE 0x1000
+#define WIN_BAR_MASK 0xe000
+#define WIN_BAR_SHIFT 13
+
+/* Attributes for RegisterClient */
+#define INFO_MASTER_CLIENT 0x01
+#define INFO_IO_CLIENT 0x02
+#define INFO_MTD_CLIENT 0x04
+#define INFO_MEM_CLIENT 0x08
+#define MAX_NUM_CLIENTS 3
+
+#define INFO_CARD_SHARE 0x10
+#define INFO_CARD_EXCL 0x20
+
+typedef struct cs_status_t {
+ u_char Function;
+ event_t CardState;
+ event_t SocketState;
+} cs_status_t;
+
+typedef struct error_info_t {
+ int func;
+ int retcode;
+} error_info_t;
+
+/* Special stuff for binding drivers to sockets */
+typedef struct bind_req_t {
+ socket_t Socket;
+ u_char Function;
+ dev_info_t *dev_info;
+} bind_req_t;
+
+/* Flag to bind to all functions */
+#define BIND_FN_ALL 0xff
+
+typedef struct mtd_bind_t {
+ socket_t Socket;
+ u_int Attributes;
+ u_int CardOffset;
+ dev_info_t *dev_info;
+} mtd_bind_t;
+
+/* Events */
+#define CS_EVENT_PRI_LOW 0
+#define CS_EVENT_PRI_HIGH 1
+
+#define CS_EVENT_WRITE_PROTECT 0x000001
+#define CS_EVENT_CARD_LOCK 0x000002
+#define CS_EVENT_CARD_INSERTION 0x000004
+#define CS_EVENT_CARD_REMOVAL 0x000008
+#define CS_EVENT_BATTERY_DEAD 0x000010
+#define CS_EVENT_BATTERY_LOW 0x000020
+#define CS_EVENT_READY_CHANGE 0x000040
+#define CS_EVENT_CARD_DETECT 0x000080
+#define CS_EVENT_RESET_REQUEST 0x000100
+#define CS_EVENT_RESET_PHYSICAL 0x000200
+#define CS_EVENT_CARD_RESET 0x000400
+#define CS_EVENT_REGISTRATION_COMPLETE 0x000800
+#define CS_EVENT_RESET_COMPLETE 0x001000
+#define CS_EVENT_PM_SUSPEND 0x002000
+#define CS_EVENT_PM_RESUME 0x004000
+#define CS_EVENT_INSERTION_REQUEST 0x008000
+#define CS_EVENT_EJECTION_REQUEST 0x010000
+#define CS_EVENT_MTD_REQUEST 0x020000
+#define CS_EVENT_ERASE_COMPLETE 0x040000
+#define CS_EVENT_REQUEST_ATTENTION 0x080000
+#define CS_EVENT_CB_DETECT 0x100000
+#define CS_EVENT_3VCARD 0x200000
+#define CS_EVENT_XVCARD 0x400000
+
+/* Return codes */
+#define CS_SUCCESS 0x00
+#define CS_BAD_ADAPTER 0x01
+#define CS_BAD_ATTRIBUTE 0x02
+#define CS_BAD_BASE 0x03
+#define CS_BAD_EDC 0x04
+#define CS_BAD_IRQ 0x06
+#define CS_BAD_OFFSET 0x07
+#define CS_BAD_PAGE 0x08
+#define CS_READ_FAILURE 0x09
+#define CS_BAD_SIZE 0x0a
+#define CS_BAD_SOCKET 0x0b
+#define CS_BAD_TYPE 0x0d
+#define CS_BAD_VCC 0x0e
+#define CS_BAD_VPP 0x0f
+#define CS_BAD_WINDOW 0x11
+#define CS_WRITE_FAILURE 0x12
+#define CS_NO_CARD 0x14
+#define CS_UNSUPPORTED_FUNCTION 0x15
+#define CS_UNSUPPORTED_MODE 0x16
+#define CS_BAD_SPEED 0x17
+#define CS_BUSY 0x18
+#define CS_GENERAL_FAILURE 0x19
+#define CS_WRITE_PROTECTED 0x1a
+#define CS_BAD_ARG_LENGTH 0x1b
+#define CS_BAD_ARGS 0x1c
+#define CS_CONFIGURATION_LOCKED 0x1d
+#define CS_IN_USE 0x1e
+#define CS_NO_MORE_ITEMS 0x1f
+#define CS_OUT_OF_RESOURCE 0x20
+#define CS_BAD_HANDLE 0x21
+
+#define CS_BAD_TUPLE 0x40
+
+#ifdef __KERNEL__
+
+/*
+ * Calls to set up low-level "Socket Services" drivers
+ */
+
+typedef int (*ss_entry_t)(u_int sock, u_int cmd, void *arg);
+extern int register_ss_entry(int nsock, ss_entry_t entry);
+extern void unregister_ss_entry(ss_entry_t entry);
+
+/*
+ * The main Card Services entry point
+ */
+
+enum service {
+ AccessConfigurationRegister, AddSocketServices,
+ AdjustResourceInfo, CheckEraseQueue, CloseMemory, CopyMemory,
+ DeregisterClient, DeregisterEraseQueue, GetCardServicesInfo,
+ GetClientInfo, GetConfigurationInfo, GetEventMask,
+ GetFirstClient, GetFirstPartion, GetFirstRegion, GetFirstTuple,
+ GetNextClient, GetNextPartition, GetNextRegion, GetNextTuple,
+ GetStatus, GetTupleData, MapLogSocket, MapLogWindow, MapMemPage,
+ MapPhySocket, MapPhyWindow, ModifyConfiguration, ModifyWindow,
+ OpenMemory, ParseTuple, ReadMemory, RegisterClient,
+ RegisterEraseQueue, RegisterMTD, RegisterTimer,
+ ReleaseConfiguration, ReleaseExclusive, ReleaseIO, ReleaseIRQ,
+ ReleaseSocketMask, ReleaseWindow, ReplaceSocketServices,
+ RequestConfiguration, RequestExclusive, RequestIO, RequestIRQ,
+ RequestSocketMask, RequestWindow, ResetCard, ReturnSSEntry,
+ SetEventMask, SetRegion, ValidateCIS, VendorSpecific,
+ WriteMemory, BindDevice, BindMTD, ReportError,
+ SuspendCard, ResumeCard, EjectCard, InsertCard, ReplaceCIS,
+ GetFirstWindow, GetNextWindow, GetMemPage
+};
+
+#ifdef IN_CARD_SERVICES
+extern int CardServices(int func, void *a1, void *a2, void *a3);
+#else
+extern int CardServices(int func, ...);
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_CS_H */
diff --git a/pcmcia/cs_types.h b/pcmcia/cs_types.h
new file mode 100644
index 0000000..88471f9
--- /dev/null
+++ b/pcmcia/cs_types.h
@@ -0,0 +1,70 @@
+/*
+ * cs_types.h 1.20 2002/04/17 02:52:39
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * 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.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#ifndef _LINUX_CS_TYPES_H
+#define _LINUX_CS_TYPES_H
+
+#ifdef __linux__
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
+#endif
+
+#ifdef __arm__
+typedef u_int ioaddr_t;
+#else
+typedef u_short ioaddr_t;
+#endif
+
+typedef u_short socket_t;
+typedef u_int event_t;
+typedef u_char cisdata_t;
+typedef u_short page_t;
+
+struct client_t;
+typedef struct client_t *client_handle_t;
+
+struct window_t;
+typedef struct window_t *window_handle_t;
+
+struct region_t;
+typedef struct region_t *memory_handle_t;
+
+struct eraseq_t;
+typedef struct eraseq_t *eraseq_handle_t;
+
+#ifndef DEV_NAME_LEN
+#define DEV_NAME_LEN 32
+#endif
+
+typedef char dev_info_t[DEV_NAME_LEN];
+
+#endif /* _LINUX_CS_TYPES_H */
diff --git a/pcmcia/ds.h b/pcmcia/ds.h
new file mode 100644
index 0000000..b372e59
--- /dev/null
+++ b/pcmcia/ds.h
@@ -0,0 +1,148 @@
+/*
+ * ds.h 1.58 2001/10/04 03:15:22
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * 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.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#ifndef _LINUX_DS_H
+#define _LINUX_DS_H
+
+#include <pcmcia/driver_ops.h>
+#include <pcmcia/bulkmem.h>
+
+typedef struct tuple_parse_t {
+ tuple_t tuple;
+ cisdata_t data[255];
+ cisparse_t parse;
+} tuple_parse_t;
+
+typedef struct win_info_t {
+ window_handle_t handle;
+ win_req_t window;
+ memreq_t map;
+} win_info_t;
+
+typedef struct bind_info_t {
+ dev_info_t dev_info;
+ u_char function;
+ struct dev_link_t *instance;
+ char name[DEV_NAME_LEN];
+ u_short major, minor;
+ void *next;
+} bind_info_t;
+
+typedef struct mtd_info_t {
+ dev_info_t dev_info;
+ u_int Attributes;
+ u_int CardOffset;
+} mtd_info_t;
+
+typedef union ds_ioctl_arg_t {
+ servinfo_t servinfo;
+ adjust_t adjust;
+ config_info_t config;
+ tuple_t tuple;
+ tuple_parse_t tuple_parse;
+ client_req_t client_req;
+ cs_status_t status;
+ conf_reg_t conf_reg;
+ cisinfo_t cisinfo;
+ region_info_t region;
+ bind_info_t bind_info;
+ mtd_info_t mtd_info;
+ win_info_t win_info;
+ cisdump_t cisdump;
+} ds_ioctl_arg_t;
+
+#define DS_GET_CARD_SERVICES_INFO _IOR ('d', 1, servinfo_t)
+#define DS_ADJUST_RESOURCE_INFO _IOWR('d', 2, adjust_t)
+#define DS_GET_CONFIGURATION_INFO _IOWR('d', 3, config_info_t)
+#define DS_GET_FIRST_TUPLE _IOWR('d', 4, tuple_t)
+#define DS_GET_NEXT_TUPLE _IOWR('d', 5, tuple_t)
+#define DS_GET_TUPLE_DATA _IOWR('d', 6, tuple_parse_t)
+#define DS_PARSE_TUPLE _IOWR('d', 7, tuple_parse_t)
+#define DS_RESET_CARD _IO ('d', 8)
+#define DS_GET_STATUS _IOWR('d', 9, cs_status_t)
+#define DS_ACCESS_CONFIGURATION_REGISTER _IOWR('d', 10, conf_reg_t)
+#define DS_VALIDATE_CIS _IOR ('d', 11, cisinfo_t)
+#define DS_SUSPEND_CARD _IO ('d', 12)
+#define DS_RESUME_CARD _IO ('d', 13)
+#define DS_EJECT_CARD _IO ('d', 14)
+#define DS_INSERT_CARD _IO ('d', 15)
+#define DS_GET_FIRST_REGION _IOWR('d', 16, region_info_t)
+#define DS_GET_NEXT_REGION _IOWR('d', 17, region_info_t)
+#define DS_REPLACE_CIS _IOWR('d', 18, cisdump_t)
+#define DS_GET_FIRST_WINDOW _IOR ('d', 19, win_info_t)
+#define DS_GET_NEXT_WINDOW _IOWR('d', 20, win_info_t)
+#define DS_GET_MEM_PAGE _IOWR('d', 21, win_info_t)
+
+#define DS_BIND_REQUEST _IOWR('d', 60, bind_info_t)
+#define DS_GET_DEVICE_INFO _IOWR('d', 61, bind_info_t)
+#define DS_GET_NEXT_DEVICE _IOWR('d', 62, bind_info_t)
+#define DS_UNBIND_REQUEST _IOW ('d', 63, bind_info_t)
+#define DS_BIND_MTD _IOWR('d', 64, mtd_info_t)
+
+#ifdef __KERNEL__
+
+typedef struct dev_link_t {
+ dev_node_t *dev;
+ u_int state, open;
+ wait_queue_head_t pending;
+ struct timer_list release;
+ client_handle_t handle;
+ io_req_t io;
+ irq_req_t irq;
+ config_req_t conf;
+ window_handle_t win;
+ void *priv;
+ struct dev_link_t *next;
+} dev_link_t;
+
+/* Flags for device state */
+#define DEV_PRESENT 0x01
+#define DEV_CONFIG 0x02
+#define DEV_STALE_CONFIG 0x04 /* release on close */
+#define DEV_STALE_LINK 0x08 /* detach on release */
+#define DEV_CONFIG_PENDING 0x10
+#define DEV_RELEASE_PENDING 0x20
+#define DEV_SUSPEND 0x40
+#define DEV_BUSY 0x80
+
+#define DEV_OK(l) \
+ ((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT)))
+
+int register_pccard_driver(dev_info_t *dev_info,
+ dev_link_t *(*attach)(void),
+ void (*detach)(dev_link_t *));
+
+int unregister_pccard_driver(dev_info_t *dev_info);
+
+#define register_pcmcia_driver register_pccard_driver
+#define unregister_pcmcia_driver unregister_pccard_driver
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_DS_H */
diff --git a/yacc_cis.y b/yacc_cis.y
new file mode 100644
index 0000000..c6188c5
--- /dev/null
+++ b/yacc_cis.y
@@ -0,0 +1,418 @@
+%{
+/*
+ * yacc_cis.y 1.13 2001/08/24 12:21:41
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * 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.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+
+#include "pack_cis.h"
+
+/* If bison: generate nicer error messages */
+#define YYERROR_VERBOSE 1
+
+extern int current_lineno;
+
+void yyerror(char *msg, ...);
+static tuple_info_t *new_tuple(u_char type, cisparse_t *parse);
+
+%}
+
+%token STRING NUMBER FLOAT VOLTAGE CURRENT SIZE
+%token VERS_1 MANFID FUNCID CONFIG CFTABLE MFC CHECKSUM
+%token POST ROM BASE LAST_INDEX CJEDEC AJEDEC
+%token DEV_INFO ATTR_DEV_INFO NO_INFO
+%token TIME TIMING WAIT READY RESERVED
+%token VNOM VMIN VMAX ISTATIC IAVG IPEAK IDOWN
+%token VCC VPP1 VPP2 IO MEM
+%token DEFAULT BVD WP RDYBSY MWAIT AUDIO READONLY PWRDOWN
+%token BIT8 BIT16 LINES RANGE
+%token IRQ_NO MASK LEVEL PULSE SHARED
+
+%union {
+ char *str;
+ u_long num;
+ float flt;
+ cistpl_power_t pwr;
+ cisparse_t *parse;
+ tuple_info_t *tuple;
+}
+
+%type <str> STRING
+%type <num> NUMBER SIZE VOLTAGE CURRENT TIME
+%type <flt> FLOAT
+%type <pwr> pwr pwrlist
+%type <parse> vers_1 manfid funcid config cftab io mem irq timing
+%type <parse> dev_info attr_dev_info checksum cjedec ajedec
+%type <tuple> tuple chain cis;
+%%
+
+cis: chain
+ { cis_root = $1; }
+ | chain mfc
+ { cis_root = $1; }
+ ;
+
+chain: /* nothing */
+ { $$ = NULL; }
+ | chain tuple
+ {
+ if ($1 == NULL) {
+ $$ = $2;
+ } else if ($2 == NULL) {
+ $$ = $1;
+ } else {
+ tuple_info_t *tail = $1;
+ while (tail->next != NULL) tail = tail->next;
+ tail->next = $2;
+ $$ = $1;
+ }
+ }
+ ;
+
+mfc: MFC '{' chain '}'
+ { mfc[nf++] = $3; }
+ | mfc ',' '{' chain '}'
+ { mfc[nf++] = $4; }
+ ;
+
+tuple: dev_info
+ { $$ = new_tuple(CISTPL_DEVICE, $1); }
+ | attr_dev_info
+ { $$ = new_tuple(CISTPL_DEVICE_A, $1); }
+ | vers_1
+ { $$ = new_tuple(CISTPL_VERS_1, $1); }
+ | manfid
+ { $$ = new_tuple(CISTPL_MANFID, $1); }
+ | funcid
+ { $$ = new_tuple(CISTPL_FUNCID, $1); }
+ | config
+ { $$ = new_tuple(CISTPL_CONFIG, $1); }
+ | cftab
+ { $$ = new_tuple(CISTPL_CFTABLE_ENTRY, $1); }
+ | checksum
+ { $$ = NULL; }
+ | error
+ { $$ = NULL; }
+ | cjedec
+ { $$ = new_tuple(CISTPL_JEDEC_C, $1); }
+ | ajedec
+ { $$ = new_tuple(CISTPL_JEDEC_A, $1); }
+ ;
+
+dev_info: DEV_INFO
+ { $$ = calloc(1, sizeof(cisparse_t)); }
+ | dev_info NUMBER TIME ',' SIZE
+ {
+ $$->device.dev[$$->device.ndev].type = $2;
+ $$->device.dev[$$->device.ndev].speed = $3;
+ $$->device.dev[$$->device.ndev].size = $5;
+ $$->device.ndev++;
+ }
+ | dev_info NO_INFO
+ ;
+
+attr_dev_info: ATTR_DEV_INFO
+ { $$ = calloc(1, sizeof(cisparse_t)); }
+ | attr_dev_info NUMBER TIME ',' SIZE
+ {
+ $$->device.dev[$$->device.ndev].type = $2;
+ $$->device.dev[$$->device.ndev].speed = $3;
+ $$->device.dev[$$->device.ndev].size = $5;
+ $$->device.ndev++;
+ }
+ | attr_dev_info NO_INFO
+ ;
+
+vers_1: VERS_1 FLOAT
+ {
+ $$ = calloc(1, sizeof(cisparse_t));
+ $$->version_1.major = $2;
+ $2 -= floor($2+0.01);
+ while (fabs($2 - floor($2+0.5)) > 0.01) {
+ $2 *= 10;
+ }
+ $$->version_1.minor = $2+0.01;
+ }
+ | vers_1 ',' STRING
+ {
+ cistpl_vers_1_t *v = &$$->version_1;
+ u_int pos = 0;
+ if (v->ns) {
+ pos = v->ofs[v->ns-1];
+ pos += strlen(v->str+pos)+1;
+ }
+ v->ofs[v->ns] = pos;
+ strcpy(v->str+pos, $3);
+ v->ns++;
+ }
+ ;
+
+manfid: MANFID NUMBER ',' NUMBER
+ {
+ $$ = calloc(1, sizeof(cisparse_t));
+ $$->manfid.manf = $2;
+ $$->manfid.card = $4;
+ }
+ ;
+
+funcid: FUNCID NUMBER
+ {
+ $$ = calloc(1, sizeof(cisparse_t));
+ $$->funcid.func = $2;
+ }
+ | funcid POST
+ { $$->funcid.sysinit |= CISTPL_SYSINIT_POST; }
+ | funcid ROM
+ { $$->funcid.sysinit |= CISTPL_SYSINIT_ROM; }
+ ;
+
+cjedec: CJEDEC NUMBER NUMBER
+ {
+ $$ = calloc(1, sizeof(cisparse_t));
+ $$->jedec.id[0].mfr = $2;
+ $$->jedec.id[0].info = $3;
+ $$->jedec.nid = 1;
+ }
+ | cjedec ',' NUMBER NUMBER
+ {
+ $$->jedec.id[$$->jedec.nid].mfr = $3;
+ $$->jedec.id[$$->jedec.nid++].info = $4;
+ }
+ ;
+
+ajedec: AJEDEC NUMBER NUMBER
+ {
+ $$ = calloc(1, sizeof(cisparse_t));
+ $$->jedec.id[0].mfr = $2;
+ $$->jedec.id[0].info = $3;
+ $$->jedec.nid = 1;
+ }
+ | ajedec ',' NUMBER NUMBER
+ {
+ $$->jedec.id[$$->jedec.nid].mfr = $3;
+ $$->jedec.id[$$->jedec.nid++].info = $4;
+ }
+ ;
+
+config: CONFIG BASE NUMBER MASK NUMBER LAST_INDEX NUMBER
+ {
+ $$ = calloc(1, sizeof(cisparse_t));
+ $$->config.base = $3;
+ $$->config.rmask[0] = $5;
+ $$->config.last_idx = $7;
+ }
+ ;
+
+pwr: VNOM VOLTAGE
+ {
+ $$.present = CISTPL_POWER_VNOM;
+ $$.param[0] = $2;
+ }
+ | VMIN VOLTAGE
+ {
+ $$.present = CISTPL_POWER_VMIN;
+ $$.param[0] = $2;
+ }
+ | VMAX VOLTAGE
+ {
+ $$.present = CISTPL_POWER_VMAX;
+ $$.param[0] = $2;
+ }
+ | ISTATIC CURRENT
+ {
+ $$.present = CISTPL_POWER_ISTATIC;
+ $$.param[0] = $2;
+ }
+ | IAVG CURRENT
+ {
+ $$.present = CISTPL_POWER_IAVG;
+ $$.param[0] = $2;
+ }
+ | IPEAK CURRENT
+ {
+ $$.present = CISTPL_POWER_IPEAK;
+ $$.param[0] = $2;
+ }
+ | IDOWN CURRENT
+ {
+ $$.present = CISTPL_POWER_IDOWN;
+ $$.param[0] = $2;
+ }
+ ;
+
+pwrlist: /* nothing */
+ {
+ $$.present = 0;
+ }
+ | pwrlist pwr
+ {
+ $$.present |= 1<<($2.present);
+ $$.param[$2.present] = $2.param[0];
+ }
+ ;
+
+timing: cftab TIMING
+ | timing WAIT TIME
+ | timing READY TIME
+ | timing RESERVED TIME
+ ;
+
+io: cftab IO NUMBER '-' NUMBER
+ {
+ int n = $$->cftable_entry.io.nwin;
+ $$->cftable_entry.io.win[n].base = $3;
+ $$->cftable_entry.io.win[n].len = $5-$3+1;
+ $$->cftable_entry.io.nwin++;
+ }
+ | io ',' NUMBER '-' NUMBER
+ {
+ int n = $$->cftable_entry.io.nwin;
+ $$->cftable_entry.io.win[n].base = $3;
+ $$->cftable_entry.io.win[n].len = $5-$3+1;
+ $$->cftable_entry.io.nwin++;
+ }
+ | io BIT8
+ { $$->cftable_entry.io.flags |= CISTPL_IO_8BIT; }
+ | io BIT16
+ { $$->cftable_entry.io.flags |= CISTPL_IO_16BIT; }
+ | io LINES '=' NUMBER ']'
+ { $$->cftable_entry.io.flags |= $4; }
+ | io RANGE
+ ;
+
+mem: cftab MEM NUMBER '-' NUMBER '@' NUMBER
+ {
+ int n = $$->cftable_entry.mem.nwin;
+ $$->cftable_entry.mem.win[n].card_addr = $3;
+ $$->cftable_entry.mem.win[n].host_addr = $7;
+ $$->cftable_entry.mem.win[n].len = $5-$3+1;
+ $$->cftable_entry.mem.nwin++;
+ }
+ | mem ',' NUMBER '-' NUMBER '@' NUMBER
+ {
+ int n = $$->cftable_entry.mem.nwin;
+ $$->cftable_entry.mem.win[n].card_addr = $3;
+ $$->cftable_entry.mem.win[n].host_addr = $7;
+ $$->cftable_entry.mem.win[n].len = $5-$3+1;
+ $$->cftable_entry.mem.nwin++;
+ }
+ | mem BIT8
+ { $$->cftable_entry.io.flags |= CISTPL_IO_8BIT; }
+ | mem BIT16
+ { $$->cftable_entry.io.flags |= CISTPL_IO_16BIT; }
+ ;
+
+irq: cftab IRQ_NO NUMBER
+ { $$->cftable_entry.irq.IRQInfo1 = ($3 & 0x0f); }
+ | cftab IRQ_NO MASK NUMBER
+ {
+ $$->cftable_entry.irq.IRQInfo1 = IRQ_INFO2_VALID;
+ $$->cftable_entry.irq.IRQInfo2 = $4;
+ }
+ | irq PULSE
+ { $$->cftable_entry.irq.IRQInfo1 |= IRQ_PULSE_ID; }
+ | irq LEVEL
+ { $$->cftable_entry.irq.IRQInfo1 |= IRQ_LEVEL_ID; }
+ | irq SHARED
+ { $$->cftable_entry.irq.IRQInfo1 |= IRQ_SHARE_ID; }
+ ;
+
+cftab: CFTABLE NUMBER
+ {
+ $$ = calloc(1, sizeof(cisparse_t));
+ $$->cftable_entry.index = $2;
+ }
+ | cftab DEFAULT
+ { $$->cftable_entry.flags |= CISTPL_CFTABLE_DEFAULT; }
+ | cftab BVD
+ { $$->cftable_entry.flags |= CISTPL_CFTABLE_BVDS; }
+ | cftab WP
+ { $$->cftable_entry.flags |= CISTPL_CFTABLE_WP; }
+ | cftab RDYBSY
+ { $$->cftable_entry.flags |= CISTPL_CFTABLE_RDYBSY; }
+ | cftab MWAIT
+ { $$->cftable_entry.flags |= CISTPL_CFTABLE_MWAIT; }
+ | cftab AUDIO
+ { $$->cftable_entry.flags |= CISTPL_CFTABLE_AUDIO; }
+ | cftab READONLY
+ { $$->cftable_entry.flags |= CISTPL_CFTABLE_READONLY; }
+ | cftab PWRDOWN
+ { $$->cftable_entry.flags |= CISTPL_CFTABLE_PWRDOWN; }
+ | cftab VCC pwrlist
+ { $$->cftable_entry.vcc = $3; }
+ | cftab VPP1 pwrlist
+ { $$->cftable_entry.vpp1 = $3; }
+ | cftab VPP2 pwrlist
+ { $$->cftable_entry.vpp2 = $3; }
+ | io
+ | mem
+ | irq
+ | timing
+ ;
+
+checksum: CHECKSUM NUMBER '-' NUMBER '=' NUMBER
+ { $$ = NULL; }
+
+%%
+
+static tuple_info_t *new_tuple(u_char type, cisparse_t *parse)
+{
+ tuple_info_t *t = calloc(1, sizeof(tuple_info_t));
+ t->type = type;
+ t->parse = parse;
+ t->next = NULL;
+}
+
+void yyerror(char *msg, ...)
+{
+ va_list ap;
+ char str[256];
+
+ va_start(ap, msg);
+ sprintf(str, "error at line %d: ", current_lineno);
+ vsprintf(str+strlen(str), msg, ap);
+ fprintf(stderr, "%s\n", str);
+ va_end(ap);
+}
+
+#ifdef DEBUG
+void main(int argc, char *argv[])
+{
+ if (argc > 1)
+ parse_cis(argv[1]);
+}
+#endif