diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2011-12-16 06:27:49 +0000 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2011-12-16 06:58:02 +0000 |
commit | 0f881f047e5aeb99a9281c766ad9d58b18a81301 (patch) | |
tree | 60e4a5ae50ee3755552677986f48a88c34d2539e | |
download | cis-tools-0f881f047e5aeb99a9281c766ad9d58b18a81301.tar.gz |
Import CIS tools from pcmcia-cs 3.2.8
-rw-r--r-- | COPYING | 23 | ||||
-rw-r--r-- | LICENSE | 563 | ||||
-rw-r--r-- | cistpl.c | 1502 | ||||
-rw-r--r-- | dump_cis.c | 1102 | ||||
-rw-r--r-- | lex_cis.l | 234 | ||||
-rw-r--r-- | pack_cis.c | 447 | ||||
-rw-r--r-- | pack_cis.h | 38 | ||||
-rw-r--r-- | pcmcia/bulkmem.h | 195 | ||||
-rw-r--r-- | pcmcia/cistpl.h | 604 | ||||
-rw-r--r-- | pcmcia/cs.h | 441 | ||||
-rw-r--r-- | pcmcia/cs_types.h | 70 | ||||
-rw-r--r-- | pcmcia/ds.h | 148 | ||||
-rw-r--r-- | yacc_cis.y | 418 |
13 files changed, 5785 insertions, 0 deletions
@@ -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 @@ -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 |